From 1817fbf1786baa98b87adfe0641fb703e81169d9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sandro=20Knau=C3=9F?= Date: Sat, 5 Apr 2025 20:14:42 +0200 Subject: [PATCH] Import nextcloud-desktop_3.16.2.orig.tar.gz [dgit import orig nextcloud-desktop_3.16.2.orig.tar.gz] --- .clang-format | 88 + .drone.yml | 24 + .git-blame-ignore-revs | 1 + .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 185 + .github/ISSUE_TEMPLATE/config.yml | 12 + .github/ISSUE_TEMPLATE/feature.md | 32 + .github/dependabot.yml | 8 + .github/pull_request_template.md | 14 + .github/workflows/check-translations.yml | 18 + .github/workflows/clang-format.yml | 20 + .github/workflows/clang-tidy-review.yml | 39 + .github/workflows/fixup.yml | 36 + .github/workflows/linux-appimage.yml | 74 + .../workflows/linux-clang-compile-tests.yml | 25 + .github/workflows/linux-gcc-compile-tests.yml | 25 + .github/workflows/macos-build-and-test.yml | 71 + .github/workflows/needsinfo.yml | 24 + .github/workflows/needsinfohelper.yaml | 13 + .github/workflows/qml-label-check.yml | 21 + .github/workflows/sonarcloud.yml | 47 + .github/workflows/stale.yml | 23 + .github/workflows/windows-build-and-test.yml | 91 + .gitmodules | 3 + .swift-format.json | 69 + .tag | 1 + .tx/config | 16 + .tx/nextcloud.client-desktop/ar_translation | 24 + .tx/nextcloud.client-desktop/bg_translation | 27 + .tx/nextcloud.client-desktop/br_translation | 26 + .tx/nextcloud.client-desktop/ca_translation | 27 + .tx/nextcloud.client-desktop/cs_translation | 27 + .../cy_GB_translation | 27 + .tx/nextcloud.client-desktop/da_translation | 27 + .tx/nextcloud.client-desktop/de_translation | 27 + .tx/nextcloud.client-desktop/el_translation | 27 + .../en_GB_translation | 27 + .tx/nextcloud.client-desktop/eo_translation | 26 + .../es_AR_translation | 27 + .../es_CL_translation | 25 + .../es_CO_translation | 25 + .../es_CR_translation | 25 + .../es_DO_translation | 26 + .../es_EC_translation | 25 + .../es_GT_translation | 25 + .../es_MX_translation | 27 + .../es_SV_translation | 25 + .tx/nextcloud.client-desktop/es_translation | 27 + .tx/nextcloud.client-desktop/et_translation | 26 + .tx/nextcloud.client-desktop/eu_translation | 27 + .tx/nextcloud.client-desktop/fa_translation | 24 + .tx/nextcloud.client-desktop/fi_translation | 27 + .tx/nextcloud.client-desktop/fr_translation | 27 + .tx/nextcloud.client-desktop/gl_translation | 26 + .tx/nextcloud.client-desktop/he_translation | 26 + .tx/nextcloud.client-desktop/hr_translation | 27 + .tx/nextcloud.client-desktop/hu_translation | 27 + .tx/nextcloud.client-desktop/id_translation | 24 + .tx/nextcloud.client-desktop/is_translation | 27 + .tx/nextcloud.client-desktop/it_translation | 27 + .tx/nextcloud.client-desktop/ja_translation | 27 + .tx/nextcloud.client-desktop/ko_translation | 27 + .../lt_LT_translation | 26 + .tx/nextcloud.client-desktop/lv_translation | 26 + .tx/nextcloud.client-desktop/mk_translation | 27 + .tx/nextcloud.client-desktop/nb_translation | 27 + .tx/nextcloud.client-desktop/nl_translation | 27 + .tx/nextcloud.client-desktop/oc_translation | 27 + .tx/nextcloud.client-desktop/pl_translation | 27 + .../pt_BR_translation | 27 + .tx/nextcloud.client-desktop/pt_translation | 27 + .tx/nextcloud.client-desktop/ro_translation | 27 + .tx/nextcloud.client-desktop/ru_translation | 27 + .tx/nextcloud.client-desktop/sc_translation | 27 + .tx/nextcloud.client-desktop/sk_translation | 27 + .tx/nextcloud.client-desktop/sl_translation | 27 + .tx/nextcloud.client-desktop/sr_translation | 26 + .tx/nextcloud.client-desktop/sv_translation | 27 + .tx/nextcloud.client-desktop/sw_translation | 26 + .tx/nextcloud.client-desktop/th_translation | 27 + .tx/nextcloud.client-desktop/tr_translation | 27 + .tx/nextcloud.client-desktop/uk_translation | 27 + .tx/nextcloud.client-desktop/vi_translation | 27 + .../zh_CN_translation | 27 + .../zh_HK_translation | 27 + .../zh_TW_translation | 27 + AUTHORS.md | 392 + CHANGELOG.md | 656 ++ CMakeLists.txt | 360 + CONTRIBUTING.md | 41 + COPYING | 339 + COPYING.documentation | 319 + CPackOptions.cmake.in | 21 + ChangeLog - Legacy | 1364 ++++ NEXTCLOUD.cmake | 91 + NextcloudCPack.cmake | 63 + README.md | 107 + VERSION.cmake | 66 + admin/CMakeLists.txt | 7 + admin/linux/build-appimage.sh | 127 + admin/linux/clean_tarball.sh | 8 + admin/linux/debian/drone-build.sh | 159 + admin/linux/debian/oscrc.enc | Bin 0 -> 5472 bytes admin/linux/debian/scripts/git2changelog.cfg | 12 + admin/linux/debian/scripts/git2changelog.py | 188 + admin/linux/debian/signing-key.txt.enc | Bin 0 -> 6672 bytes admin/nix/flake.nix | 143 + admin/osx/CMakeLists.txt | 16 + admin/osx/DMGBackground.png | Bin 0 -> 18463 bytes admin/osx/DS_Store.in | Bin 0 -> 15364 bytes admin/osx/create_mac.sh.cmake | 74 + ...utoupdate_com.owncloud.desktopclient.plist | Bin 0 -> 65 bytes admin/osx/gen_sym_files.py | 77 + admin/osx/installer-background.png | Bin 0 -> 4028 bytes admin/osx/installer-background.svg | 2 + admin/osx/installer-background_2x.png | Bin 0 -> 7190 bytes admin/osx/mac-crafter/Package.swift | 22 + admin/osx/mac-crafter/README.md | 63 + .../mac-crafter/Sources/Utils/Codesign.swift | 193 + .../osx/mac-crafter/Sources/Utils/Craft.swift | 17 + .../mac-crafter/Sources/Utils/Install.swift | 35 + .../mac-crafter/Sources/Utils/Packaging.swift | 122 + .../osx/mac-crafter/Sources/Utils/Shell.swift | 68 + admin/osx/mac-crafter/Sources/main.swift | 342 + admin/osx/macosx.pkgproj.cmake | 892 +++ admin/osx/make_universal.py | 85 + admin/osx/post_install.sh.cmake | 13 + admin/osx/pre_install.sh.cmake | 7 + admin/osx/sign_app.sh | 19 + admin/osx/sign_dmg.sh | 40 + admin/osx/sparkle/dsa_pub.pem | 36 + admin/osx/sparkle/example_update_rss.rss | 21 + admin/test/wait_for_server.sh | 25 + admin/win/CMakeLists.txt | 8 + admin/win/Toolchain-mingw32-openSUSE.cmake | 34 + admin/win/create_stable_toolchain.sh | 30 + admin/win/download_runtimes.sh | 19 + admin/win/msi/CMakeLists.txt | 34 + admin/win/msi/Nextcloud.wxs | 237 + admin/win/msi/OEM.wxi.in | 56 + admin/win/msi/Platform.wxi | 38 + admin/win/msi/RegistryCleanup.vbs.in | 80 + admin/win/msi/RegistryCleanupCustomAction.wxs | 7 + admin/win/msi/collect-transform.xsl.in | 41 + admin/win/msi/gui/banner.bmp | Bin 0 -> 85894 bytes admin/win/msi/gui/banner.svg | 72 + admin/win/msi/gui/dialog.bmp | Bin 0 -> 464774 bytes admin/win/msi/make-msi.bat.in | 26 + admin/win/nsi/.directory | 3 + admin/win/nsi/README.md | 28 + admin/win/nsi/RELEASE_NOTES.txt | 0 admin/win/nsi/installer.ico | Bin 0 -> 276766 bytes admin/win/nsi/l10n/Basque.nsh | 42 + admin/win/nsi/l10n/Catalan.nsh | 42 + admin/win/nsi/l10n/Czech.nsh | 42 + admin/win/nsi/l10n/Dutch.nsh | 42 + admin/win/nsi/l10n/English.nsh | 42 + admin/win/nsi/l10n/Estonian.nsh | 42 + admin/win/nsi/l10n/Farsi.nsh | 42 + admin/win/nsi/l10n/Finnish.nsh | 42 + admin/win/nsi/l10n/French.nsh | 42 + admin/win/nsi/l10n/Galician.nsh | 42 + admin/win/nsi/l10n/German.nsh | 42 + admin/win/nsi/l10n/Greek.nsh | 42 + admin/win/nsi/l10n/Hungarian.nsh | 42 + admin/win/nsi/l10n/Italian.nsh | 42 + admin/win/nsi/l10n/Japanese.nsh | 42 + admin/win/nsi/l10n/Norwegian.nsh | 42 + admin/win/nsi/l10n/Polish.nsh | 42 + admin/win/nsi/l10n/Portuguese.nsh | 42 + admin/win/nsi/l10n/PortugueseBR.nsh | 42 + admin/win/nsi/l10n/Russian.nsh | 42 + admin/win/nsi/l10n/SimpChinese.nsh | 42 + admin/win/nsi/l10n/Slovak.nsh | 42 + admin/win/nsi/l10n/Slovenian.nsh | 42 + admin/win/nsi/l10n/Spanish.nsh | 42 + admin/win/nsi/l10n/SpanishInternational.nsh | 42 + admin/win/nsi/l10n/Swedish.nsh | 42 + admin/win/nsi/l10n/Thai.nsh | 42 + admin/win/nsi/l10n/Turkish.nsh | 42 + admin/win/nsi/l10n/Ukrainian.nsh | 42 + admin/win/nsi/l10n/declarations.nsh | 42 + admin/win/nsi/l10n/languages.nsh | 28 + admin/win/nsi/lib/fileassoc.nsh | 120 + admin/win/nsi/page_header.bmp | Bin 0 -> 25818 bytes admin/win/nsi/qt.conf | 7 + admin/win/nsi/welcome.bmp | Bin 0 -> 154542 bytes admin/win/tools/CMakeLists.txt | 63 + admin/win/tools/NCMsiHelper/CMakeLists.txt | 41 + admin/win/tools/NCMsiHelper/CustomAction.cpp | 118 + admin/win/tools/NCMsiHelper/CustomAction.def | 3 + admin/win/tools/NCMsiHelper/LogResult.cpp | 134 + admin/win/tools/NCMsiHelper/LogResult.h | 48 + admin/win/tools/NCMsiHelper/NCMsiHelper.cpp | 84 + admin/win/tools/NCMsiHelper/NCMsiHelper.h | 99 + admin/win/tools/NCMsiHelper/NCMsiHelper.wxs | 43 + admin/win/tools/NCNavRemove/CMakeLists.txt | 14 + admin/win/tools/NCNavRemove/ConfigIni.cpp | 77 + admin/win/tools/NCNavRemove/ConfigIni.h | 30 + admin/win/tools/NCNavRemove/NavRemove.ini.in | 2 + .../tools/NCNavRemove/NavRemoveConstants.h.in | 9 + .../win/tools/NCNavRemove/dll/CMakeLists.txt | 25 + admin/win/tools/NCNavRemove/dll/NavRemove.cpp | 40 + admin/win/tools/NCNavRemove/dll/NavRemove.h | 32 + admin/win/tools/NCNavRemove/dll/dllmain.cpp | 42 + admin/win/tools/NCNavRemove/dll/exports.def | 2 + .../win/tools/NCNavRemove/exe/CMakeLists.txt | 19 + admin/win/tools/NCNavRemove/exe/main.cpp | 53 + admin/win/tools/NCNavRemove/version.rc.in | 40 + .../tools/NCToolsShared/3rdparty/SimpleIni.h | 3474 ++++++++ admin/win/tools/NCToolsShared/CMakeLists.txt | 4 + .../tools/NCToolsShared/SimpleNamedMutex.cpp | 48 + .../tools/NCToolsShared/SimpleNamedMutex.h | 31 + admin/win/tools/NCToolsShared/utility.h | 58 + admin/win/tools/NCToolsShared/utility_win.cpp | 477 ++ cmake/modules/AddCMockaTest.cmake | 23 + cmake/modules/COPYING-CMAKE-SCRIPTS | 22 + cmake/modules/CheckCCompilerFlagSSP.cmake | 26 + cmake/modules/CheckPrototypeDefinition.c.in | 29 + cmake/modules/CheckPrototypeDefinition.cmake | 98 + cmake/modules/Copyright.txt | 13 + cmake/modules/DBusMacros.cmake | 0 cmake/modules/DefineCMakeDefaults.cmake | 29 + cmake/modules/DefineCompilerFlags.cmake | 96 + cmake/modules/DefineInstallationPaths.cmake | 111 + cmake/modules/DefinePlatformDefaults.cmake | 32 + cmake/modules/DeployQt5.cmake | 381 + cmake/modules/ECMAddAppIcon.cmake | 415 + cmake/modules/ECMCoverageOption.cmake | 29 + cmake/modules/ECMEnableSanitizers.cmake | 169 + cmake/modules/ECMFindModuleHelpers.cmake | 297 + cmake/modules/ECMFindModuleHelpersStub.cmake | 1 + cmake/modules/FindCMocka.cmake | 49 + cmake/modules/FindInotify.cmake | 62 + cmake/modules/FindLibSSH.cmake | 96 + cmake/modules/FindPackageVersionCheck.cmake | 72 + cmake/modules/FindPdfLatex.cmake | 20 + cmake/modules/FindPng2Ico.cmake | 117 + cmake/modules/FindSMBClient.cmake | 66 + cmake/modules/FindSQLite3.cmake | 68 + cmake/modules/FindSharedMimeInfo.cmake | 93 + cmake/modules/FindSparkle.cmake | 21 + cmake/modules/FindSphinx.cmake | 20 + cmake/modules/GenerateIconsUtils.cmake | 58 + cmake/modules/GetGitRevisionDescription.cmake | 116 + .../GetGitRevisionDescription.cmake.in | 38 + cmake/modules/MacOSXBundleInfo.plist.in | 92 + cmake/modules/MacroAddCompileFlags.cmake | 21 + cmake/modules/MacroAddLinkFlags.cmake | 20 + .../modules/MacroEnsureOutOfSourceBuild.cmake | 17 + cmake/modules/MacroLogFeature.cmake | 157 + cmake/modules/MacroOptionalFindPackage.cmake | 47 + cmake/modules/NSIS.InstallOptions.ini.in | 24 + cmake/modules/NSIS.template.in | 881 +++ cmake/modules/UseDoxygen.cmake | 131 + cmake/modules/Warnings.cmake | 30 + cmake/scripts/generate_findpackage_file | 154 + cmake/scripts/generate_lib_file | 135 + codecov.yml | 25 + config.h.in | 74 + craftmaster.ini | 64 + doc/CMakeLists.txt | 93 + doc/Makefile | 169 + doc/README.md | 35 + doc/_shared_assets/static/logo-blue.pdf | Bin 0 -> 8943 bytes doc/_shared_assets/static/logo-blue.png | Bin 0 -> 6607 bytes doc/_shared_assets/static/social/diaspora.svg | 57 + .../static/social/diasporaround.png | Bin 0 -> 2601 bytes doc/_shared_assets/static/social/facebook.png | Bin 0 -> 2493 bytes .../static/social/googleplus.png | Bin 0 -> 4334 bytes doc/_shared_assets/static/social/mail.png | Bin 0 -> 4230 bytes doc/_shared_assets/static/social/mail.svg | 77 + doc/_shared_assets/static/social/rss.png | Bin 0 -> 4400 bytes doc/_shared_assets/static/social/rss.svg | 60 + doc/_shared_assets/static/social/twitter.svg | 1 + .../static/social/twitterround.png | Bin 0 -> 3719 bytes doc/_shared_assets/static/social/youtube.svg | 1 + .../themes/bootstrap/globaltoc.html | 4 + .../themes/bootstrap/layout.html | 134 + .../themes/bootstrap/localtoc.html | 5 + .../themes/bootstrap/relations.html | 8 + .../themes/bootstrap/searchbox.html | 7 + .../themes/bootstrap/sourcelink.html | 4 + .../bootstrap/static/bootstrap-responsive.css | 9 + .../bootstrap/static/bootstrap-sphinx.css_t | 24 + .../themes/bootstrap/static/bootstrap.css | 9 + .../themes/bootstrap/static/bootstrap.js | 6 + .../static/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../static/img/glyphicons-halflings.png | Bin 0 -> 13826 bytes .../themes/bootstrap/static/jquery.js | 4 + .../themes/bootstrap/theme.conf | 5 + .../themes/nextcloud_com/globaltoc.html | 10 + .../themes/nextcloud_com/layout.html | 258 + .../themes/nextcloud_com/localtoc.html | 1 + .../themes/nextcloud_com/navbar-2.html | 51 + .../themes/nextcloud_com/navbar.html | 50 + .../themes/nextcloud_com/navbarsearchbox.html | 9 + .../themes/nextcloud_com/navbartoc.html | 10 + .../themes/nextcloud_com/relations.html | 23 + .../themes/nextcloud_com/search.html | 71 + .../themes/nextcloud_com/searchbox.html | 9 + .../themes/nextcloud_com/searchresults.html | 38 + .../themes/nextcloud_com/sourcelink.html | 6 + .../bootstrap-3.1.0/css/bootstrap-theme.css | 347 + .../css/bootstrap-theme.css.map | 1 + .../css/bootstrap-theme.min.css | 7 + .../static/bootstrap-3.1.0/css/bootstrap.css | 5831 ++++++++++++++ .../bootstrap-3.1.0/css/bootstrap.css.map | 1 + .../bootstrap-3.1.0/css/bootstrap.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes .../static/bootstrap-3.1.0/js/bootstrap.js | 1951 +++++ .../bootstrap-3.1.0/js/bootstrap.min.js | 6 + .../static/bootstrap-sphinx.css_t | 239 + .../static/bootstrap-sphinx.js_t | 173 + .../static/fonts/OpenSans-Bold.ttf | Bin 0 -> 224592 bytes .../static/fonts/OpenSans-Bold.woff | Bin 0 -> 21272 bytes .../static/fonts/OpenSans-Italic.ttf | Bin 0 -> 212896 bytes .../static/fonts/OpenSans-Italic.woff | Bin 0 -> 23188 bytes .../static/fonts/OpenSans-Light.ttf | Bin 0 -> 222412 bytes .../static/fonts/OpenSans-Light.woff | Bin 0 -> 62844 bytes .../static/fonts/OpenSans-Regular.ttf | Bin 0 -> 217360 bytes .../static/fonts/OpenSans-Regular.woff | Bin 0 -> 20544 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../static/fonts/fontawesome-webfont.svg | 504 ++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes .../static/img/home/background3.jpg | Bin 0 -> 95212 bytes .../themes/nextcloud_com/static/img/logo.svg | 107 + .../nextcloud_com/static/img/note_pencil.svg | 10 + .../static/img/social/diaspora.png | Bin 0 -> 792 bytes .../static/img/social/diaspora.svg | 57 + .../static/img/social/diasporaround.png | Bin 0 -> 2601 bytes .../static/img/social/facebook.png | Bin 0 -> 2493 bytes .../static/img/social/facebook.svg | 1 + .../static/img/social/googleplus.png | Bin 0 -> 4334 bytes .../static/img/social/googleplus.svg | 1 + .../nextcloud_com/static/img/social/mail.svg | 77 + .../nextcloud_com/static/img/social/rss.png | Bin 0 -> 4400 bytes .../nextcloud_com/static/img/social/rss.svg | 60 + .../static/img/social/twitter.png | Bin 0 -> 1885 bytes .../static/img/social/twitter.svg | 1 + .../static/img/social/twitterround.png | Bin 0 -> 3719 bytes .../static/img/social/youtube.svg | 1 + .../nextcloud_com/static/img/warning.svg | 8 + .../static/js/jquery-1.11.0.min.js | 4 + .../nextcloud_com/static/js/jquery-fix.js | 2 + .../themes/nextcloud_com/static/main.min.css | 6 + .../themes/nextcloud_com/static/styles.css | 1299 +++ .../themes/nextcloud_com/theme.conf | 60 + .../themes/nextcloud_release/globaltoc.html | 10 + .../themes/nextcloud_release/layout.html | 142 + .../themes/nextcloud_release/localtoc.html | 1 + .../themes/nextcloud_release/navbar-2.html | 51 + .../themes/nextcloud_release/navbar.html | 50 + .../nextcloud_release/navbarsearchbox.html | 9 + .../themes/nextcloud_release/navbartoc.html | 10 + .../themes/nextcloud_release/relations.html | 23 + .../themes/nextcloud_release/search.html | 71 + .../themes/nextcloud_release/searchbox.html | 9 + .../nextcloud_release/searchresults.html | 38 + .../themes/nextcloud_release/sourcelink.html | 6 + .../bootstrap-3.1.0/css/bootstrap-theme.css | 347 + .../css/bootstrap-theme.css.map | 1 + .../css/bootstrap-theme.min.css | 7 + .../static/bootstrap-3.1.0/css/bootstrap.css | 5831 ++++++++++++++ .../bootstrap-3.1.0/css/bootstrap.css.map | 1 + .../bootstrap-3.1.0/css/bootstrap.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes .../static/bootstrap-3.1.0/js/bootstrap.js | 1951 +++++ .../bootstrap-3.1.0/js/bootstrap.min.js | 6 + .../static/bootstrap-responsive.css | 9 + .../static/bootstrap-sphinx.css_t | 239 + .../static/bootstrap-sphinx.js_t | 173 + .../nextcloud_release/static/bootstrap.css | 9 + .../nextcloud_release/static/bootstrap.js | 6 + .../static/fonts/OpenSans-Bold.ttf | Bin 0 -> 224592 bytes .../static/fonts/OpenSans-Bold.woff | Bin 0 -> 21272 bytes .../static/fonts/OpenSans-Italic.ttf | Bin 0 -> 212896 bytes .../static/fonts/OpenSans-Italic.woff | Bin 0 -> 23188 bytes .../static/fonts/OpenSans-Light.ttf | Bin 0 -> 222412 bytes .../static/fonts/OpenSans-Light.woff | Bin 0 -> 62844 bytes .../static/fonts/OpenSans-Regular.ttf | Bin 0 -> 217360 bytes .../static/fonts/OpenSans-Regular.woff | Bin 0 -> 20544 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../static/fonts/fontawesome-webfont.svg | 504 ++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes .../static/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../static/img/glyphicons-halflings.png | Bin 0 -> 13826 bytes .../nextcloud_release/static/img/note.svg | 103 + .../static/img/note_pencil.svg | 10 + .../static/img/social/diaspora.png | Bin 0 -> 792 bytes .../static/img/social/diaspora.svg | 57 + .../static/img/social/diasporaround.png | Bin 0 -> 2601 bytes .../static/img/social/facebook.png | Bin 0 -> 2493 bytes .../static/img/social/facebook.svg | 1 + .../static/img/social/googleplus.png | Bin 0 -> 4334 bytes .../static/img/social/googleplus.svg | 1 + .../static/img/social/mail.svg | 80 + .../static/img/social/rss.png | Bin 0 -> 4400 bytes .../static/img/social/rss.svg | 60 + .../static/img/social/twitter.png | Bin 0 -> 1885 bytes .../static/img/social/twitter.svg | 1 + .../static/img/social/twitterround.png | Bin 0 -> 3719 bytes .../static/img/social/youtube.svg | 1 + .../nextcloud_release/static/img/todo.svg | 114 + .../nextcloud_release/static/img/warning.svg | 8 + .../themes/nextcloud_release/static/jquery.js | 4 + .../static/js/jquery-1.11.0.min.js | 4 + .../nextcloud_release/static/js/jquery-fix.js | 2 + .../nextcloud_release/static/main.min.css | 6 + .../nextcloud_release/static/styles.css | 498 ++ .../themes/nextcloud_release/theme.conf | 60 + doc/advancedusage.rst | 40 + doc/architecture.rst | 462 ++ doc/autoupdate.rst | 116 + doc/building.rst | 445 ++ doc/conf.py | 292 + doc/conffile.rst | 84 + doc/conflicts.rst | 61 + doc/dev/CMakeLists.txt | 11 + doc/dev/Doxyfile.in | 2307 ++++++ doc/dev/main-page.md | 5 + doc/dev/sync-algorithm.md | 84 + doc/envvars.rst | 11 + doc/faq.rst | 114 + doc/glossary.rst | 28 + doc/images/checksums/client-activity.png | Bin 0 -> 34786 bytes doc/images/checksums/testing-checksums.png | Bin 0 -> 68756 bytes doc/images/create_debug_archive.png | Bin 0 -> 20110 bytes .../dev/desktop-development-with-cpp.png | Bin 0 -> 10770 bytes doc/images/dev/path.png | Bin 0 -> 15062 bytes doc/images/dev/visual-studio-installer.png | Bin 0 -> 16502 bytes doc/images/folderwizard_local.png | Bin 0 -> 46414 bytes doc/images/folderwizard_remote.png | Bin 0 -> 48409 bytes .../general_settings_folder_context_menu.png | Bin 0 -> 7135 bytes doc/images/icon-error.png | Bin 0 -> 1158 bytes doc/images/icon-information.png | Bin 0 -> 1141 bytes doc/images/icon-offline.png | Bin 0 -> 997 bytes doc/images/icon-paused.png | Bin 0 -> 980 bytes doc/images/icon-syncing.png | Bin 0 -> 1818 bytes doc/images/icon.png | Bin 0 -> 1219 bytes doc/images/ignored_files_editor.png | Bin 0 -> 43757 bytes doc/images/log_output_window.png | Bin 0 -> 68429 bytes doc/images/mac-share.png | Bin 0 -> 229153 bytes doc/images/macosvfs-file-locking.png | Bin 0 -> 584668 bytes doc/images/macosvfs-file-sharing.png | Bin 0 -> 266804 bytes doc/images/macosvfs-finder-sidebar.png | Bin 0 -> 164291 bytes doc/images/macosvfs-settings.png | Bin 0 -> 440571 bytes doc/images/macosvfs-sync-status-icons.png | Bin 0 -> 231653 bytes doc/images/main_dialog.png | Bin 0 -> 21217 bytes doc/images/main_dialog_christine.png | Bin 0 -> 193044 bytes doc/images/open-share-dialog.png | Bin 0 -> 14811 bytes doc/images/save_log_file.png | Bin 0 -> 63204 bytes doc/images/set-user-status-menu.png | Bin 0 -> 45377 bytes doc/images/set-user-status.png | Bin 0 -> 10191 bytes doc/images/settings_general.png | Bin 0 -> 31702 bytes doc/images/settings_network.png | Bin 0 -> 26063 bytes doc/images/settingsdialog.png | Bin 0 -> 36266 bytes doc/images/setup/confirm.png | Bin 0 -> 23455 bytes doc/images/setup/remove.png | Bin 0 -> 52363 bytes doc/images/setup/wizard.png | Bin 0 -> 57531 bytes doc/images/share-dialog-view-profile.png | Bin 0 -> 32996 bytes doc/images/share_context_menu.png | Bin 0 -> 30215 bytes doc/images/share_dialog.png | Bin 0 -> 13426 bytes doc/images/status_feature_example.png | Bin 0 -> 30368 bytes doc/images/sync-state-paused.png | Bin 0 -> 31270 bytes doc/images/sync-state-synced.png | Bin 0 -> 26297 bytes doc/images/sync-state-syncing.png | Bin 0 -> 31791 bytes doc/images/sync-state-warnings.png | Bin 0 -> 35365 bytes doc/images/traymenu.png | Bin 0 -> 6763 bytes doc/images/unified-search-events.png | Bin 0 -> 12052 bytes doc/images/unified-search-files.png | Bin 0 -> 9975 bytes doc/images/unified-search-talk.png | Bin 0 -> 14738 bytes doc/images/user-account-options.png | Bin 0 -> 13894 bytes doc/images/user_status-selector_dialog.png | Bin 0 -> 18089 bytes .../user_status_selector_main_dialog.png | Bin 0 -> 45723 bytes doc/images/vfs_context_menu_options.png | Bin 0 -> 262650 bytes doc/images/vfs_hydration_progress_bar.png | Bin 0 -> 421607 bytes doc/images/wizard_advanced.png | Bin 0 -> 22006 bytes doc/images/wizard_flow2.png | Bin 0 -> 12134 bytes doc/images/wizard_setup.png | Bin 0 -> 15764 bytes doc/images/wizard_welcome.png | Bin 0 -> 16297 bytes doc/index.rst | 22 + doc/installing.rst | 220 + doc/introduction.rst | 25 + doc/logo-blue.pdf | Bin 0 -> 1851 bytes doc/lowdiskspace.rst | 5 + doc/macosvfs.rst | 136 + doc/massdeploymentcommandline.rst | 30 + doc/navigating.rst | 292 + doc/nextcloudcmd.rst | 102 + doc/options-cmd.rst | 35 + doc/options.rst | 34 + doc/scripts/README.rst | 15 + doc/scripts/htmlhelp.reg | 12 + doc/scripts/htmlhelp.sh | 41 + doc/troubleshooting.rst | 323 + doc/visualtour.rst | 303 + doc/wizardaccountsetupcommandline.rst | 16 + man/CMakeLists.txt | 14 + man/index.rst | 1 + man/nextcloud.1.rst | 32 + man/nextcloudcmd.1.rst | 60 + mirall.desktop.in | 206 + nextcloud.client-desktop/ar_translation | 24 + .../ar_translation.desktop | 28 + .../ast_translation.desktop | 25 + nextcloud.client-desktop/bg_translation | 27 + .../bg_translation.desktop | 28 + nextcloud.client-desktop/br_translation | 26 + .../br_translation.desktop | 27 + nextcloud.client-desktop/ca_translation | 27 + .../ca_translation.desktop | 28 + nextcloud.client-desktop/cs_translation | 27 + .../cs_translation.desktop | 28 + nextcloud.client-desktop/cy_GB_translation | 27 + .../cy_GB_translation.desktop | 28 + nextcloud.client-desktop/da_translation | 27 + .../da_translation.desktop | 28 + nextcloud.client-desktop/de_translation | 27 + .../de_translation.desktop | 28 + nextcloud.client-desktop/el_translation | 27 + .../el_translation.desktop | 28 + nextcloud.client-desktop/en_GB_translation | 27 + .../en_GB_translation.desktop | 28 + nextcloud.client-desktop/eo_translation | 27 + .../eo_translation.desktop | 28 + nextcloud.client-desktop/es_AR_translation | 27 + .../es_AR_translation.desktop | 28 + nextcloud.client-desktop/es_CL_translation | 25 + .../es_CL_translation.desktop | 26 + nextcloud.client-desktop/es_CO_translation | 25 + .../es_CO_translation.desktop | 26 + nextcloud.client-desktop/es_CR_translation | 25 + .../es_CR_translation.desktop | 26 + nextcloud.client-desktop/es_DO_translation | 26 + .../es_DO_translation.desktop | 27 + nextcloud.client-desktop/es_EC_translation | 25 + .../es_EC_translation.desktop | 28 + nextcloud.client-desktop/es_GT_translation | 25 + .../es_GT_translation.desktop | 26 + nextcloud.client-desktop/es_MX_translation | 27 + .../es_MX_translation.desktop | 28 + nextcloud.client-desktop/es_SV_translation | 25 + .../es_SV_translation.desktop | 26 + nextcloud.client-desktop/es_translation | 27 + .../es_translation.desktop | 28 + nextcloud.client-desktop/et_translation | 26 + .../et_translation.desktop | 28 + nextcloud.client-desktop/eu_translation | 27 + .../eu_translation.desktop | 28 + nextcloud.client-desktop/fa_translation | 24 + .../fa_translation.desktop | 28 + nextcloud.client-desktop/fi_translation | 27 + .../fi_translation.desktop | 28 + nextcloud.client-desktop/fr_translation | 27 + .../fr_translation.desktop | 28 + .../ga_translation.desktop | 28 + nextcloud.client-desktop/gl_translation | 27 + .../gl_translation.desktop | 28 + nextcloud.client-desktop/he_translation | 27 + .../he_translation.desktop | 28 + nextcloud.client-desktop/hr_translation | 27 + .../hr_translation.desktop | 28 + nextcloud.client-desktop/hu_translation | 27 + .../hu_translation.desktop | 28 + nextcloud.client-desktop/id_translation | 24 + .../id_translation.desktop | 25 + nextcloud.client-desktop/is_translation | 27 + .../is_translation.desktop | 28 + nextcloud.client-desktop/it_translation | 27 + .../it_translation.desktop | 28 + nextcloud.client-desktop/ja_translation | 27 + .../ja_translation.desktop | 28 + .../kab_translation.desktop | 28 + nextcloud.client-desktop/ko_translation | 27 + .../ko_translation.desktop | 28 + nextcloud.client-desktop/lt_LT_translation | 26 + .../lt_LT_translation.desktop | 27 + nextcloud.client-desktop/lv_translation | 26 + .../lv_translation.desktop | 27 + nextcloud.client-desktop/mk_translation | 27 + .../mk_translation.desktop | 28 + nextcloud.client-desktop/nb_translation | 27 + .../nb_translation.desktop | 28 + nextcloud.client-desktop/nl_translation | 27 + .../nl_translation.desktop | 28 + nextcloud.client-desktop/oc_translation | 27 + .../oc_translation.desktop | 28 + nextcloud.client-desktop/pl_translation | 27 + .../pl_translation.desktop | 28 + nextcloud.client-desktop/pt_BR_translation | 27 + .../pt_BR_translation.desktop | 28 + nextcloud.client-desktop/pt_translation | 27 + .../pt_translation.desktop | 28 + nextcloud.client-desktop/ro_translation | 27 + .../ro_translation.desktop | 28 + nextcloud.client-desktop/ru_translation | 27 + .../ru_translation.desktop | 28 + nextcloud.client-desktop/sc_translation | 27 + .../sc_translation.desktop | 28 + nextcloud.client-desktop/sk_translation | 27 + .../sk_translation.desktop | 28 + nextcloud.client-desktop/sl_translation | 27 + .../sl_translation.desktop | 28 + nextcloud.client-desktop/sr_translation | 26 + .../sr_translation.desktop | 28 + nextcloud.client-desktop/sv_translation | 27 + .../sv_translation.desktop | 28 + nextcloud.client-desktop/sw_translation | 26 + .../sw_translation.desktop | 27 + nextcloud.client-desktop/th_translation | 27 + .../th_translation.desktop | 28 + nextcloud.client-desktop/tr_translation | 27 + .../tr_translation.desktop | 28 + nextcloud.client-desktop/uk_translation | 27 + .../uk_translation.desktop | 28 + nextcloud.client-desktop/vi_translation | 27 + .../vi_translation.desktop | 28 + nextcloud.client-desktop/zh_CN_translation | 27 + .../zh_CN_translation.desktop | 28 + nextcloud.client-desktop/zh_HK_translation | 27 + .../zh_HK_translation.desktop | 28 + nextcloud.client-desktop/zh_TW_translation | 27 + .../zh_TW_translation.desktop | 28 + resources.qrc | 70 + shell_integration/CMakeLists.txt | 30 + shell_integration/MacOSX/CMakeLists.txt | 78 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/OwnCloud.xccheckout | 41 + .../Extensions/Logger+Extensions.swift | 47 + .../FileProviderExt/FileProviderConfig.swift | 40 + .../FileProviderExt-Bridging-Header.h | 20 + .../FileProviderExt.entitlements | 16 + ...ileProviderExtension+ClientInterface.swift | 204 + ...roviderExtension+EnumerationListener.swift | 23 + .../FileProviderExtension+Thumbnailing.swift | 46 + .../FileProviderExtension.swift | 438 + ...viderMaterialisedEnumerationObserver.swift | 88 + .../FileProviderSocketLineProcessor.swift | 59 + .../FileProviderExt/Info.plist | 27 + .../Services/ClientCommunicationProtocol.h | 34 + .../Services/ClientCommunicationService.swift | 107 + .../Services/FPUIExtensionService.swift | 18 + .../Services/FPUIExtensionServiceSource.swift | 65 + .../DocumentActionViewController.swift | 61 + .../Extensions/Logger+Extensions.swift | 23 + .../Extensions/NKShare+Extensions.swift | 138 + .../FileProviderCommunication.swift | 31 + .../FileProviderUIExt.entitlements | 16 + .../FileProviderUIExt/Info.plist | 46 + .../Locking/LockViewController.swift | 259 + .../Locking/LockViewController.xib | 126 + .../FileProviderUIExt/MetadataProvider.swift | 54 + .../Sharing/ShareController.swift | 163 + .../Sharing/ShareOptionsView.swift | 357 + .../Sharing/ShareTableItemView.swift | 66 + .../Sharing/ShareTableItemView.xib | 95 + .../Sharing/ShareTableViewDataSource.swift | 235 + .../Sharing/ShareViewController.swift | 194 + .../Sharing/ShareViewController.xib | 532 ++ .../ShareViewDataSourceUIDelegate.swift | 17 + .../Sharing/ShareeSuggestionsDataSource.swift | 64 + .../FinderSyncExt/FinderSync.h | 28 + .../FinderSyncExt/FinderSync.m | 259 + .../FinderSyncExt/FinderSyncExt.entitlements | 12 + .../FinderSyncSocketLineProcessor.h | 35 + .../FinderSyncSocketLineProcessor.m | 102 + .../FinderSyncExt/Info.plist | 43 + .../FinderSyncExt/SyncClient.h | 27 + .../NCDesktopClientSocketKit/LineProcessor.h | 24 + .../LocalSocketClient.h | 56 + .../LocalSocketClient.m | 367 + .../NCDesktopClientSocketKit.h | 19 + .../project.pbxproj | 1573 ++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/FinderSyncExt.xcscheme | 117 + .../desktopclient/Info.plist | 30 + .../NextcloudIntegration/desktopclient/main.m | 16 + shell_integration/dolphin/CMakeLists.txt | 60 + shell_integration/dolphin/README | 11 + .../dolphin/ownclouddolphinactionplugin.cpp | 137 + .../ownclouddolphinactionplugin.json.in | 13 + .../dolphin/ownclouddolphinoverlayplugin.cpp | 105 + .../dolphin/ownclouddolphinoverlayplugin.json | 8 + .../dolphin/ownclouddolphinpluginhelper.cpp | 117 + .../dolphin/ownclouddolphinpluginhelper.h | 73 + .../icons/1024x1024/oC_error.png | Bin 0 -> 19432 bytes .../icons/1024x1024/oC_error_shared.png | Bin 0 -> 29804 bytes shell_integration/icons/1024x1024/oC_ok.png | Bin 0 -> 21912 bytes .../icons/1024x1024/oC_ok_shared.png | Bin 0 -> 32098 bytes shell_integration/icons/1024x1024/oC_sync.png | Bin 0 -> 24301 bytes .../icons/1024x1024/oC_sync_shared.png | Bin 0 -> 34594 bytes shell_integration/icons/1024x1024/oC_warn.png | Bin 0 -> 19847 bytes .../icons/1024x1024/oC_warn_shared.png | Bin 0 -> 30250 bytes shell_integration/icons/128x128/oC_error.png | Bin 0 -> 1899 bytes .../icons/128x128/oC_error_shared.png | Bin 0 -> 3004 bytes shell_integration/icons/128x128/oC_ok.png | Bin 0 -> 2052 bytes .../icons/128x128/oC_ok_shared.png | Bin 0 -> 3176 bytes shell_integration/icons/128x128/oC_sync.png | Bin 0 -> 2422 bytes .../icons/128x128/oC_sync_shared.png | Bin 0 -> 3585 bytes shell_integration/icons/128x128/oC_warn.png | Bin 0 -> 1849 bytes .../icons/128x128/oC_warn_shared.png | Bin 0 -> 3040 bytes shell_integration/icons/16x16/oC_error.png | Bin 0 -> 1388 bytes .../icons/16x16/oC_error_shared.png | Bin 0 -> 1494 bytes shell_integration/icons/16x16/oC_ok.png | Bin 0 -> 1392 bytes .../icons/16x16/oC_ok_shared.png | Bin 0 -> 1483 bytes shell_integration/icons/16x16/oC_sync.png | Bin 0 -> 1391 bytes .../icons/16x16/oC_sync_shared.png | Bin 0 -> 1495 bytes shell_integration/icons/16x16/oC_warn.png | Bin 0 -> 1389 bytes .../icons/16x16/oC_warn_shared.png | Bin 0 -> 1484 bytes shell_integration/icons/256x256/oC_error.png | Bin 0 -> 4067 bytes .../icons/256x256/oC_error_shared.png | Bin 0 -> 6409 bytes shell_integration/icons/256x256/oC_ok.png | Bin 0 -> 4384 bytes .../icons/256x256/oC_ok_shared.png | Bin 0 -> 6777 bytes shell_integration/icons/256x256/oC_sync.png | Bin 0 -> 5137 bytes .../icons/256x256/oC_sync_shared.png | Bin 0 -> 7437 bytes shell_integration/icons/256x256/oC_warn.png | Bin 0 -> 4070 bytes .../icons/256x256/oC_warn_shared.png | Bin 0 -> 6435 bytes shell_integration/icons/32x32/oC_error.png | Bin 0 -> 1816 bytes .../icons/32x32/oC_error_shared.png | Bin 0 -> 2541 bytes shell_integration/icons/32x32/oC_ok.png | Bin 0 -> 1825 bytes .../icons/32x32/oC_ok_shared.png | Bin 0 -> 2543 bytes shell_integration/icons/32x32/oC_sync.png | Bin 0 -> 1884 bytes .../icons/32x32/oC_sync_shared.png | Bin 0 -> 2592 bytes shell_integration/icons/32x32/oC_warn.png | Bin 0 -> 1800 bytes .../icons/32x32/oC_warn_shared.png | Bin 0 -> 2498 bytes shell_integration/icons/48x48/oC_error.png | Bin 0 -> 2236 bytes .../icons/48x48/oC_error_shared.png | Bin 0 -> 3215 bytes shell_integration/icons/48x48/oC_ok.png | Bin 0 -> 2204 bytes .../icons/48x48/oC_ok_shared.png | Bin 0 -> 3167 bytes shell_integration/icons/48x48/oC_sync.png | Bin 0 -> 2335 bytes .../icons/48x48/oC_sync_shared.png | Bin 0 -> 3342 bytes shell_integration/icons/48x48/oC_warn.png | Bin 0 -> 2190 bytes .../icons/48x48/oC_warn_shared.png | Bin 0 -> 3191 bytes shell_integration/icons/512x512/oC_error.png | Bin 0 -> 8819 bytes .../icons/512x512/oC_error_shared.png | Bin 0 -> 14165 bytes shell_integration/icons/512x512/oC_ok.png | Bin 0 -> 9584 bytes .../icons/512x512/oC_ok_shared.png | Bin 0 -> 14521 bytes shell_integration/icons/512x512/oC_sync.png | Bin 0 -> 11128 bytes .../icons/512x512/oC_sync_shared.png | Bin 0 -> 16318 bytes shell_integration/icons/512x512/oC_warn.png | Bin 0 -> 8862 bytes .../icons/512x512/oC_warn_shared.png | Bin 0 -> 14046 bytes shell_integration/icons/64x64/oC_error.png | Bin 0 -> 2558 bytes .../icons/64x64/oC_error_shared.png | Bin 0 -> 3957 bytes shell_integration/icons/64x64/oC_ok.png | Bin 0 -> 2659 bytes .../icons/64x64/oC_ok_shared.png | Bin 0 -> 3871 bytes shell_integration/icons/64x64/oC_sync.png | Bin 0 -> 2764 bytes .../icons/64x64/oC_sync_shared.png | Bin 0 -> 4043 bytes shell_integration/icons/64x64/oC_warn.png | Bin 0 -> 2687 bytes .../icons/64x64/oC_warn_shared.png | Bin 0 -> 3929 bytes shell_integration/icons/72x72/oC_error.png | Bin 0 -> 2939 bytes .../icons/72x72/oC_error_shared.png | Bin 0 -> 4292 bytes shell_integration/icons/72x72/oC_ok.png | Bin 0 -> 2818 bytes .../icons/72x72/oC_ok_shared.png | Bin 0 -> 4216 bytes shell_integration/icons/72x72/oC_sync.png | Bin 0 -> 3157 bytes .../icons/72x72/oC_sync_shared.png | Bin 0 -> 4570 bytes shell_integration/icons/72x72/oC_warn.png | Bin 0 -> 2871 bytes .../icons/72x72/oC_warn_shared.png | Bin 0 -> 4282 bytes shell_integration/icons/CMakeLists.txt | 15 + shell_integration/icons/SVG/Error.svg | 3824 +++++++++ shell_integration/icons/SVG/Error_Shared.svg | 4769 +++++++++++ shell_integration/icons/SVG/OK.svg | 3781 +++++++++ shell_integration/icons/SVG/OK_Shared.svg | 4711 +++++++++++ shell_integration/icons/SVG/Sync.svg | 3837 +++++++++ shell_integration/icons/SVG/Sync_Shared.svg | 4802 +++++++++++ shell_integration/icons/SVG/Warning.svg | 3787 +++++++++ .../icons/SVG/Warning_Shared.svg | 4730 +++++++++++ .../icons/Sidebar/sidebar_icon_osx_18.png | Bin 0 -> 1419 bytes .../Sidebar/sidebar_icon_osx_hover_18.png | Bin 0 -> 1371 bytes .../icons/Sidebar/sidebar_icon_win_18.png | Bin 0 -> 1396 bytes .../Sidebar/sidebar_icon_win_hover_18.png | Bin 0 -> 1228 bytes shell_integration/icons/icns/error.icns | Bin 0 -> 58407 bytes shell_integration/icons/icns/error_swm.icns | Bin 0 -> 87687 bytes shell_integration/icons/icns/ok.icns | Bin 0 -> 57059 bytes shell_integration/icons/icns/ok_swm.icns | Bin 0 -> 86112 bytes shell_integration/icons/icns/sync.icns | Bin 0 -> 63480 bytes shell_integration/icons/icns/sync_swm.icns | Bin 0 -> 91991 bytes shell_integration/icons/icns/warning.icns | Bin 0 -> 58209 bytes shell_integration/icons/icns/warning_swm.icns | Bin 0 -> 86541 bytes .../icons/nopadding/SVG/attention.svg | 40 + .../icons/nopadding/SVG/error.svg | 39 + .../nopadding/SVG/generate_windows_ico.sh | 8 + shell_integration/icons/nopadding/SVG/ok.svg | 36 + .../icons/nopadding/SVG/shared.svg | 47 + .../icons/nopadding/SVG/sync.svg | 48 + .../nopadding/error.iconset/icon_128x128.png | Bin 0 -> 5541 bytes .../error.iconset/icon_128x128@2x.png | Bin 0 -> 11767 bytes .../nopadding/error.iconset/icon_16x16.png | Bin 0 -> 603 bytes .../nopadding/error.iconset/icon_16x16@2x.png | Bin 0 -> 1257 bytes .../nopadding/error.iconset/icon_256x256.png | Bin 0 -> 11689 bytes .../error.iconset/icon_256x256@2x.png | Bin 0 -> 25593 bytes .../nopadding/error.iconset/icon_32x32.png | Bin 0 -> 1255 bytes .../nopadding/error.iconset/icon_32x32@2x.png | Bin 0 -> 2506 bytes .../nopadding/ok.iconset/icon_128x128.png | Bin 0 -> 6666 bytes .../nopadding/ok.iconset/icon_128x128@2x.png | Bin 0 -> 14441 bytes .../icons/nopadding/ok.iconset/icon_16x16.png | Bin 0 -> 615 bytes .../nopadding/ok.iconset/icon_16x16@2x.png | Bin 0 -> 1243 bytes .../nopadding/ok.iconset/icon_256x256.png | Bin 0 -> 14634 bytes .../nopadding/ok.iconset/icon_256x256@2x.png | Bin 0 -> 31427 bytes .../icons/nopadding/ok.iconset/icon_32x32.png | Bin 0 -> 1243 bytes .../nopadding/ok.iconset/icon_32x32@2x.png | Bin 0 -> 2722 bytes .../nopadding/ok_swm.iconset/icon_128x128.png | Bin 0 -> 7492 bytes .../ok_swm.iconset/icon_128x128@2x.png | Bin 0 -> 16248 bytes .../nopadding/ok_swm.iconset/icon_16x16.png | Bin 0 -> 647 bytes .../ok_swm.iconset/icon_16x16@2x.png | Bin 0 -> 1452 bytes .../nopadding/ok_swm.iconset/icon_256x256.png | Bin 0 -> 16286 bytes .../ok_swm.iconset/icon_256x256@2x.png | Bin 0 -> 35262 bytes .../nopadding/ok_swm.iconset/icon_32x32.png | Bin 0 -> 1462 bytes .../ok_swm.iconset/icon_32x32@2x.png | Bin 0 -> 3267 bytes .../nopadding/sync.iconset/icon_128x128.png | Bin 0 -> 7701 bytes .../sync.iconset/icon_128x128@2x.png | Bin 0 -> 16662 bytes .../nopadding/sync.iconset/icon_16x16.png | Bin 0 -> 694 bytes .../nopadding/sync.iconset/icon_16x16@2x.png | Bin 0 -> 1522 bytes .../nopadding/sync.iconset/icon_256x256.png | Bin 0 -> 16662 bytes .../sync.iconset/icon_256x256@2x.png | Bin 0 -> 35628 bytes .../nopadding/sync.iconset/icon_32x32.png | Bin 0 -> 1563 bytes .../nopadding/sync.iconset/icon_32x32@2x.png | Bin 0 -> 3459 bytes .../warning.iconset/icon_128x128.png | Bin 0 -> 6039 bytes .../warning.iconset/icon_128x128@2x.png | Bin 0 -> 12859 bytes .../nopadding/warning.iconset/icon_16x16.png | Bin 0 -> 523 bytes .../warning.iconset/icon_16x16@2x.png | Bin 0 -> 1082 bytes .../warning.iconset/icon_256x256.png | Bin 0 -> 12859 bytes .../warning.iconset/icon_256x256@2x.png | Bin 0 -> 27637 bytes .../nopadding/warning.iconset/icon_32x32.png | Bin 0 -> 1082 bytes .../warning.iconset/icon_32x32@2x.png | Bin 0 -> 2582 bytes .../libcloudproviders/CMakeLists.txt | 50 + .../org.freedesktop.CloudProviders.ini.in | 4 + .../org.freedesktop.CloudProviders.service.in | 4 + shell_integration/nautilus/CMakeLists.txt | 35 + .../nautilus/createcajaplugin.sh | 8 + .../nautilus/createnemoplugin.sh | 7 + shell_integration/nautilus/setappname.sh | 8 + shell_integration/nautilus/syncstate.py | 482 ++ shell_integration/windows/CMakeLists.txt | 22 + .../windows/NCContextMenu/CMakeLists.txt | 27 + .../NCContextMenu/NCClientInterface.cpp | 99 + .../windows/NCContextMenu/NCClientInterface.h | 59 + .../windows/NCContextMenu/NCContextMenu.cpp | 232 + .../windows/NCContextMenu/NCContextMenu.def | 6 + .../windows/NCContextMenu/NCContextMenu.h | 53 + .../windows/NCContextMenu/NCContextMenu.rc | Bin 0 -> 4590 bytes .../NCContextMenu/NCContextMenuFactory.cpp | 89 + .../NCContextMenu/NCContextMenuFactory.h | 42 + .../NCContextMenu/NCContextMenuRegHandler.cpp | 231 + .../NCContextMenu/NCContextMenuRegHandler.h | 38 + .../windows/NCContextMenu/RegDelnode.h | 114 + .../windows/NCContextMenu/dllmain.cpp | 124 + .../windows/NCContextMenu/resource.h | 14 + .../windows/NCOverlays/CMakeLists.txt | 26 + .../windows/NCOverlays/DllMain.cpp | 177 + .../windows/NCOverlays/NCOverlay.cpp | 162 + .../windows/NCOverlays/NCOverlay.h | 43 + .../windows/NCOverlays/NCOverlay.rc | Bin 0 -> 5532 bytes .../windows/NCOverlays/NCOverlayFactory.cpp | 94 + .../windows/NCOverlays/NCOverlayFactory.h | 48 + .../NCOverlayRegistrationHandler.cpp | 171 + .../NCOverlays/NCOverlayRegistrationHandler.h | 31 + .../windows/NCOverlays/NCOverlays.def | 6 + .../windows/NCOverlays/ico/Error.ico | Bin 0 -> 28077 bytes .../windows/NCOverlays/ico/OK.ico | Bin 0 -> 27184 bytes .../windows/NCOverlays/ico/OK_Shared.ico | Bin 0 -> 29964 bytes .../windows/NCOverlays/ico/Sync.ico | Bin 0 -> 32010 bytes .../windows/NCOverlays/ico/Warning.ico | Bin 0 -> 25872 bytes .../windows/NCOverlays/resource.h | Bin 0 -> 1536 bytes .../windows/NCUtil/CMakeLists.txt | 11 + .../windows/NCUtil/CommunicationSocket.cpp | 143 + .../windows/NCUtil/CommunicationSocket.h | 48 + shell_integration/windows/NCUtil/NCUtil.rc | Bin 0 -> 4476 bytes .../windows/NCUtil/RemotePathChecker.cpp | 236 + .../windows/NCUtil/RemotePathChecker.h | 70 + .../windows/NCUtil/StringUtil.cpp | 36 + shell_integration/windows/NCUtil/StringUtil.h | 91 + shell_integration/windows/NCUtil/Version.h | 11 + shell_integration/windows/NCUtil/resource.h | 14 + shell_integration/windows/WinShellExt.wxs.in | 94 + .../windows/WinShellExtConstants.h.in | 47 + sonar-project.properties | 12 + src/3rdparty/LGPL_EXCEPTION.txt | 22 + src/3rdparty/QProgressIndicator/LICENSE | 21 + .../QProgressIndicator/QProgressIndicator.cpp | 135 + .../QProgressIndicator/QProgressIndicator.h | 111 + src/3rdparty/QProgressIndicator/README.md | 14 + src/3rdparty/kirigami/wheelhandler.cpp | 626 ++ src/3rdparty/kirigami/wheelhandler.h | 378 + .../kmessagewidget/kmessagewidget.cpp | 512 ++ src/3rdparty/kmessagewidget/kmessagewidget.h | 346 + src/3rdparty/qtlockedfile/README.txt | 5 + src/3rdparty/qtlockedfile/qtlockedfile.cpp | 158 + src/3rdparty/qtlockedfile/qtlockedfile.h | 77 + src/3rdparty/qtlockedfile/qtlockedfile.pri | 11 + .../qtlockedfile/qtlockedfile_unix.cpp | 108 + .../qtlockedfile/qtlockedfile_win.cpp | 196 + src/3rdparty/qtsingleapplication/README.txt | 5 + .../qtsingleapplication/qtlocalpeer.cpp | 182 + .../qtsingleapplication/qtlocalpeer.h | 65 + .../qtsingleapplication.cpp | 180 + .../qtsingleapplication/qtsingleapplication.h | 78 + .../qtsingleapplication.pri | 15 + .../qtsinglecoreapplication.cpp | 74 + .../qtsinglecoreapplication.h | 61 + .../qtsinglecoreapplication.pri | 14 + src/CMakeLists.txt | 106 + src/cmd/CMakeLists.txt | 51 + src/cmd/cmd.cpp | 583 ++ src/cmd/cmd.h | 39 + src/cmd/cmd.md | 4 + src/cmd/netrcparser.cpp | 111 + src/cmd/netrcparser.h | 45 + src/cmd/simplesslerrorhandler.cpp | 47 + src/cmd/simplesslerrorhandler.h | 35 + src/common/README | 2 + src/common/asserts.h | 64 + src/common/c_jhash.h | 255 + src/common/checksumcalculator.cpp | 180 + src/common/checksumcalculator.h | 58 + src/common/checksumconsts.h | 28 + src/common/checksums.cpp | 326 + src/common/checksums.h | 180 + src/common/common.cmake | 34 + src/common/constants.h | 23 + src/common/filesystembase.cpp | 700 ++ src/common/filesystembase.h | 210 + src/common/ownsql.cpp | 474 ++ src/common/ownsql.h | 173 + src/common/pinstate.cpp | 16 + src/common/pinstate.h | 138 + src/common/plugin.cpp | 33 + src/common/plugin.h | 48 + src/common/preparedsqlquerymanager.cpp | 56 + src/common/preparedsqlquerymanager.h | 129 + src/common/remotepermissions.cpp | 115 + src/common/remotepermissions.h | 128 + src/common/result.h | 168 + src/common/shellextensionutils.cpp | 35 + src/common/shellextensionutils.h | 38 + src/common/syncfilestatus.cpp | 79 + src/common/syncfilestatus.h | 71 + src/common/syncjournaldb.cpp | 3113 ++++++++ src/common/syncjournaldb.h | 468 ++ src/common/syncjournalfilerecord.cpp | 56 + src/common/syncjournalfilerecord.h | 184 + src/common/utility.cpp | 727 ++ src/common/utility.h | 371 + src/common/utility_mac.mm | 268 + src/common/utility_unix.cpp | 152 + src/common/utility_win.cpp | 545 ++ src/common/vfs.cpp | 275 + src/common/vfs.h | 372 + src/common/vfspluginmetadata.json.in | 4 + src/crashreporter/CMakeLists.txt | 63 + src/crashreporter/CrashReporterConfig.h.in | 16 + src/crashreporter/main.cpp | 110 + src/crashreporter/resources.qrc | 5 + src/csync/AUTHORS | 3 + src/csync/CMakeLists.txt | 135 + src/csync/COPYING | 502 ++ src/csync/ChangeLog | 355 + src/csync/ConfigureChecks.cmake | 40 + src/csync/DefineOptions.cmake | 1 + src/csync/INSTALL.md | 84 + src/csync/README.md | 34 + src/csync/config_csync.h.cmake | 14 + src/csync/csync.cpp | 22 + src/csync/csync.h | 257 + src/csync/csync_exclude.cpp | 874 ++ src/csync/csync_exclude.h | 275 + src/csync/csync_version.h.in | 29 + src/csync/std/c_lib.h | 24 + src/csync/std/c_private.h | 151 + src/csync/std/c_time.cpp | 103 + src/csync/std/c_time.h | 37 + src/csync/vio/csync_vio_local.h | 37 + src/csync/vio/csync_vio_local_unix.cpp | 175 + src/csync/vio/csync_vio_local_win.cpp | 234 + src/gui/CMakeLists.txt | 786 ++ src/gui/ConflictDelegate.qml | 86 + src/gui/ConflictItemFileInfo.qml | 98 + src/gui/EmojiPicker.qml | 146 + src/gui/EncryptionTokenSelectionWindow.qml | 146 + src/gui/ErrorBox.qml | 92 + src/gui/PredefinedStatusButton.qml | 72 + src/gui/ResolveConflictsDialog.qml | 177 + src/gui/UserStatusSelector.qml | 287 + src/gui/UserStatusSelectorButton.qml | 90 + src/gui/UserStatusSelectorPage.qml | 44 + src/gui/accountmanager.cpp | 708 ++ src/gui/accountmanager.h | 141 + src/gui/accountsettings.cpp | 1762 +++++ src/gui/accountsettings.h | 164 + src/gui/accountsettings.ui | 346 + src/gui/accountsetupcommandlinemanager.cpp | 119 + src/gui/accountsetupcommandlinemanager.h | 53 + src/gui/accountsetupfromcommandlinejob.cpp | 238 + src/gui/accountsetupfromcommandlinejob.h | 66 + src/gui/accountstate.cpp | 708 ++ src/gui/accountstate.h | 299 + src/gui/addcertificatedialog.cpp | 63 + src/gui/addcertificatedialog.h | 53 + src/gui/addcertificatedialog.ui | 217 + src/gui/application.cpp | 1142 +++ src/gui/application.h | 165 + src/gui/authenticationdialog.cpp | 58 + src/gui/authenticationdialog.h | 45 + src/gui/callstatechecker.cpp | 184 + src/gui/callstatechecker.h | 70 + src/gui/caseclashfilenamedialog.cpp | 290 + src/gui/caseclashfilenamedialog.h | 83 + src/gui/caseclashfilenamedialog.ui | 340 + .../cloudproviders/cloudproviderconfig.h.in | 21 + .../cloudproviders/cloudprovidermanager.cpp | 78 + src/gui/cloudproviders/cloudprovidermanager.h | 42 + .../cloudproviders/cloudproviderwrapper.cpp | 357 + src/gui/cloudproviders/cloudproviderwrapper.h | 66 + src/gui/cocoainitializer.h | 34 + src/gui/cocoainitializer_mac.mm | 89 + src/gui/configgui.h.in | 4 + src/gui/conflictdialog.cpp | 183 + src/gui/conflictdialog.h | 57 + src/gui/conflictdialog.ui | 305 + src/gui/conflictsolver.cpp | 164 + src/gui/conflictsolver.h | 64 + src/gui/connectionvalidator.cpp | 425 + src/gui/connectionvalidator.h | 192 + src/gui/creds/credentialsfactory.cpp | 46 + src/gui/creds/credentialsfactory.h | 38 + src/gui/creds/flow2auth.cpp | 290 + src/gui/creds/flow2auth.h | 87 + src/gui/creds/httpcredentialsgui.cpp | 123 + src/gui/creds/httpcredentialsgui.h | 49 + src/gui/creds/webflowcredentials.cpp | 594 ++ src/gui/creds/webflowcredentials.h | 131 + src/gui/creds/webflowcredentialsdialog.cpp | 178 + src/gui/creds/webflowcredentialsdialog.h | 68 + src/gui/editlocallyjob.cpp | 581 ++ src/gui/editlocallyjob.h | 104 + src/gui/editlocallymanager.cpp | 196 + src/gui/editlocallymanager.h | 78 + src/gui/editlocallyverificationjob.cpp | 134 + src/gui/editlocallyverificationjob.h | 55 + src/gui/elidedlabel.cpp | 53 + src/gui/elidedlabel.h | 45 + src/gui/emojimodel.cpp | 1571 ++++ src/gui/emojimodel.h | 137 + src/gui/fileactivitylistmodel.cpp | 93 + src/gui/fileactivitylistmodel.h | 46 + src/gui/filedetails/FileActivityView.qml | 33 + src/gui/filedetails/FileDetailsPage.qml | 286 + src/gui/filedetails/FileDetailsView.qml | 46 + src/gui/filedetails/FileDetailsWindow.qml | 45 + src/gui/filedetails/FileTag.qml | 32 + src/gui/filedetails/NCInputDateField.qml | 50 + src/gui/filedetails/NCInputTextArea.qml | 55 + src/gui/filedetails/NCInputTextField.qml | 58 + src/gui/filedetails/NCTabButton.qml | 87 + src/gui/filedetails/ShareDelegate.qml | 280 + src/gui/filedetails/ShareDetailsPage.qml | 803 ++ src/gui/filedetails/ShareView.qml | 336 + src/gui/filedetails/ShareeDelegate.qml | 72 + src/gui/filedetails/ShareeSearchField.qml | 236 + src/gui/filedetails/datefieldbackend.cpp | 184 + src/gui/filedetails/datefieldbackend.h | 94 + src/gui/filedetails/filedetails.cpp | 207 + src/gui/filedetails/filedetails.h | 89 + src/gui/filedetails/shareemodel.cpp | 341 + src/gui/filedetails/shareemodel.h | 112 + src/gui/filedetails/sharemodel.cpp | 1511 ++++ src/gui/filedetails/sharemodel.h | 279 + src/gui/filedetails/sortedsharemodel.cpp | 92 + src/gui/filedetails/sortedsharemodel.h | 34 + src/gui/filetagmodel.cpp | 211 + src/gui/filetagmodel.h | 80 + src/gui/folder.cpp | 1927 +++++ src/gui/folder.h | 590 ++ src/gui/foldercreationdialog.cpp | 95 + src/gui/foldercreationdialog.h | 50 + src/gui/foldercreationdialog.ui | 100 + src/gui/folderman.cpp | 2099 +++++ src/gui/folderman.h | 421 + src/gui/folderstatusdelegate.cpp | 432 + src/gui/folderstatusdelegate.h | 80 + src/gui/folderstatusmodel.cpp | 1363 ++++ src/gui/folderstatusmodel.h | 179 + src/gui/folderstatusview.cpp | 42 + src/gui/folderstatusview.h | 39 + src/gui/folderwatcher.cpp | 263 + src/gui/folderwatcher.h | 160 + src/gui/folderwatcher_linux.cpp | 220 + src/gui/folderwatcher_linux.h | 67 + src/gui/folderwatcher_mac.cpp | 159 + src/gui/folderwatcher_mac.h | 53 + src/gui/folderwatcher_win.cpp | 239 + src/gui/folderwatcher_win.h | 88 + src/gui/folderwizard.cpp | 723 ++ src/gui/folderwizard.h | 182 + src/gui/folderwizardsourcepage.ui | 76 + src/gui/folderwizardtargetpage.ui | 125 + src/gui/foregroundbackground_cocoa.h | 42 + src/gui/foregroundbackground_cocoa.mm | 34 + src/gui/foregroundbackground_interface.h | 63 + src/gui/foregroundbackground_mac.mm | 39 + src/gui/generalsettings.cpp | 679 ++ src/gui/generalsettings.h | 82 + src/gui/generalsettings.ui | 527 ++ src/gui/gui.md | 5 + src/gui/guiutility.cpp | 105 + src/gui/guiutility.h | 55 + src/gui/iconutils.cpp | 206 + src/gui/iconutils.h | 31 + src/gui/ignorelisteditor.cpp | 94 + src/gui/ignorelisteditor.h | 54 + src/gui/ignorelisteditor.ui | 97 + src/gui/ignorelisttablewidget.cpp | 170 + src/gui/ignorelisttablewidget.h | 38 + src/gui/ignorelisttablewidget.ui | 112 + src/gui/invalidfilenamedialog.cpp | 321 + src/gui/invalidfilenamedialog.h | 87 + src/gui/invalidfilenamedialog.ui | 133 + src/gui/legalnotice.cpp | 71 + src/gui/legalnotice.h | 50 + src/gui/legalnotice.ui | 67 + src/gui/lockwatcher.cpp | 67 + src/gui/lockwatcher.h | 74 + src/gui/logbrowser.cpp | 128 + src/gui/logbrowser.h | 52 + src/gui/macOS/ClientCommunicationProtocol.h | 1 + src/gui/macOS/fileprovider.h | 61 + src/gui/macOS/fileprovider_mac.mm | 116 + src/gui/macOS/fileproviderdomainmanager.h | 65 + .../macOS/fileproviderdomainmanager_mac.mm | 710 ++ src/gui/macOS/fileproviderdomainsyncstatus.h | 98 + .../macOS/fileproviderdomainsyncstatus_mac.mm | 263 + src/gui/macOS/fileprovidereditlocallyjob.cpp | 97 + src/gui/macOS/fileprovidereditlocallyjob.h | 57 + .../macOS/fileprovidereditlocallyjob_mac.mm | 92 + src/gui/macOS/fileprovideritemmetadata.cpp | 190 + src/gui/macOS/fileprovideritemmetadata.h | 143 + src/gui/macOS/fileprovideritemmetadata_mac.mm | 155 + .../fileprovidermaterialiseditemsmodel.cpp | 171 + .../fileprovidermaterialiseditemsmodel.h | 90 + .../fileprovidermaterialiseditemsmodel_mac.mm | 84 + .../macOS/fileprovidersettingscontroller.h | 81 + .../fileprovidersettingscontroller_mac.mm | 511 ++ .../macOS/fileprovidersocketcontroller.cpp | 270 + src/gui/macOS/fileprovidersocketcontroller.h | 66 + src/gui/macOS/fileprovidersocketserver.cpp | 103 + src/gui/macOS/fileprovidersocketserver.h | 72 + src/gui/macOS/fileprovidersocketserver_mac.mm | 40 + ...ileproviderstorageuseenumerationobserver.h | 25 + ...ileproviderstorageuseenumerationobserver.m | 56 + src/gui/macOS/fileproviderutils.h | 50 + src/gui/macOS/fileproviderutils_mac.mm | 94 + src/gui/macOS/fileproviderxpc.h | 60 + src/gui/macOS/fileproviderxpc_mac.mm | 242 + src/gui/macOS/fileproviderxpc_mac_utils.h | 34 + src/gui/macOS/fileproviderxpc_mac_utils.mm | 282 + src/gui/macOS/progressobserver.h | 30 + src/gui/macOS/progressobserver.m | 42 + .../macOS/ui/FileProviderEvictionDialog.qml | 81 + .../FileProviderFastEnumerationSettings.qml | 58 + src/gui/macOS/ui/FileProviderFileDelegate.qml | 99 + src/gui/macOS/ui/FileProviderSettings.qml | 146 + src/gui/macOS/ui/FileProviderStorageInfo.qml | 69 + src/gui/macOS/ui/FileProviderSyncStatus.qml | 80 + src/gui/main.cpp | 209 + src/gui/manifest-mingw.rc | 3 + src/gui/mnemonicdialog.ui | 142 + src/gui/navigationpanehelper.cpp | 180 + src/gui/navigationpanehelper.h | 46 + src/gui/networksettings.cpp | 332 + src/gui/networksettings.h | 64 + src/gui/networksettings.ui | 596 ++ src/gui/notificationconfirmjob.cpp | 70 + src/gui/notificationconfirmjob.h | 73 + src/gui/ocsjob.cpp | 160 + src/gui/ocsjob.h | 159 + src/gui/ocsnavigationappsjob.cpp | 37 + src/gui/ocsnavigationappsjob.h | 55 + src/gui/ocsshareejob.cpp | 49 + src/gui/ocsshareejob.h | 55 + src/gui/ocssharejob.cpp | 226 + src/gui/ocssharejob.h | 164 + src/gui/openfilemanager.cpp | 198 + src/gui/openfilemanager.h | 24 + src/gui/owncloud.exe.manifest-mingw | 10 + src/gui/owncloud.xml.in | 7 + src/gui/owncloudgui.cpp | 719 ++ src/gui/owncloudgui.h | 132 + src/gui/owncloudsetupwizard.cpp | 780 ++ src/gui/owncloudsetupwizard.h | 91 + src/gui/passwordinputdialog.cpp | 41 + src/gui/passwordinputdialog.h | 39 + src/gui/passwordinputdialog.ui | 115 + src/gui/profilepagewidget.cpp | 46 + src/gui/profilepagewidget.h | 30 + src/gui/proxyauthdialog.cpp | 54 + src/gui/proxyauthdialog.h | 53 + src/gui/proxyauthdialog.ui | 118 + src/gui/proxyauthhandler.cpp | 267 + src/gui/proxyauthhandler.h | 117 + src/gui/remotewipe.cpp | 171 + src/gui/remotewipe.h | 61 + src/gui/selectivesyncdialog.cpp | 560 ++ src/gui/selectivesyncdialog.h | 119 + src/gui/settingsdialog.cpp | 410 + src/gui/settingsdialog.h | 99 + src/gui/settingsdialog.ui | 43 + src/gui/sharee.cpp | 128 + src/gui/sharee.h | 81 + src/gui/sharemanager.cpp | 725 ++ src/gui/sharemanager.h | 497 ++ src/gui/sharepermissions.h | 41 + src/gui/shellextensionsserver.cpp | 365 + src/gui/shellextensionsserver.h | 78 + src/gui/socketapi/CMakeLists.txt | 10 + src/gui/socketapi/socketapi.cpp | 1735 ++++ src/gui/socketapi/socketapi.h | 213 + src/gui/socketapi/socketapi_mac.mm | 35 + src/gui/socketapi/socketapi_p.h | 168 + src/gui/socketapi/socketuploadjob.cpp | 97 + src/gui/socketapi/socketuploadjob.h | 44 + src/gui/sslbutton.cpp | 248 + src/gui/sslbutton.h | 53 + src/gui/sslerrordialog.cpp | 243 + src/gui/sslerrordialog.h | 70 + src/gui/sslerrordialog.ui | 47 + src/gui/syncconflictsmodel.cpp | 343 + src/gui/syncconflictsmodel.h | 131 + src/gui/syncrunfilelog.cpp | 151 + src/gui/syncrunfilelog.h | 54 + src/gui/systray.cpp | 989 +++ src/gui/systray.h | 208 + src/gui/systray_mac_common.mm | 55 + src/gui/systray_mac_usernotifications.mm | 272 + src/gui/tooltipupdater.cpp | 57 + src/gui/tooltipupdater.h | 53 + src/gui/tray/ActivityItem.qml | 70 + src/gui/tray/ActivityItemActions.qml | 49 + src/gui/tray/ActivityItemContent.qml | 272 + src/gui/tray/ActivityItemContextMenu.qml | 26 + src/gui/tray/ActivityList.qml | 164 + src/gui/tray/AutoSizingMenu.qml | 16 + src/gui/tray/CallNotificationDialog.qml | 259 + src/gui/tray/CurrentAccountHeaderButton.qml | 275 + src/gui/tray/EditFileLocallyLoadingDialog.qml | 84 + .../tray/EncryptionTokenDiscoveryDialog.qml | 89 + src/gui/tray/EnforcedPlainTextLabel.qml | 29 + src/gui/tray/HeaderButton.qml | 47 + src/gui/tray/ListItemLineAndSubline.qml | 50 + src/gui/tray/MainWindow.qml | 502 ++ src/gui/tray/NCBusyIndicator.qml | 53 + src/gui/tray/NCIconWithBackgroundImage.qml | 37 + src/gui/tray/NCProgressBar.qml | 47 + src/gui/tray/NCToolTip.qml | 29 + src/gui/tray/SyncStatus.qml | 133 + src/gui/tray/TalkReplyTextField.qml | 55 + src/gui/tray/TrayFolderListItem.qml | 63 + src/gui/tray/TrayFoldersMenuButton.qml | 241 + src/gui/tray/TrayWindowHeader.qml | 140 + src/gui/tray/UnifiedSearchInputContainer.qml | 104 + src/gui/tray/UnifiedSearchPlaceholderView.qml | 50 + .../UnifiedSearchResultFetchMoreTrigger.qml | 61 + src/gui/tray/UnifiedSearchResultItem.qml | 109 + .../tray/UnifiedSearchResultItemSkeleton.qml | 177 + ...ifiedSearchResultItemSkeletonContainer.qml | 85 + ...rchResultItemSkeletonGradientRectangle.qml | 56 + src/gui/tray/UnifiedSearchResultListItem.qml | 83 + .../tray/UnifiedSearchResultNothingFound.qml | 59 + .../tray/UnifiedSearchResultSectionItem.qml | 34 + src/gui/tray/UserLine.qml | 194 + src/gui/tray/activitydata.cpp | 232 + src/gui/tray/activitydata.h | 232 + src/gui/tray/activitylistmodel.cpp | 1005 +++ src/gui/tray/activitylistmodel.h | 227 + src/gui/tray/asyncimageresponse.cpp | 150 + src/gui/tray/asyncimageresponse.h | 40 + src/gui/tray/notificationhandler.cpp | 183 + src/gui/tray/notificationhandler.h | 37 + src/gui/tray/sortedactivitylistmodel.cpp | 150 + src/gui/tray/sortedactivitylistmodel.h | 34 + src/gui/tray/svgimageprovider.cpp | 55 + src/gui/tray/svgimageprovider.h | 28 + src/gui/tray/syncstatussummary.cpp | 376 + src/gui/tray/syncstatussummary.h | 97 + src/gui/tray/talkreply.cpp | 46 + src/gui/tray/talkreply.h | 24 + src/gui/tray/trayimageprovider.cpp | 25 + src/gui/tray/trayimageprovider.h | 33 + src/gui/tray/unifiedsearchresult.cpp | 36 + src/gui/tray/unifiedsearchresult.h | 51 + .../tray/unifiedsearchresultslistmodel.cpp | 748 ++ src/gui/tray/unifiedsearchresultslistmodel.h | 139 + src/gui/tray/usermodel.cpp | 1802 +++++ src/gui/tray/usermodel.h | 327 + src/gui/updater/CMakeLists.txt | 9 + src/gui/updater/ocupdater.cpp | 573 ++ src/gui/updater/ocupdater.h | 192 + src/gui/updater/sparkleupdater.h | 65 + src/gui/updater/sparkleupdater_mac.mm | 320 + src/gui/updater/updateinfo.cpp | 106 + src/gui/updater/updateinfo.h | 37 + src/gui/updater/updater.cpp | 176 + src/gui/updater/updater.h | 62 + src/gui/userinfo.cpp | 161 + src/gui/userinfo.h | 114 + src/gui/userstatusselectormodel.cpp | 475 ++ src/gui/userstatusselectormodel.h | 148 + src/gui/version.rc.in | 37 + src/gui/vfsdownloaderrordialog.cpp | 35 + src/gui/vfsdownloaderrordialog.h | 35 + src/gui/vfsdownloaderrordialog.ui | 166 + src/gui/wizard/abstractcredswizardpage.cpp | 37 + src/gui/wizard/abstractcredswizardpage.h | 37 + src/gui/wizard/flow2authcredspage.cpp | 153 + src/gui/wizard/flow2authcredspage.h | 68 + src/gui/wizard/flow2authwidget.cpp | 229 + src/gui/wizard/flow2authwidget.h | 71 + src/gui/wizard/flow2authwidget.ui | 261 + src/gui/wizard/linklabel.cpp | 58 + src/gui/wizard/linklabel.h | 46 + src/gui/wizard/owncloudadvancedsetuppage.cpp | 688 ++ src/gui/wizard/owncloudadvancedsetuppage.h | 112 + src/gui/wizard/owncloudadvancedsetuppage.ui | 749 ++ .../wizard/owncloudconnectionmethoddialog.cpp | 57 + .../wizard/owncloudconnectionmethoddialog.h | 60 + .../wizard/owncloudconnectionmethoddialog.ui | 81 + src/gui/wizard/owncloudhttpcredspage.cpp | 213 + src/gui/wizard/owncloudhttpcredspage.h | 66 + src/gui/wizard/owncloudhttpcredspage.ui | 158 + src/gui/wizard/owncloudsetupnocredspage.ui | 378 + src/gui/wizard/owncloudsetuppage.cpp | 401 + src/gui/wizard/owncloudsetuppage.h | 99 + src/gui/wizard/owncloudwizard.cpp | 521 ++ src/gui/wizard/owncloudwizard.h | 151 + src/gui/wizard/owncloudwizardcommon.cpp | 86 + src/gui/wizard/owncloudwizardcommon.h | 61 + src/gui/wizard/postfixlineedit.cpp | 77 + src/gui/wizard/postfixlineedit.h | 56 + src/gui/wizard/slideshow.cpp | 218 + src/gui/wizard/slideshow.h | 84 + src/gui/wizard/termsofservicecheckwidget.cpp | 194 + src/gui/wizard/termsofservicecheckwidget.h | 72 + src/gui/wizard/termsofservicecheckwidget.ui | 248 + src/gui/wizard/termsofservicewizardpage.cpp | 93 + src/gui/wizard/termsofservicewizardpage.h | 58 + src/gui/wizard/webview.cpp | 272 + src/gui/wizard/webview.h | 49 + src/gui/wizard/webview.ui | 80 + src/gui/wizard/webviewpage.cpp | 129 + src/gui/wizard/webviewpage.h | 50 + src/gui/wizard/welcomepage.cpp | 125 + src/gui/wizard/welcomepage.h | 54 + src/gui/wizard/welcomepage.ui | 229 + src/libsync/CMakeLists.txt | 287 + src/libsync/abstractnetworkjob.cpp | 500 ++ src/libsync/abstractnetworkjob.h | 276 + src/libsync/accessmanager.cpp | 93 + src/libsync/accessmanager.h | 45 + src/libsync/account.cpp | 1399 ++++ src/libsync/account.h | 600 ++ src/libsync/accountfwd.h | 29 + src/libsync/bandwidthmanager.cpp | 414 + src/libsync/bandwidthmanager.h | 106 + .../basepropagateremotedeleteencrypted.cpp | 208 + .../basepropagateremotedeleteencrypted.h | 78 + src/libsync/bulkpropagatorjob.cpp | 765 ++ src/libsync/bulkpropagatorjob.h | 171 + src/libsync/capabilities.cpp | 519 ++ src/libsync/capabilities.h | 231 + src/libsync/caseclashconflictsolver.cpp | 227 + src/libsync/caseclashconflictsolver.h | 107 + src/libsync/clientproxy.cpp | 157 + src/libsync/clientproxy.h | 66 + src/libsync/clientsideencryption.cpp | 3211 ++++++++ src/libsync/clientsideencryption.h | 423 + src/libsync/clientsideencryptionjobs.cpp | 542 ++ src/libsync/clientsideencryptionjobs.h | 369 + .../clientsideencryptionprimitives.cpp | 161 + src/libsync/clientsideencryptionprimitives.h | 142 + .../clientsideencryptiontokenselector.cpp | 285 + .../clientsideencryptiontokenselector.h | 71 + src/libsync/clientstatusreporting.cpp | 72 + src/libsync/clientstatusreporting.h | 53 + src/libsync/clientstatusreportingcommon.cpp | 49 + src/libsync/clientstatusreportingcommon.h | 31 + src/libsync/clientstatusreportingdatabase.cpp | 280 + src/libsync/clientstatusreportingdatabase.h | 68 + src/libsync/clientstatusreportingnetwork.cpp | 191 + src/libsync/clientstatusreportingnetwork.h | 68 + src/libsync/clientstatusreportingrecord.h | 38 + src/libsync/configfile.cpp | 1318 +++ src/libsync/configfile.h | 275 + src/libsync/cookiejar.cpp | 150 + src/libsync/cookiejar.h | 54 + src/libsync/creds/abstractcredentials.cpp | 65 + src/libsync/creds/abstractcredentials.h | 118 + src/libsync/creds/credentialscommon.cpp | 30 + src/libsync/creds/credentialscommon.h | 25 + src/libsync/creds/dummycredentials.cpp | 67 + src/libsync/creds/dummycredentials.h | 44 + src/libsync/creds/httpcredentials.cpp | 565 ++ src/libsync/creds/httpcredentials.h | 169 + src/libsync/creds/keychainchunk.cpp | 487 ++ src/libsync/creds/keychainchunk.h | 200 + src/libsync/creds/tokencredentials.cpp | 171 + src/libsync/creds/tokencredentials.h | 66 + src/libsync/datetimeprovider.cpp | 17 + src/libsync/datetimeprovider.h | 18 + src/libsync/deletejob.cpp | 78 + src/libsync/deletejob.h | 47 + src/libsync/discovery.cpp | 2351 ++++++ src/libsync/discovery.h | 312 + src/libsync/discoveryphase.cpp | 798 ++ src/libsync/discoveryphase.h | 387 + .../encryptedfoldermetadatahandler.cpp | 394 + src/libsync/encryptedfoldermetadatahandler.h | 128 + src/libsync/encryptfolderjob.cpp | 156 + src/libsync/encryptfolderjob.h | 73 + src/libsync/filesystem.cpp | 569 ++ src/libsync/filesystem.h | 137 + src/libsync/foldermetadata.cpp | 1158 +++ src/libsync/foldermetadata.h | 258 + src/libsync/helpers.cpp | 25 + src/libsync/helpers.h | 25 + src/libsync/httplogger.cpp | 139 + src/libsync/httplogger.h | 34 + src/libsync/iconjob.cpp | 44 + src/libsync/iconjob.h | 49 + src/libsync/libsync.md | 5 + src/libsync/localdiscoverytracker.cpp | 95 + src/libsync/localdiscoverytracker.h | 103 + src/libsync/lockfilejobs.cpp | 257 + src/libsync/lockfilejobs.h | 71 + src/libsync/logger.cpp | 416 + src/libsync/logger.h | 129 + src/libsync/networkjobs.cpp | 1357 ++++ src/libsync/networkjobs.h | 598 ++ src/libsync/nextcloudtheme.cpp | 41 + src/libsync/nextcloudtheme.h | 35 + src/libsync/ocsprofileconnector.cpp | 168 + src/libsync/ocsprofileconnector.h | 58 + src/libsync/ocsuserstatusconnector.cpp | 475 ++ src/libsync/ocsuserstatusconnector.h | 70 + src/libsync/owncloudpropagator.cpp | 1792 +++++ src/libsync/owncloudpropagator.h | 759 ++ src/libsync/owncloudpropagator_p.h | 158 + src/libsync/progressdispatcher.cpp | 422 + src/libsync/progressdispatcher.h | 322 + src/libsync/propagatedownload.cpp | 1475 ++++ src/libsync/propagatedownload.h | 278 + src/libsync/propagatedownloadencrypted.cpp | 117 + src/libsync/propagatedownloadencrypted.h | 47 + src/libsync/propagateremotedelete.cpp | 140 + src/libsync/propagateremotedelete.h | 49 + .../propagateremotedeleteencrypted.cpp | 93 + src/libsync/propagateremotedeleteencrypted.h | 35 + ...opagateremotedeleteencryptedrootfolder.cpp | 207 + ...propagateremotedeleteencryptedrootfolder.h | 44 + src/libsync/propagateremotemkdir.cpp | 292 + src/libsync/propagateremotemkdir.h | 62 + src/libsync/propagateremotemove.cpp | 347 + src/libsync/propagateremotemove.h | 71 + src/libsync/propagateupload.cpp | 901 +++ src/libsync/propagateupload.h | 427 + src/libsync/propagateuploadencrypted.cpp | 189 + src/libsync/propagateuploadencrypted.h | 79 + src/libsync/propagateuploadng.cpp | 578 ++ src/libsync/propagateuploadv1.cpp | 404 + src/libsync/propagatorjobs.cpp | 562 ++ src/libsync/propagatorjobs.h | 96 + src/libsync/pushnotifications.cpp | 297 + src/libsync/pushnotifications.h | 142 + src/libsync/putmultifilejob.cpp | 119 + src/libsync/putmultifilejob.h | 78 + src/libsync/rootencryptedfolderinfo.cpp | 54 + src/libsync/rootencryptedfolderinfo.h | 44 + src/libsync/syncengine.cpp | 1644 ++++ src/libsync/syncengine.h | 430 + src/libsync/syncfileitem.cpp | 270 + src/libsync/syncfileitem.h | 367 + src/libsync/syncfilestatustracker.cpp | 375 + src/libsync/syncfilestatustracker.h | 87 + src/libsync/syncoptions.cpp | 104 + src/libsync/syncoptions.h | 128 + src/libsync/syncresult.cpp | 188 + src/libsync/syncresult.h | 122 + src/libsync/theme.cpp | 1104 +++ src/libsync/theme.h | 671 ++ src/libsync/updatee2eefoldermetadatajob.cpp | 178 + src/libsync/updatee2eefoldermetadatajob.h | 58 + .../updatee2eefolderusersmetadatajob.cpp | 374 + .../updatee2eefolderusersmetadatajob.h | 111 + src/libsync/updatemigratede2eemetadatajob.cpp | 98 + src/libsync/updatemigratede2eemetadatajob.h | 49 + src/libsync/userstatusconnector.cpp | 121 + src/libsync/userstatusconnector.h | 141 + src/libsync/vfs/CMakeLists.txt | 30 + src/libsync/vfs/cfapi/CMakeLists.txt | 52 + src/libsync/vfs/cfapi/cfapiwrapper.cpp | 989 +++ src/libsync/vfs/cfapi/cfapiwrapper.h | 105 + src/libsync/vfs/cfapi/hydrationjob.cpp | 375 + src/libsync/vfs/cfapi/hydrationjob.h | 127 + src/libsync/vfs/cfapi/shellext/CMakeLists.txt | 216 + .../cfapi/shellext/CfApiShellIntegration.def | 3 + .../cfapi/shellext/CustomStateProvider.idl | 21 + .../cfapishellintegrationclassfactory.cpp | 97 + .../cfapishellintegrationclassfactory.h | 50 + .../shellext/configvfscfapishellext.h.in | 20 + .../cfapi/shellext/customstateprovider.cpp | 104 + .../vfs/cfapi/shellext/customstateprovider.h | 46 + .../cfapi/shellext/customstateprovideripc.cpp | 104 + .../cfapi/shellext/customstateprovideripc.h | 43 + src/libsync/vfs/cfapi/shellext/dllmain.cpp | 75 + src/libsync/vfs/cfapi/shellext/ipccommon.cpp | 50 + src/libsync/vfs/cfapi/shellext/ipccommon.h | 21 + .../vfs/cfapi/shellext/thumbnailprovider.cpp | 167 + .../vfs/cfapi/shellext/thumbnailprovider.h | 56 + .../cfapi/shellext/thumbnailprovideripc.cpp | 113 + .../vfs/cfapi/shellext/thumbnailprovideripc.h | 46 + src/libsync/vfs/cfapi/vfs_cfapi.cpp | 572 ++ src/libsync/vfs/cfapi/vfs_cfapi.h | 106 + src/libsync/vfs/suffix/CMakeLists.txt | 45 + src/libsync/vfs/suffix/vfs_suffix.cpp | 177 + src/libsync/vfs/suffix/vfs_suffix.h | 72 + src/libsync/vfs/xattr/CMakeLists.txt | 61 + src/libsync/vfs/xattr/vfs_xattr.cpp | 201 + src/libsync/vfs/xattr/vfs_xattr.h | 74 + src/libsync/vfs/xattr/xattrwrapper.h | 33 + src/libsync/vfs/xattr/xattrwrapper_linux.cpp | 69 + src/libsync/wordlist.cpp | 2098 +++++ src/libsync/wordlist.h | 16 + sync-exclude.lst | 53 + test/CMakeLists.txt | 146 + test/activitylistmodeltestutils.cpp | 562 ++ test/activitylistmodeltestutils.h | 105 + test/benchmarks/benchlargesync.cpp | 49 + test/csync/AUTHORS | 3 + test/csync/CMakeLists.txt | 26 + test/csync/COPYING | 502 ++ test/csync/cmdline.c | 90 + test/csync/std_tests/check_std_c_jhash.c | 329 + test/csync/torture.c | 41 + test/csync/torture.h | 52 + test/csync/valgrind-csync.supp | 61 + test/csync/vio_tests/check_vio_ext.cpp | 366 + test/e2etestsfakecert.pem | 22 + test/e2etestsfakecertprivatekey.pem | 28 + test/e2etestsfakecertpublickey.pem | 9 + test/endtoendtestutils.cpp | 174 + test/endtoendtestutils.h | 98 + test/fake2eelocksucceeded.json | 10 + test/fakefiledrope2eefoldermetadata.json | 10 + test/fakeshortcut.base64 | 1 + test/manual/favlink/favlink.pro | 16 + test/manual/favlink/main.cpp | 23 + test/manual/favlink/owncloudlib.h | 1 + test/mockserver/CMakeLists.txt | 21 + test/mockserver/httpserver.cpp | 64 + test/mockserver/httpserver.h | 27 + test/mockserver/main.cpp | 24 + test/nextcloud_add_test.cmake | 120 + test/pushnotificationstestutils.cpp | 210 + test/pushnotificationstestutils.h | 89 + test/sharetestutils.cpp | 444 ++ test/sharetestutils.h | 136 + test/stubfolderman.cpp | 14 + test/stubremotewipe.cpp | 31 + test/syncenginetestutils.cpp | 1533 ++++ test/syncenginetestutils.h | 702 ++ test/test_journal.db | Bin 0 -> 57344 bytes test/testaccount.cpp | 43 + test/testactivitydata.cpp | 336 + test/testactivitylistmodel.cpp | 352 + test/testallfilesdeleted.cpp | 344 + test/testasyncop.cpp | 241 + test/testblacklist.cpp | 194 + test/testcapabilities.cpp | 317 + test/testcfapishellextensionsipc.cpp | 411 + test/testchecksumvalidator.cpp | 232 + test/testchunkingng.cpp | 680 ++ test/testclientsideencryption.cpp | 282 + test/testclientsideencryptionv2.cpp | 427 + test/testclientstatusreporting.cpp | 150 + test/testconcaturl.cpp | 115 + test/testcookies.cpp | 43 + test/testdatabaseerror.cpp | 88 + test/testdatefieldbackend.cpp | 163 + test/testdownload.cpp | 255 + test/teste2efiletransfer.cpp | 125 + test/teste2eserversetup.cpp | 67 + test/testexcludedfiles.cpp | 788 ++ test/testfiletagmodel.cpp | 171 + test/testfolder.cpp | 45 + test/testfolderman.cpp | 450 ++ test/testfolderstatusmodel.cpp | 81 + test/testfolderwatcher.cpp | 397 + test/testhelper.cpp | 28 + test/testhelper.h | 44 + test/testiconutils.cpp | 102 + test/testinotifywatcher.cpp | 71 + test/testlocaldiscovery.cpp | 869 ++ test/testlockedfiles.cpp | 177 + test/testlockfile.cpp | 795 ++ test/testlongpath.cpp | 151 + test/testnetrcparser.cpp | 84 + test/testnextcloudpropagator.cpp | 113 + test/testownsql.cpp | 156 + test/testpermissions.cpp | 959 +++ test/testplan.txt | 83 + test/testpushnotifications.cpp | 306 + test/testremotediscovery.cpp | 186 + test/testremotewipe.cpp | 92 + test/testsecurefiledrop.cpp | 193 + test/testselectivesync.cpp | 130 + test/testsetuserstatusdialog.cpp | 757 ++ test/testshareemodel.cpp | 507 ++ test/testsharemodel.cpp | 986 +++ test/testsortedactivitylistmodel.cpp | 245 + test/testsortedsharemodel.cpp | 201 + test/testsynccfapi.cpp | 1455 ++++ test/testsyncconflict.cpp | 672 ++ test/testsyncconflictsmodel.cpp | 121 + test/testsyncdelete.cpp | 70 + test/testsyncengine.cpp | 2115 +++++ test/testsyncfileitem.cpp | 75 + test/testsyncfilestatustracker.cpp | 571 ++ test/testsyncjournaldb.cpp | 465 ++ test/testsyncmove.cpp | 1319 +++ test/testsyncvirtualfiles.cpp | 2026 +++++ test/testsyncxattr.cpp | 1094 +++ test/testtalkreply.cpp | 98 + test/testtheme.cpp | 123 + test/testunifiedsearchlistmodel.cpp | 645 ++ test/testupdater.cpp | 43 + test/testuploadreset.cpp | 83 + test/testutility.cpp | 349 + test/testxmlparse.cpp | 629 ++ test/themeutils.cpp | 40 + test/themeutils.h | 34 + theme.qrc.in | 246 + theme/Style/Style.qml | 208 + theme/Style/qmldir | 2 + theme/account.svg | 1 + theme/add.svg | 1 + theme/black/account-group.svg | 1 + theme/black/activity.svg | 1 + theme/black/add.svg | 1 + theme/black/bell.svg | 1 + theme/black/calendar.svg | 1 + theme/black/caret-down.svg | 1 + theme/black/change.svg | 1 + theme/black/clear.svg | 1 + theme/black/close.svg | 1 + theme/black/comment.svg | 1 + theme/black/confirm.svg | 1 + theme/black/control-next.svg | 9 + theme/black/control-prev.svg | 9 + theme/black/deck.svg | 8 + theme/black/edit.svg | 1 + theme/black/email.svg | 1 + theme/black/expand-less-black.svg | 1 + theme/black/external.png | Bin 0 -> 2430 bytes theme/black/external.svg | 1 + theme/black/external@2x.png | Bin 0 -> 3060 bytes theme/black/folder-group.svg | 1 + theme/black/folder.png | Bin 0 -> 1924 bytes theme/black/folder.svg | 1 + theme/black/folder@2x.png | Bin 0 -> 2270 bytes theme/black/more-apps.svg | 1 + theme/black/search.svg | 1 + theme/black/settings.svg | 1 + theme/black/state-error.svg | 1 + theme/black/state-info.svg | 1 + theme/black/state-offline.svg | 1 + theme/black/state-ok.svg | 1 + theme/black/state-pause.svg | 1 + theme/black/state-sync.svg | 1 + theme/black/state-warning.svg | 1 + theme/black/user.svg | 1 + theme/black/wizard-files.png | Bin 0 -> 2913 bytes theme/black/wizard-files.svg | 1 + theme/black/wizard-files@2x.png | Bin 0 -> 4365 bytes theme/black/wizard-groupware.png | Bin 0 -> 3027 bytes theme/black/wizard-groupware.svg | 1 + theme/black/wizard-groupware@2x.png | Bin 0 -> 4455 bytes theme/black/wizard-nextcloud.png | Bin 0 -> 3410 bytes theme/black/wizard-nextcloud.svg | 81 + theme/black/wizard-nextcloud@2x.png | Bin 0 -> 7396 bytes theme/black/wizard-talk.png | Bin 0 -> 1954 bytes theme/black/wizard-talk.svg | 1 + theme/black/wizard-talk@2x.png | Bin 0 -> 4303 bytes theme/call-notification.wav | Bin 0 -> 919394 bytes .../cfapishellext_custom_states/0-locked.svg | 1 + .../cfapishellext_custom_states/1-shared.svg | 1 + .../1024-0-locked.png | Bin 0 -> 12483 bytes .../1024-1-shared.png | Bin 0 -> 20840 bytes .../128-0-locked.png | Bin 0 -> 1064 bytes .../128-1-shared.png | Bin 0 -> 1424 bytes .../24-0-locked.png | Bin 0 -> 325 bytes .../24-1-shared.png | Bin 0 -> 405 bytes .../256-0-locked.png | Bin 0 -> 2257 bytes .../256-1-shared.png | Bin 0 -> 3666 bytes .../32-0-locked.png | Bin 0 -> 314 bytes .../32-1-shared.png | Bin 0 -> 379 bytes .../40-0-locked.png | Bin 0 -> 439 bytes .../40-1-shared.png | Bin 0 -> 566 bytes .../48-0-locked.png | Bin 0 -> 459 bytes .../48-1-shared.png | Bin 0 -> 585 bytes .../512-0-locked.png | Bin 0 -> 5037 bytes .../512-1-shared.png | Bin 0 -> 9135 bytes .../64-0-locked.png | Bin 0 -> 580 bytes .../64-1-shared.png | Bin 0 -> 656 bytes theme/change.svg | 1 + theme/chevron-double-up.svg | 1 + theme/close.svg | 1 + theme/colored/Nextcloud-icon-square.svg | 11 + theme/colored/Nextcloud-icon.svg | 121 + theme/colored/Nextcloud-macOS-icon.svg | 287 + theme/colored/Nextcloud-macOS-sidebar.svg | 7 + theme/colored/Nextcloud-w10startmenu.svg | 121 + theme/colored/Nextcloud-w10starttile.png | Bin 0 -> 547962 bytes theme/colored/add-bordered.svg | 19 + theme/colored/add.svg | 1 + theme/colored/change-bordered.svg | 1 + theme/colored/delete-bordered.svg | 19 + theme/colored/delete.svg | 1 + theme/colored/external.png | Bin 0 -> 2473 bytes theme/colored/external.svg | 1 + theme/colored/external@2x.png | Bin 0 -> 3117 bytes theme/colored/folder.png | Bin 0 -> 2272 bytes theme/colored/folder.svg | 5 + theme/colored/folder@2x.png | Bin 0 -> 2863 bytes .../icons/Nextcloud-icon-win-folder.svg | 278 + theme/colored/state-error.svg | 1 + theme/colored/state-offline.svg | 1 + theme/colored/state-ok.svg | 1 + theme/colored/state-pause.svg | 1 + theme/colored/state-sync.svg | 1 + theme/colored/state-warning.svg | 1 + theme/colored/talk-bordered.svg | 19 + theme/colored/user-status-away.svg | 1 + theme/colored/user-status-dnd.svg | 1 + theme/colored/user-status-invisible.svg | 1 + theme/colored/user-status-online.svg | 1 + theme/colored/wizard-files.png | Bin 0 -> 3097 bytes theme/colored/wizard-files.svg | 1 + theme/colored/wizard-files@2x.png | Bin 0 -> 4587 bytes theme/colored/wizard-groupware.png | Bin 0 -> 3307 bytes theme/colored/wizard-groupware.svg | 1 + theme/colored/wizard-groupware@2x.png | Bin 0 -> 5126 bytes theme/colored/wizard-nextcloud.png | Bin 0 -> 5228 bytes theme/colored/wizard-nextcloud.svg | 81 + theme/colored/wizard-nextcloud@2x.png | Bin 0 -> 11010 bytes theme/colored/wizard-talk.png | Bin 0 -> 2976 bytes theme/colored/wizard-talk.svg | 1 + theme/colored/wizard-talk@2x.png | Bin 0 -> 6145 bytes theme/colored/wizard_logo.png | Bin 0 -> 2215 bytes theme/colored/wizard_logo.svg | 2 + theme/colored/wizard_logo@2x.png | Bin 0 -> 3566 bytes theme/confirm.svg | 1 + theme/copy.svg | 1 + theme/delete.svg | 1 + theme/external.svg | 1 + theme/files.svg | 1 + theme/lock-broken.svg | 1 + theme/lock-http.svg | 1 + theme/lock-https.svg | 1 + theme/lock.svg | 1 + theme/magnifying-glass.svg | 1 + theme/more.svg | 1 + theme/network.svg | 1 + theme/nextcloud.VisualElementsManifest.xml | 7 + theme/public.svg | 1 + theme/reply.svg | 1 + theme/send.svg | 1 + theme/settings.svg | 1 + theme/share.svg | 1 + theme/sync-arrow.svg | 1 + theme/talk-app.svg | 40 + theme/white/activity.svg | 1 + theme/white/add.svg | 1 + theme/white/bell.svg | 1 + theme/white/calendar.svg | 1 + theme/white/caret-down.svg | 1 + theme/white/change.svg | 1 + theme/white/close.svg | 1 + theme/white/comment.svg | 1 + theme/white/confirm.svg | 1 + theme/white/control-next.svg | 9 + theme/white/control-prev.svg | 9 + theme/white/deck.svg | 8 + theme/white/edit.svg | 1 + theme/white/email.svg | 1 + theme/white/external.png | Bin 0 -> 2508 bytes theme/white/external.svg | 1 + theme/white/external@2x.png | Bin 0 -> 3130 bytes theme/white/folder.png | Bin 0 -> 1954 bytes theme/white/folder.svg | 1 + theme/white/folder@2x.png | Bin 0 -> 2321 bytes theme/white/more-apps.svg | 1 + theme/white/nc-assistant-app.svg | 3 + theme/white/settings.svg | 1 + theme/white/state-error.svg | 1 + theme/white/state-info.svg | 1 + theme/white/state-offline.svg | 1 + theme/white/state-ok.svg | 1 + theme/white/state-pause.svg | 1 + theme/white/state-sync.svg | 1 + theme/white/state-warning.svg | 1 + theme/white/talk-app.svg | 1 + theme/white/user.svg | 1 + theme/white/wizard-files.png | Bin 0 -> 3089 bytes theme/white/wizard-files.svg | 1 + theme/white/wizard-files@2x.png | Bin 0 -> 4652 bytes theme/white/wizard-groupware.png | Bin 0 -> 3181 bytes theme/white/wizard-groupware.svg | 1 + theme/white/wizard-groupware@2x.png | Bin 0 -> 5059 bytes theme/white/wizard-nextcloud.png | Bin 0 -> 4075 bytes theme/white/wizard-nextcloud.svg | 81 + theme/white/wizard-nextcloud@2x.png | Bin 0 -> 9394 bytes theme/white/wizard-talk.png | Bin 0 -> 2301 bytes theme/white/wizard-talk.svg | 1 + theme/white/wizard-talk@2x.png | Bin 0 -> 5282 bytes translations/client_TW.ts | 1885 +++++ translations/client_af.ts | 4828 +++++++++++ translations/client_ar.ts | 6850 ++++++++++++++++ translations/client_bg.ts | 6851 ++++++++++++++++ translations/client_br.ts | 6832 ++++++++++++++++ translations/client_ca.ts | 6832 ++++++++++++++++ translations/client_cs.ts | 6869 ++++++++++++++++ translations/client_da.ts | 6841 ++++++++++++++++ translations/client_de.ts | 6869 ++++++++++++++++ translations/client_el.ts | 6834 ++++++++++++++++ translations/client_en.ts | 4068 ++++++++++ translations/client_en_GB.ts | 6871 ++++++++++++++++ translations/client_eo.ts | 6830 ++++++++++++++++ translations/client_es.ts | 6867 ++++++++++++++++ translations/client_es_AR.ts | 7036 +++++++++++++++++ translations/client_es_CL.ts | 6823 ++++++++++++++++ translations/client_es_CO.ts | 6823 ++++++++++++++++ translations/client_es_CR.ts | 6823 ++++++++++++++++ translations/client_es_DO.ts | 6823 ++++++++++++++++ translations/client_es_EC.ts | 6850 ++++++++++++++++ translations/client_es_GT.ts | 6823 ++++++++++++++++ translations/client_es_HN.ts | 6823 ++++++++++++++++ translations/client_es_MX.ts | 6856 ++++++++++++++++ translations/client_es_SV.ts | 6823 ++++++++++++++++ translations/client_et.ts | 6739 ++++++++++++++++ translations/client_eu.ts | 6866 ++++++++++++++++ translations/client_fa.ts | 6849 ++++++++++++++++ translations/client_fi.ts | 6834 ++++++++++++++++ translations/client_fr.ts | 6868 ++++++++++++++++ translations/client_ga.ts | 6871 ++++++++++++++++ translations/client_gl.ts | 6870 ++++++++++++++++ translations/client_he.ts | 6828 ++++++++++++++++ translations/client_hr.ts | 6848 ++++++++++++++++ translations/client_hu.ts | 6871 ++++++++++++++++ translations/client_id.ts | 6171 +++++++++++++++ translations/client_is.ts | 6860 ++++++++++++++++ translations/client_it.ts | 6865 ++++++++++++++++ translations/client_ja.ts | 6870 ++++++++++++++++ translations/client_ko.ts | 6868 ++++++++++++++++ translations/client_lt_LT.ts | 6831 ++++++++++++++++ translations/client_lv.ts | 6838 ++++++++++++++++ translations/client_mk.ts | 6829 ++++++++++++++++ translations/client_nb_NO.ts | 6855 ++++++++++++++++ translations/client_nl.ts | 6854 ++++++++++++++++ translations/client_oc.ts | 6821 ++++++++++++++++ translations/client_pl.ts | 6870 ++++++++++++++++ translations/client_pt.ts | 6825 ++++++++++++++++ translations/client_pt_BR.ts | 6864 ++++++++++++++++ translations/client_ro.ts | 6833 ++++++++++++++++ translations/client_ru.ts | 6862 ++++++++++++++++ translations/client_sc.ts | 6847 ++++++++++++++++ translations/client_sk.ts | 6870 ++++++++++++++++ translations/client_sl.ts | 6848 ++++++++++++++++ translations/client_sr.ts | 6871 ++++++++++++++++ translations/client_sv.ts | 6871 ++++++++++++++++ translations/client_th.ts | 6830 ++++++++++++++++ translations/client_tr.ts | 6869 ++++++++++++++++ translations/client_ug.ts | 6867 ++++++++++++++++ translations/client_uk.ts | 6869 ++++++++++++++++ translations/client_zh_CN.ts | 6860 ++++++++++++++++ translations/client_zh_HK.ts | 6872 ++++++++++++++++ translations/client_zh_TW.ts | 6871 ++++++++++++++++ version.h.in | 52 + 1894 files changed, 689432 insertions(+) create mode 100644 .clang-format create mode 100644 .drone.yml create mode 100644 .git-blame-ignore-revs create mode 100644 .github/ISSUE_TEMPLATE/BUG_REPORT.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/check-translations.yml create mode 100644 .github/workflows/clang-format.yml create mode 100644 .github/workflows/clang-tidy-review.yml create mode 100644 .github/workflows/fixup.yml create mode 100644 .github/workflows/linux-appimage.yml create mode 100644 .github/workflows/linux-clang-compile-tests.yml create mode 100644 .github/workflows/linux-gcc-compile-tests.yml create mode 100644 .github/workflows/macos-build-and-test.yml create mode 100644 .github/workflows/needsinfo.yml create mode 100644 .github/workflows/needsinfohelper.yaml create mode 100644 .github/workflows/qml-label-check.yml create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 .github/workflows/stale.yml create mode 100644 .github/workflows/windows-build-and-test.yml create mode 100644 .gitmodules create mode 100644 .swift-format.json create mode 100644 .tag create mode 100644 .tx/config create mode 100644 .tx/nextcloud.client-desktop/ar_translation create mode 100644 .tx/nextcloud.client-desktop/bg_translation create mode 100644 .tx/nextcloud.client-desktop/br_translation create mode 100644 .tx/nextcloud.client-desktop/ca_translation create mode 100644 .tx/nextcloud.client-desktop/cs_translation create mode 100644 .tx/nextcloud.client-desktop/cy_GB_translation create mode 100644 .tx/nextcloud.client-desktop/da_translation create mode 100644 .tx/nextcloud.client-desktop/de_translation create mode 100644 .tx/nextcloud.client-desktop/el_translation create mode 100644 .tx/nextcloud.client-desktop/en_GB_translation create mode 100644 .tx/nextcloud.client-desktop/eo_translation create mode 100644 .tx/nextcloud.client-desktop/es_AR_translation create mode 100644 .tx/nextcloud.client-desktop/es_CL_translation create mode 100644 .tx/nextcloud.client-desktop/es_CO_translation create mode 100644 .tx/nextcloud.client-desktop/es_CR_translation create mode 100644 .tx/nextcloud.client-desktop/es_DO_translation create mode 100644 .tx/nextcloud.client-desktop/es_EC_translation create mode 100644 .tx/nextcloud.client-desktop/es_GT_translation create mode 100644 .tx/nextcloud.client-desktop/es_MX_translation create mode 100644 .tx/nextcloud.client-desktop/es_SV_translation create mode 100644 .tx/nextcloud.client-desktop/es_translation create mode 100644 .tx/nextcloud.client-desktop/et_translation create mode 100644 .tx/nextcloud.client-desktop/eu_translation create mode 100644 .tx/nextcloud.client-desktop/fa_translation create mode 100644 .tx/nextcloud.client-desktop/fi_translation create mode 100644 .tx/nextcloud.client-desktop/fr_translation create mode 100644 .tx/nextcloud.client-desktop/gl_translation create mode 100644 .tx/nextcloud.client-desktop/he_translation create mode 100644 .tx/nextcloud.client-desktop/hr_translation create mode 100644 .tx/nextcloud.client-desktop/hu_translation create mode 100644 .tx/nextcloud.client-desktop/id_translation create mode 100644 .tx/nextcloud.client-desktop/is_translation create mode 100644 .tx/nextcloud.client-desktop/it_translation create mode 100644 .tx/nextcloud.client-desktop/ja_translation create mode 100644 .tx/nextcloud.client-desktop/ko_translation create mode 100644 .tx/nextcloud.client-desktop/lt_LT_translation create mode 100644 .tx/nextcloud.client-desktop/lv_translation create mode 100644 .tx/nextcloud.client-desktop/mk_translation create mode 100644 .tx/nextcloud.client-desktop/nb_translation create mode 100644 .tx/nextcloud.client-desktop/nl_translation create mode 100644 .tx/nextcloud.client-desktop/oc_translation create mode 100644 .tx/nextcloud.client-desktop/pl_translation create mode 100644 .tx/nextcloud.client-desktop/pt_BR_translation create mode 100644 .tx/nextcloud.client-desktop/pt_translation create mode 100644 .tx/nextcloud.client-desktop/ro_translation create mode 100644 .tx/nextcloud.client-desktop/ru_translation create mode 100644 .tx/nextcloud.client-desktop/sc_translation create mode 100644 .tx/nextcloud.client-desktop/sk_translation create mode 100644 .tx/nextcloud.client-desktop/sl_translation create mode 100644 .tx/nextcloud.client-desktop/sr_translation create mode 100644 .tx/nextcloud.client-desktop/sv_translation create mode 100644 .tx/nextcloud.client-desktop/sw_translation create mode 100644 .tx/nextcloud.client-desktop/th_translation create mode 100644 .tx/nextcloud.client-desktop/tr_translation create mode 100644 .tx/nextcloud.client-desktop/uk_translation create mode 100644 .tx/nextcloud.client-desktop/vi_translation create mode 100644 .tx/nextcloud.client-desktop/zh_CN_translation create mode 100644 .tx/nextcloud.client-desktop/zh_HK_translation create mode 100644 .tx/nextcloud.client-desktop/zh_TW_translation create mode 100644 AUTHORS.md create mode 100644 CHANGELOG.md create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md create mode 100644 COPYING create mode 100644 COPYING.documentation create mode 100644 CPackOptions.cmake.in create mode 100644 ChangeLog - Legacy create mode 100644 NEXTCLOUD.cmake create mode 100644 NextcloudCPack.cmake create mode 100644 README.md create mode 100644 VERSION.cmake create mode 100644 admin/CMakeLists.txt create mode 100755 admin/linux/build-appimage.sh create mode 100755 admin/linux/clean_tarball.sh create mode 100755 admin/linux/debian/drone-build.sh create mode 100644 admin/linux/debian/oscrc.enc create mode 100644 admin/linux/debian/scripts/git2changelog.cfg create mode 100755 admin/linux/debian/scripts/git2changelog.py create mode 100644 admin/linux/debian/signing-key.txt.enc create mode 100644 admin/nix/flake.nix create mode 100644 admin/osx/CMakeLists.txt create mode 100644 admin/osx/DMGBackground.png create mode 100644 admin/osx/DS_Store.in create mode 100755 admin/osx/create_mac.sh.cmake create mode 100644 admin/osx/deny_autoupdate_com.owncloud.desktopclient.plist create mode 100755 admin/osx/gen_sym_files.py create mode 100644 admin/osx/installer-background.png create mode 100644 admin/osx/installer-background.svg create mode 100644 admin/osx/installer-background_2x.png create mode 100644 admin/osx/mac-crafter/Package.swift create mode 100644 admin/osx/mac-crafter/README.md create mode 100644 admin/osx/mac-crafter/Sources/Utils/Codesign.swift create mode 100644 admin/osx/mac-crafter/Sources/Utils/Craft.swift create mode 100644 admin/osx/mac-crafter/Sources/Utils/Install.swift create mode 100644 admin/osx/mac-crafter/Sources/Utils/Packaging.swift create mode 100644 admin/osx/mac-crafter/Sources/Utils/Shell.swift create mode 100644 admin/osx/mac-crafter/Sources/main.swift create mode 100644 admin/osx/macosx.pkgproj.cmake create mode 100755 admin/osx/make_universal.py create mode 100644 admin/osx/post_install.sh.cmake create mode 100644 admin/osx/pre_install.sh.cmake create mode 100755 admin/osx/sign_app.sh create mode 100755 admin/osx/sign_dmg.sh create mode 100644 admin/osx/sparkle/dsa_pub.pem create mode 100644 admin/osx/sparkle/example_update_rss.rss create mode 100755 admin/test/wait_for_server.sh create mode 100644 admin/win/CMakeLists.txt create mode 100644 admin/win/Toolchain-mingw32-openSUSE.cmake create mode 100755 admin/win/create_stable_toolchain.sh create mode 100755 admin/win/download_runtimes.sh create mode 100644 admin/win/msi/CMakeLists.txt create mode 100644 admin/win/msi/Nextcloud.wxs create mode 100644 admin/win/msi/OEM.wxi.in create mode 100644 admin/win/msi/Platform.wxi create mode 100644 admin/win/msi/RegistryCleanup.vbs.in create mode 100644 admin/win/msi/RegistryCleanupCustomAction.wxs create mode 100644 admin/win/msi/collect-transform.xsl.in create mode 100644 admin/win/msi/gui/banner.bmp create mode 100644 admin/win/msi/gui/banner.svg create mode 100644 admin/win/msi/gui/dialog.bmp create mode 100644 admin/win/msi/make-msi.bat.in create mode 100644 admin/win/nsi/.directory create mode 100644 admin/win/nsi/README.md create mode 100644 admin/win/nsi/RELEASE_NOTES.txt create mode 100644 admin/win/nsi/installer.ico create mode 100644 admin/win/nsi/l10n/Basque.nsh create mode 100644 admin/win/nsi/l10n/Catalan.nsh create mode 100644 admin/win/nsi/l10n/Czech.nsh create mode 100644 admin/win/nsi/l10n/Dutch.nsh create mode 100644 admin/win/nsi/l10n/English.nsh create mode 100644 admin/win/nsi/l10n/Estonian.nsh create mode 100644 admin/win/nsi/l10n/Farsi.nsh create mode 100644 admin/win/nsi/l10n/Finnish.nsh create mode 100644 admin/win/nsi/l10n/French.nsh create mode 100644 admin/win/nsi/l10n/Galician.nsh create mode 100644 admin/win/nsi/l10n/German.nsh create mode 100644 admin/win/nsi/l10n/Greek.nsh create mode 100644 admin/win/nsi/l10n/Hungarian.nsh create mode 100644 admin/win/nsi/l10n/Italian.nsh create mode 100644 admin/win/nsi/l10n/Japanese.nsh create mode 100644 admin/win/nsi/l10n/Norwegian.nsh create mode 100644 admin/win/nsi/l10n/Polish.nsh create mode 100644 admin/win/nsi/l10n/Portuguese.nsh create mode 100644 admin/win/nsi/l10n/PortugueseBR.nsh create mode 100644 admin/win/nsi/l10n/Russian.nsh create mode 100644 admin/win/nsi/l10n/SimpChinese.nsh create mode 100644 admin/win/nsi/l10n/Slovak.nsh create mode 100644 admin/win/nsi/l10n/Slovenian.nsh create mode 100644 admin/win/nsi/l10n/Spanish.nsh create mode 100644 admin/win/nsi/l10n/SpanishInternational.nsh create mode 100644 admin/win/nsi/l10n/Swedish.nsh create mode 100644 admin/win/nsi/l10n/Thai.nsh create mode 100644 admin/win/nsi/l10n/Turkish.nsh create mode 100644 admin/win/nsi/l10n/Ukrainian.nsh create mode 100644 admin/win/nsi/l10n/declarations.nsh create mode 100644 admin/win/nsi/l10n/languages.nsh create mode 100644 admin/win/nsi/lib/fileassoc.nsh create mode 100644 admin/win/nsi/page_header.bmp create mode 100644 admin/win/nsi/qt.conf create mode 100644 admin/win/nsi/welcome.bmp create mode 100644 admin/win/tools/CMakeLists.txt create mode 100644 admin/win/tools/NCMsiHelper/CMakeLists.txt create mode 100644 admin/win/tools/NCMsiHelper/CustomAction.cpp create mode 100644 admin/win/tools/NCMsiHelper/CustomAction.def create mode 100644 admin/win/tools/NCMsiHelper/LogResult.cpp create mode 100644 admin/win/tools/NCMsiHelper/LogResult.h create mode 100644 admin/win/tools/NCMsiHelper/NCMsiHelper.cpp create mode 100644 admin/win/tools/NCMsiHelper/NCMsiHelper.h create mode 100644 admin/win/tools/NCMsiHelper/NCMsiHelper.wxs create mode 100644 admin/win/tools/NCNavRemove/CMakeLists.txt create mode 100644 admin/win/tools/NCNavRemove/ConfigIni.cpp create mode 100644 admin/win/tools/NCNavRemove/ConfigIni.h create mode 100644 admin/win/tools/NCNavRemove/NavRemove.ini.in create mode 100644 admin/win/tools/NCNavRemove/NavRemoveConstants.h.in create mode 100644 admin/win/tools/NCNavRemove/dll/CMakeLists.txt create mode 100644 admin/win/tools/NCNavRemove/dll/NavRemove.cpp create mode 100644 admin/win/tools/NCNavRemove/dll/NavRemove.h create mode 100644 admin/win/tools/NCNavRemove/dll/dllmain.cpp create mode 100644 admin/win/tools/NCNavRemove/dll/exports.def create mode 100644 admin/win/tools/NCNavRemove/exe/CMakeLists.txt create mode 100644 admin/win/tools/NCNavRemove/exe/main.cpp create mode 100644 admin/win/tools/NCNavRemove/version.rc.in create mode 100644 admin/win/tools/NCToolsShared/3rdparty/SimpleIni.h create mode 100644 admin/win/tools/NCToolsShared/CMakeLists.txt create mode 100644 admin/win/tools/NCToolsShared/SimpleNamedMutex.cpp create mode 100644 admin/win/tools/NCToolsShared/SimpleNamedMutex.h create mode 100644 admin/win/tools/NCToolsShared/utility.h create mode 100644 admin/win/tools/NCToolsShared/utility_win.cpp create mode 100644 cmake/modules/AddCMockaTest.cmake create mode 100644 cmake/modules/COPYING-CMAKE-SCRIPTS create mode 100644 cmake/modules/CheckCCompilerFlagSSP.cmake create mode 100644 cmake/modules/CheckPrototypeDefinition.c.in create mode 100644 cmake/modules/CheckPrototypeDefinition.cmake create mode 100644 cmake/modules/Copyright.txt create mode 100644 cmake/modules/DBusMacros.cmake create mode 100644 cmake/modules/DefineCMakeDefaults.cmake create mode 100644 cmake/modules/DefineCompilerFlags.cmake create mode 100644 cmake/modules/DefineInstallationPaths.cmake create mode 100644 cmake/modules/DefinePlatformDefaults.cmake create mode 100644 cmake/modules/DeployQt5.cmake create mode 100644 cmake/modules/ECMAddAppIcon.cmake create mode 100644 cmake/modules/ECMCoverageOption.cmake create mode 100644 cmake/modules/ECMEnableSanitizers.cmake create mode 100644 cmake/modules/ECMFindModuleHelpers.cmake create mode 100644 cmake/modules/ECMFindModuleHelpersStub.cmake create mode 100644 cmake/modules/FindCMocka.cmake create mode 100644 cmake/modules/FindInotify.cmake create mode 100644 cmake/modules/FindLibSSH.cmake create mode 100644 cmake/modules/FindPackageVersionCheck.cmake create mode 100644 cmake/modules/FindPdfLatex.cmake create mode 100644 cmake/modules/FindPng2Ico.cmake create mode 100644 cmake/modules/FindSMBClient.cmake create mode 100644 cmake/modules/FindSQLite3.cmake create mode 100644 cmake/modules/FindSharedMimeInfo.cmake create mode 100644 cmake/modules/FindSparkle.cmake create mode 100644 cmake/modules/FindSphinx.cmake create mode 100644 cmake/modules/GenerateIconsUtils.cmake create mode 100644 cmake/modules/GetGitRevisionDescription.cmake create mode 100644 cmake/modules/GetGitRevisionDescription.cmake.in create mode 100644 cmake/modules/MacOSXBundleInfo.plist.in create mode 100644 cmake/modules/MacroAddCompileFlags.cmake create mode 100644 cmake/modules/MacroAddLinkFlags.cmake create mode 100644 cmake/modules/MacroEnsureOutOfSourceBuild.cmake create mode 100644 cmake/modules/MacroLogFeature.cmake create mode 100644 cmake/modules/MacroOptionalFindPackage.cmake create mode 100644 cmake/modules/NSIS.InstallOptions.ini.in create mode 100644 cmake/modules/NSIS.template.in create mode 100644 cmake/modules/UseDoxygen.cmake create mode 100644 cmake/modules/Warnings.cmake create mode 100644 cmake/scripts/generate_findpackage_file create mode 100644 cmake/scripts/generate_lib_file create mode 100644 codecov.yml create mode 100644 config.h.in create mode 100644 craftmaster.ini create mode 100644 doc/CMakeLists.txt create mode 100644 doc/Makefile create mode 100644 doc/README.md create mode 100644 doc/_shared_assets/static/logo-blue.pdf create mode 100644 doc/_shared_assets/static/logo-blue.png create mode 100644 doc/_shared_assets/static/social/diaspora.svg create mode 100644 doc/_shared_assets/static/social/diasporaround.png create mode 100644 doc/_shared_assets/static/social/facebook.png create mode 100644 doc/_shared_assets/static/social/googleplus.png create mode 100644 doc/_shared_assets/static/social/mail.png create mode 100644 doc/_shared_assets/static/social/mail.svg create mode 100644 doc/_shared_assets/static/social/rss.png create mode 100644 doc/_shared_assets/static/social/rss.svg create mode 100644 doc/_shared_assets/static/social/twitter.svg create mode 100644 doc/_shared_assets/static/social/twitterround.png create mode 100644 doc/_shared_assets/static/social/youtube.svg create mode 100644 doc/_shared_assets/themes/bootstrap/globaltoc.html create mode 100644 doc/_shared_assets/themes/bootstrap/layout.html create mode 100644 doc/_shared_assets/themes/bootstrap/localtoc.html create mode 100644 doc/_shared_assets/themes/bootstrap/relations.html create mode 100644 doc/_shared_assets/themes/bootstrap/searchbox.html create mode 100644 doc/_shared_assets/themes/bootstrap/sourcelink.html create mode 100644 doc/_shared_assets/themes/bootstrap/static/bootstrap-responsive.css create mode 100644 doc/_shared_assets/themes/bootstrap/static/bootstrap-sphinx.css_t create mode 100644 doc/_shared_assets/themes/bootstrap/static/bootstrap.css create mode 100644 doc/_shared_assets/themes/bootstrap/static/bootstrap.js create mode 100644 doc/_shared_assets/themes/bootstrap/static/img/glyphicons-halflings-white.png create mode 100644 doc/_shared_assets/themes/bootstrap/static/img/glyphicons-halflings.png create mode 100644 doc/_shared_assets/themes/bootstrap/static/jquery.js create mode 100644 doc/_shared_assets/themes/bootstrap/theme.conf create mode 100644 doc/_shared_assets/themes/nextcloud_com/globaltoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/layout.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/localtoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/navbar-2.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/navbar.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/navbarsearchbox.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/navbartoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/relations.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/search.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/searchbox.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/searchresults.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/sourcelink.html create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap-theme.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap-theme.css.map create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap-theme.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap.css.map create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/css/bootstrap.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.eot create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.woff create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/js/bootstrap.js create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-3.1.0/js/bootstrap.min.js create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-sphinx.css_t create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/bootstrap-sphinx.js_t create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Bold.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Bold.woff create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Italic.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Italic.woff create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Light.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Light.woff create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Regular.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/fonts/OpenSans-Regular.woff create mode 100755 doc/_shared_assets/themes/nextcloud_com/static/fonts/fontawesome-webfont.eot create mode 100755 doc/_shared_assets/themes/nextcloud_com/static/fonts/fontawesome-webfont.svg create mode 100755 doc/_shared_assets/themes/nextcloud_com/static/fonts/fontawesome-webfont.ttf create mode 100755 doc/_shared_assets/themes/nextcloud_com/static/fonts/fontawesome-webfont.woff create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/home/background3.jpg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/logo.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/note_pencil.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/diaspora.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/diaspora.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/diasporaround.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/facebook.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/facebook.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/googleplus.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/googleplus.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/mail.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/rss.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/rss.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/twitter.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/twitter.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/twitterround.png create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/social/youtube.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/img/warning.svg create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/js/jquery-1.11.0.min.js create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/js/jquery-fix.js create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/main.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/static/styles.css create mode 100644 doc/_shared_assets/themes/nextcloud_com/theme.conf create mode 100644 doc/_shared_assets/themes/nextcloud_release/globaltoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/layout.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/localtoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/navbar-2.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/navbar.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/navbarsearchbox.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/navbartoc.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/relations.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/search.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/searchbox.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/searchresults.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/sourcelink.html create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap-theme.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap-theme.css.map create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap-theme.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap.css.map create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/css/bootstrap.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.eot create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/fonts/glyphicons-halflings-regular.woff create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/js/bootstrap.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-3.1.0/js/bootstrap.min.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-responsive.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-sphinx.css_t create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap-sphinx.js_t create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/bootstrap.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Bold.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Bold.woff create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Italic.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Italic.woff create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Light.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Light.woff create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Regular.ttf create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/fonts/OpenSans-Regular.woff create mode 100755 doc/_shared_assets/themes/nextcloud_release/static/fonts/fontawesome-webfont.eot create mode 100755 doc/_shared_assets/themes/nextcloud_release/static/fonts/fontawesome-webfont.svg create mode 100755 doc/_shared_assets/themes/nextcloud_release/static/fonts/fontawesome-webfont.ttf create mode 100755 doc/_shared_assets/themes/nextcloud_release/static/fonts/fontawesome-webfont.woff create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/glyphicons-halflings-white.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/glyphicons-halflings.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/note.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/note_pencil.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/diaspora.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/diaspora.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/diasporaround.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/facebook.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/facebook.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/googleplus.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/googleplus.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/mail.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/rss.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/rss.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/twitter.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/twitter.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/twitterround.png create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/social/youtube.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/todo.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/img/warning.svg create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/jquery.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/js/jquery-1.11.0.min.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/js/jquery-fix.js create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/main.min.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/static/styles.css create mode 100644 doc/_shared_assets/themes/nextcloud_release/theme.conf create mode 100644 doc/advancedusage.rst create mode 100644 doc/architecture.rst create mode 100644 doc/autoupdate.rst create mode 100644 doc/building.rst create mode 100644 doc/conf.py create mode 100644 doc/conffile.rst create mode 100644 doc/conflicts.rst create mode 100644 doc/dev/CMakeLists.txt create mode 100644 doc/dev/Doxyfile.in create mode 100644 doc/dev/main-page.md create mode 100644 doc/dev/sync-algorithm.md create mode 100644 doc/envvars.rst create mode 100644 doc/faq.rst create mode 100644 doc/glossary.rst create mode 100644 doc/images/checksums/client-activity.png create mode 100644 doc/images/checksums/testing-checksums.png create mode 100644 doc/images/create_debug_archive.png create mode 100644 doc/images/dev/desktop-development-with-cpp.png create mode 100644 doc/images/dev/path.png create mode 100644 doc/images/dev/visual-studio-installer.png create mode 100644 doc/images/folderwizard_local.png create mode 100644 doc/images/folderwizard_remote.png create mode 100644 doc/images/general_settings_folder_context_menu.png create mode 100644 doc/images/icon-error.png create mode 100644 doc/images/icon-information.png create mode 100644 doc/images/icon-offline.png create mode 100644 doc/images/icon-paused.png create mode 100644 doc/images/icon-syncing.png create mode 100644 doc/images/icon.png create mode 100644 doc/images/ignored_files_editor.png create mode 100644 doc/images/log_output_window.png create mode 100644 doc/images/mac-share.png create mode 100644 doc/images/macosvfs-file-locking.png create mode 100644 doc/images/macosvfs-file-sharing.png create mode 100644 doc/images/macosvfs-finder-sidebar.png create mode 100644 doc/images/macosvfs-settings.png create mode 100644 doc/images/macosvfs-sync-status-icons.png create mode 100644 doc/images/main_dialog.png create mode 100644 doc/images/main_dialog_christine.png create mode 100644 doc/images/open-share-dialog.png create mode 100644 doc/images/save_log_file.png create mode 100644 doc/images/set-user-status-menu.png create mode 100644 doc/images/set-user-status.png create mode 100644 doc/images/settings_general.png create mode 100644 doc/images/settings_network.png create mode 100644 doc/images/settingsdialog.png create mode 100644 doc/images/setup/confirm.png create mode 100644 doc/images/setup/remove.png create mode 100644 doc/images/setup/wizard.png create mode 100644 doc/images/share-dialog-view-profile.png create mode 100644 doc/images/share_context_menu.png create mode 100644 doc/images/share_dialog.png create mode 100644 doc/images/status_feature_example.png create mode 100644 doc/images/sync-state-paused.png create mode 100644 doc/images/sync-state-synced.png create mode 100644 doc/images/sync-state-syncing.png create mode 100644 doc/images/sync-state-warnings.png create mode 100644 doc/images/traymenu.png create mode 100644 doc/images/unified-search-events.png create mode 100644 doc/images/unified-search-files.png create mode 100644 doc/images/unified-search-talk.png create mode 100644 doc/images/user-account-options.png create mode 100644 doc/images/user_status-selector_dialog.png create mode 100644 doc/images/user_status_selector_main_dialog.png create mode 100644 doc/images/vfs_context_menu_options.png create mode 100644 doc/images/vfs_hydration_progress_bar.png create mode 100644 doc/images/wizard_advanced.png create mode 100644 doc/images/wizard_flow2.png create mode 100644 doc/images/wizard_setup.png create mode 100644 doc/images/wizard_welcome.png create mode 100644 doc/index.rst create mode 100644 doc/installing.rst create mode 100644 doc/introduction.rst create mode 100644 doc/logo-blue.pdf create mode 100644 doc/lowdiskspace.rst create mode 100644 doc/macosvfs.rst create mode 100644 doc/massdeploymentcommandline.rst create mode 100644 doc/navigating.rst create mode 100644 doc/nextcloudcmd.rst create mode 100644 doc/options-cmd.rst create mode 100644 doc/options.rst create mode 100644 doc/scripts/README.rst create mode 100755 doc/scripts/htmlhelp.reg create mode 100755 doc/scripts/htmlhelp.sh create mode 100644 doc/troubleshooting.rst create mode 100644 doc/visualtour.rst create mode 100644 doc/wizardaccountsetupcommandline.rst create mode 100644 man/CMakeLists.txt create mode 100644 man/index.rst create mode 100644 man/nextcloud.1.rst create mode 100644 man/nextcloudcmd.1.rst create mode 100644 mirall.desktop.in create mode 100644 nextcloud.client-desktop/ar_translation create mode 100644 nextcloud.client-desktop/ar_translation.desktop create mode 100644 nextcloud.client-desktop/ast_translation.desktop create mode 100644 nextcloud.client-desktop/bg_translation create mode 100644 nextcloud.client-desktop/bg_translation.desktop create mode 100644 nextcloud.client-desktop/br_translation create mode 100644 nextcloud.client-desktop/br_translation.desktop create mode 100644 nextcloud.client-desktop/ca_translation create mode 100644 nextcloud.client-desktop/ca_translation.desktop create mode 100644 nextcloud.client-desktop/cs_translation create mode 100644 nextcloud.client-desktop/cs_translation.desktop create mode 100644 nextcloud.client-desktop/cy_GB_translation create mode 100644 nextcloud.client-desktop/cy_GB_translation.desktop create mode 100644 nextcloud.client-desktop/da_translation create mode 100644 nextcloud.client-desktop/da_translation.desktop create mode 100644 nextcloud.client-desktop/de_translation create mode 100644 nextcloud.client-desktop/de_translation.desktop create mode 100644 nextcloud.client-desktop/el_translation create mode 100644 nextcloud.client-desktop/el_translation.desktop create mode 100644 nextcloud.client-desktop/en_GB_translation create mode 100644 nextcloud.client-desktop/en_GB_translation.desktop create mode 100644 nextcloud.client-desktop/eo_translation create mode 100644 nextcloud.client-desktop/eo_translation.desktop create mode 100644 nextcloud.client-desktop/es_AR_translation create mode 100644 nextcloud.client-desktop/es_AR_translation.desktop create mode 100644 nextcloud.client-desktop/es_CL_translation create mode 100644 nextcloud.client-desktop/es_CL_translation.desktop create mode 100644 nextcloud.client-desktop/es_CO_translation create mode 100644 nextcloud.client-desktop/es_CO_translation.desktop create mode 100644 nextcloud.client-desktop/es_CR_translation create mode 100644 nextcloud.client-desktop/es_CR_translation.desktop create mode 100644 nextcloud.client-desktop/es_DO_translation create mode 100644 nextcloud.client-desktop/es_DO_translation.desktop create mode 100644 nextcloud.client-desktop/es_EC_translation create mode 100644 nextcloud.client-desktop/es_EC_translation.desktop create mode 100644 nextcloud.client-desktop/es_GT_translation create mode 100644 nextcloud.client-desktop/es_GT_translation.desktop create mode 100644 nextcloud.client-desktop/es_MX_translation create mode 100644 nextcloud.client-desktop/es_MX_translation.desktop create mode 100644 nextcloud.client-desktop/es_SV_translation create mode 100644 nextcloud.client-desktop/es_SV_translation.desktop create mode 100644 nextcloud.client-desktop/es_translation create mode 100644 nextcloud.client-desktop/es_translation.desktop create mode 100644 nextcloud.client-desktop/et_translation create mode 100644 nextcloud.client-desktop/et_translation.desktop create mode 100644 nextcloud.client-desktop/eu_translation create mode 100644 nextcloud.client-desktop/eu_translation.desktop create mode 100644 nextcloud.client-desktop/fa_translation create mode 100644 nextcloud.client-desktop/fa_translation.desktop create mode 100644 nextcloud.client-desktop/fi_translation create mode 100644 nextcloud.client-desktop/fi_translation.desktop create mode 100644 nextcloud.client-desktop/fr_translation create mode 100644 nextcloud.client-desktop/fr_translation.desktop create mode 100644 nextcloud.client-desktop/ga_translation.desktop create mode 100644 nextcloud.client-desktop/gl_translation create mode 100644 nextcloud.client-desktop/gl_translation.desktop create mode 100644 nextcloud.client-desktop/he_translation create mode 100644 nextcloud.client-desktop/he_translation.desktop create mode 100644 nextcloud.client-desktop/hr_translation create mode 100644 nextcloud.client-desktop/hr_translation.desktop create mode 100644 nextcloud.client-desktop/hu_translation create mode 100644 nextcloud.client-desktop/hu_translation.desktop create mode 100644 nextcloud.client-desktop/id_translation create mode 100644 nextcloud.client-desktop/id_translation.desktop create mode 100644 nextcloud.client-desktop/is_translation create mode 100644 nextcloud.client-desktop/is_translation.desktop create mode 100644 nextcloud.client-desktop/it_translation create mode 100644 nextcloud.client-desktop/it_translation.desktop create mode 100644 nextcloud.client-desktop/ja_translation create mode 100644 nextcloud.client-desktop/ja_translation.desktop create mode 100644 nextcloud.client-desktop/kab_translation.desktop create mode 100644 nextcloud.client-desktop/ko_translation create mode 100644 nextcloud.client-desktop/ko_translation.desktop create mode 100644 nextcloud.client-desktop/lt_LT_translation create mode 100644 nextcloud.client-desktop/lt_LT_translation.desktop create mode 100644 nextcloud.client-desktop/lv_translation create mode 100644 nextcloud.client-desktop/lv_translation.desktop create mode 100644 nextcloud.client-desktop/mk_translation create mode 100644 nextcloud.client-desktop/mk_translation.desktop create mode 100644 nextcloud.client-desktop/nb_translation create mode 100644 nextcloud.client-desktop/nb_translation.desktop create mode 100644 nextcloud.client-desktop/nl_translation create mode 100644 nextcloud.client-desktop/nl_translation.desktop create mode 100644 nextcloud.client-desktop/oc_translation create mode 100644 nextcloud.client-desktop/oc_translation.desktop create mode 100644 nextcloud.client-desktop/pl_translation create mode 100644 nextcloud.client-desktop/pl_translation.desktop create mode 100644 nextcloud.client-desktop/pt_BR_translation create mode 100644 nextcloud.client-desktop/pt_BR_translation.desktop create mode 100644 nextcloud.client-desktop/pt_translation create mode 100644 nextcloud.client-desktop/pt_translation.desktop create mode 100644 nextcloud.client-desktop/ro_translation create mode 100644 nextcloud.client-desktop/ro_translation.desktop create mode 100644 nextcloud.client-desktop/ru_translation create mode 100644 nextcloud.client-desktop/ru_translation.desktop create mode 100644 nextcloud.client-desktop/sc_translation create mode 100644 nextcloud.client-desktop/sc_translation.desktop create mode 100644 nextcloud.client-desktop/sk_translation create mode 100644 nextcloud.client-desktop/sk_translation.desktop create mode 100644 nextcloud.client-desktop/sl_translation create mode 100644 nextcloud.client-desktop/sl_translation.desktop create mode 100644 nextcloud.client-desktop/sr_translation create mode 100644 nextcloud.client-desktop/sr_translation.desktop create mode 100644 nextcloud.client-desktop/sv_translation create mode 100644 nextcloud.client-desktop/sv_translation.desktop create mode 100644 nextcloud.client-desktop/sw_translation create mode 100644 nextcloud.client-desktop/sw_translation.desktop create mode 100644 nextcloud.client-desktop/th_translation create mode 100644 nextcloud.client-desktop/th_translation.desktop create mode 100644 nextcloud.client-desktop/tr_translation create mode 100644 nextcloud.client-desktop/tr_translation.desktop create mode 100644 nextcloud.client-desktop/uk_translation create mode 100644 nextcloud.client-desktop/uk_translation.desktop create mode 100644 nextcloud.client-desktop/vi_translation create mode 100644 nextcloud.client-desktop/vi_translation.desktop create mode 100644 nextcloud.client-desktop/zh_CN_translation create mode 100644 nextcloud.client-desktop/zh_CN_translation.desktop create mode 100644 nextcloud.client-desktop/zh_HK_translation create mode 100644 nextcloud.client-desktop/zh_HK_translation.desktop create mode 100644 nextcloud.client-desktop/zh_TW_translation create mode 100644 nextcloud.client-desktop/zh_TW_translation.desktop create mode 100644 resources.qrc create mode 100644 shell_integration/CMakeLists.txt create mode 100644 shell_integration/MacOSX/CMakeLists.txt create mode 100644 shell_integration/MacOSX/Nextcloud.xcworkspace/contents.xcworkspacedata create mode 100644 shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 shell_integration/MacOSX/Nextcloud.xcworkspace/xcshareddata/OwnCloud.xccheckout create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderConfig.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt-Bridging-Header.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+EnumerationListener.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/ClientCommunicationProtocol.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/ClientCommunicationService.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionService.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionServiceSource.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/DocumentActionViewController.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/Logger+Extensions.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/NKShare+Extensions.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderCommunication.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Info.plist create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Locking/LockViewController.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Locking/LockViewController.xib create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/MetadataProvider.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareController.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareOptionsView.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareTableItemView.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareTableItemView.xib create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareTableViewDataSource.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareViewController.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareViewController.xib create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareViewDataSourceUIDelegate.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareeSuggestionsDataSource.swift create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncExt.entitlements create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/Info.plist create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/SyncClient.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme create mode 100644 shell_integration/MacOSX/NextcloudIntegration/desktopclient/Info.plist create mode 100644 shell_integration/MacOSX/NextcloudIntegration/desktopclient/main.m create mode 100644 shell_integration/dolphin/CMakeLists.txt create mode 100644 shell_integration/dolphin/README create mode 100644 shell_integration/dolphin/ownclouddolphinactionplugin.cpp create mode 100644 shell_integration/dolphin/ownclouddolphinactionplugin.json.in create mode 100644 shell_integration/dolphin/ownclouddolphinoverlayplugin.cpp create mode 100644 shell_integration/dolphin/ownclouddolphinoverlayplugin.json create mode 100644 shell_integration/dolphin/ownclouddolphinpluginhelper.cpp create mode 100644 shell_integration/dolphin/ownclouddolphinpluginhelper.h create mode 100644 shell_integration/icons/1024x1024/oC_error.png create mode 100644 shell_integration/icons/1024x1024/oC_error_shared.png create mode 100644 shell_integration/icons/1024x1024/oC_ok.png create mode 100644 shell_integration/icons/1024x1024/oC_ok_shared.png create mode 100644 shell_integration/icons/1024x1024/oC_sync.png create mode 100644 shell_integration/icons/1024x1024/oC_sync_shared.png create mode 100644 shell_integration/icons/1024x1024/oC_warn.png create mode 100644 shell_integration/icons/1024x1024/oC_warn_shared.png create mode 100644 shell_integration/icons/128x128/oC_error.png create mode 100644 shell_integration/icons/128x128/oC_error_shared.png create mode 100644 shell_integration/icons/128x128/oC_ok.png create mode 100644 shell_integration/icons/128x128/oC_ok_shared.png create mode 100644 shell_integration/icons/128x128/oC_sync.png create mode 100644 shell_integration/icons/128x128/oC_sync_shared.png create mode 100644 shell_integration/icons/128x128/oC_warn.png create mode 100644 shell_integration/icons/128x128/oC_warn_shared.png create mode 100644 shell_integration/icons/16x16/oC_error.png create mode 100644 shell_integration/icons/16x16/oC_error_shared.png create mode 100644 shell_integration/icons/16x16/oC_ok.png create mode 100644 shell_integration/icons/16x16/oC_ok_shared.png create mode 100644 shell_integration/icons/16x16/oC_sync.png create mode 100644 shell_integration/icons/16x16/oC_sync_shared.png create mode 100644 shell_integration/icons/16x16/oC_warn.png create mode 100644 shell_integration/icons/16x16/oC_warn_shared.png create mode 100644 shell_integration/icons/256x256/oC_error.png create mode 100644 shell_integration/icons/256x256/oC_error_shared.png create mode 100644 shell_integration/icons/256x256/oC_ok.png create mode 100644 shell_integration/icons/256x256/oC_ok_shared.png create mode 100644 shell_integration/icons/256x256/oC_sync.png create mode 100644 shell_integration/icons/256x256/oC_sync_shared.png create mode 100644 shell_integration/icons/256x256/oC_warn.png create mode 100644 shell_integration/icons/256x256/oC_warn_shared.png create mode 100644 shell_integration/icons/32x32/oC_error.png create mode 100644 shell_integration/icons/32x32/oC_error_shared.png create mode 100644 shell_integration/icons/32x32/oC_ok.png create mode 100644 shell_integration/icons/32x32/oC_ok_shared.png create mode 100644 shell_integration/icons/32x32/oC_sync.png create mode 100644 shell_integration/icons/32x32/oC_sync_shared.png create mode 100644 shell_integration/icons/32x32/oC_warn.png create mode 100644 shell_integration/icons/32x32/oC_warn_shared.png create mode 100644 shell_integration/icons/48x48/oC_error.png create mode 100644 shell_integration/icons/48x48/oC_error_shared.png create mode 100644 shell_integration/icons/48x48/oC_ok.png create mode 100644 shell_integration/icons/48x48/oC_ok_shared.png create mode 100644 shell_integration/icons/48x48/oC_sync.png create mode 100644 shell_integration/icons/48x48/oC_sync_shared.png create mode 100644 shell_integration/icons/48x48/oC_warn.png create mode 100644 shell_integration/icons/48x48/oC_warn_shared.png create mode 100644 shell_integration/icons/512x512/oC_error.png create mode 100644 shell_integration/icons/512x512/oC_error_shared.png create mode 100644 shell_integration/icons/512x512/oC_ok.png create mode 100644 shell_integration/icons/512x512/oC_ok_shared.png create mode 100644 shell_integration/icons/512x512/oC_sync.png create mode 100644 shell_integration/icons/512x512/oC_sync_shared.png create mode 100644 shell_integration/icons/512x512/oC_warn.png create mode 100644 shell_integration/icons/512x512/oC_warn_shared.png create mode 100644 shell_integration/icons/64x64/oC_error.png create mode 100644 shell_integration/icons/64x64/oC_error_shared.png create mode 100644 shell_integration/icons/64x64/oC_ok.png create mode 100644 shell_integration/icons/64x64/oC_ok_shared.png create mode 100644 shell_integration/icons/64x64/oC_sync.png create mode 100644 shell_integration/icons/64x64/oC_sync_shared.png create mode 100644 shell_integration/icons/64x64/oC_warn.png create mode 100644 shell_integration/icons/64x64/oC_warn_shared.png create mode 100644 shell_integration/icons/72x72/oC_error.png create mode 100644 shell_integration/icons/72x72/oC_error_shared.png create mode 100644 shell_integration/icons/72x72/oC_ok.png create mode 100644 shell_integration/icons/72x72/oC_ok_shared.png create mode 100644 shell_integration/icons/72x72/oC_sync.png create mode 100644 shell_integration/icons/72x72/oC_sync_shared.png create mode 100644 shell_integration/icons/72x72/oC_warn.png create mode 100644 shell_integration/icons/72x72/oC_warn_shared.png create mode 100644 shell_integration/icons/CMakeLists.txt create mode 100644 shell_integration/icons/SVG/Error.svg create mode 100644 shell_integration/icons/SVG/Error_Shared.svg create mode 100644 shell_integration/icons/SVG/OK.svg create mode 100644 shell_integration/icons/SVG/OK_Shared.svg create mode 100644 shell_integration/icons/SVG/Sync.svg create mode 100644 shell_integration/icons/SVG/Sync_Shared.svg create mode 100644 shell_integration/icons/SVG/Warning.svg create mode 100644 shell_integration/icons/SVG/Warning_Shared.svg create mode 100644 shell_integration/icons/Sidebar/sidebar_icon_osx_18.png create mode 100644 shell_integration/icons/Sidebar/sidebar_icon_osx_hover_18.png create mode 100644 shell_integration/icons/Sidebar/sidebar_icon_win_18.png create mode 100644 shell_integration/icons/Sidebar/sidebar_icon_win_hover_18.png create mode 100644 shell_integration/icons/icns/error.icns create mode 100644 shell_integration/icons/icns/error_swm.icns create mode 100644 shell_integration/icons/icns/ok.icns create mode 100644 shell_integration/icons/icns/ok_swm.icns create mode 100644 shell_integration/icons/icns/sync.icns create mode 100644 shell_integration/icons/icns/sync_swm.icns create mode 100644 shell_integration/icons/icns/warning.icns create mode 100644 shell_integration/icons/icns/warning_swm.icns create mode 100755 shell_integration/icons/nopadding/SVG/attention.svg create mode 100755 shell_integration/icons/nopadding/SVG/error.svg create mode 100755 shell_integration/icons/nopadding/SVG/generate_windows_ico.sh create mode 100755 shell_integration/icons/nopadding/SVG/ok.svg create mode 100755 shell_integration/icons/nopadding/SVG/shared.svg create mode 100755 shell_integration/icons/nopadding/SVG/sync.svg create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_128x128.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_128x128@2x.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_16x16.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_16x16@2x.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_256x256.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_256x256@2x.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_32x32.png create mode 100755 shell_integration/icons/nopadding/error.iconset/icon_32x32@2x.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_128x128.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_128x128@2x.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_16x16.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_16x16@2x.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_256x256.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_256x256@2x.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_32x32.png create mode 100755 shell_integration/icons/nopadding/ok.iconset/icon_32x32@2x.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_128x128.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_128x128@2x.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_16x16.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_16x16@2x.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_256x256.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_256x256@2x.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_32x32.png create mode 100755 shell_integration/icons/nopadding/ok_swm.iconset/icon_32x32@2x.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_128x128.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_128x128@2x.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_16x16.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_16x16@2x.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_256x256.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_256x256@2x.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_32x32.png create mode 100755 shell_integration/icons/nopadding/sync.iconset/icon_32x32@2x.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_128x128.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_128x128@2x.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_16x16.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_16x16@2x.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_256x256.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_256x256@2x.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_32x32.png create mode 100755 shell_integration/icons/nopadding/warning.iconset/icon_32x32@2x.png create mode 100644 shell_integration/libcloudproviders/CMakeLists.txt create mode 100644 shell_integration/libcloudproviders/org.freedesktop.CloudProviders.ini.in create mode 100644 shell_integration/libcloudproviders/org.freedesktop.CloudProviders.service.in create mode 100644 shell_integration/nautilus/CMakeLists.txt create mode 100755 shell_integration/nautilus/createcajaplugin.sh create mode 100755 shell_integration/nautilus/createnemoplugin.sh create mode 100755 shell_integration/nautilus/setappname.sh create mode 100644 shell_integration/nautilus/syncstate.py create mode 100644 shell_integration/windows/CMakeLists.txt create mode 100644 shell_integration/windows/NCContextMenu/CMakeLists.txt create mode 100644 shell_integration/windows/NCContextMenu/NCClientInterface.cpp create mode 100644 shell_integration/windows/NCContextMenu/NCClientInterface.h create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenu.cpp create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenu.def create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenu.h create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenu.rc create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenuFactory.cpp create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenuFactory.h create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenuRegHandler.cpp create mode 100644 shell_integration/windows/NCContextMenu/NCContextMenuRegHandler.h create mode 100644 shell_integration/windows/NCContextMenu/RegDelnode.h create mode 100644 shell_integration/windows/NCContextMenu/dllmain.cpp create mode 100644 shell_integration/windows/NCContextMenu/resource.h create mode 100644 shell_integration/windows/NCOverlays/CMakeLists.txt create mode 100644 shell_integration/windows/NCOverlays/DllMain.cpp create mode 100644 shell_integration/windows/NCOverlays/NCOverlay.cpp create mode 100644 shell_integration/windows/NCOverlays/NCOverlay.h create mode 100644 shell_integration/windows/NCOverlays/NCOverlay.rc create mode 100644 shell_integration/windows/NCOverlays/NCOverlayFactory.cpp create mode 100644 shell_integration/windows/NCOverlays/NCOverlayFactory.h create mode 100644 shell_integration/windows/NCOverlays/NCOverlayRegistrationHandler.cpp create mode 100644 shell_integration/windows/NCOverlays/NCOverlayRegistrationHandler.h create mode 100644 shell_integration/windows/NCOverlays/NCOverlays.def create mode 100644 shell_integration/windows/NCOverlays/ico/Error.ico create mode 100644 shell_integration/windows/NCOverlays/ico/OK.ico create mode 100644 shell_integration/windows/NCOverlays/ico/OK_Shared.ico create mode 100644 shell_integration/windows/NCOverlays/ico/Sync.ico create mode 100644 shell_integration/windows/NCOverlays/ico/Warning.ico create mode 100644 shell_integration/windows/NCOverlays/resource.h create mode 100644 shell_integration/windows/NCUtil/CMakeLists.txt create mode 100644 shell_integration/windows/NCUtil/CommunicationSocket.cpp create mode 100644 shell_integration/windows/NCUtil/CommunicationSocket.h create mode 100644 shell_integration/windows/NCUtil/NCUtil.rc create mode 100644 shell_integration/windows/NCUtil/RemotePathChecker.cpp create mode 100644 shell_integration/windows/NCUtil/RemotePathChecker.h create mode 100644 shell_integration/windows/NCUtil/StringUtil.cpp create mode 100644 shell_integration/windows/NCUtil/StringUtil.h create mode 100644 shell_integration/windows/NCUtil/Version.h create mode 100644 shell_integration/windows/NCUtil/resource.h create mode 100644 shell_integration/windows/WinShellExt.wxs.in create mode 100644 shell_integration/windows/WinShellExtConstants.h.in create mode 100644 sonar-project.properties create mode 100644 src/3rdparty/LGPL_EXCEPTION.txt create mode 100644 src/3rdparty/QProgressIndicator/LICENSE create mode 100644 src/3rdparty/QProgressIndicator/QProgressIndicator.cpp create mode 100644 src/3rdparty/QProgressIndicator/QProgressIndicator.h create mode 100644 src/3rdparty/QProgressIndicator/README.md create mode 100644 src/3rdparty/kirigami/wheelhandler.cpp create mode 100644 src/3rdparty/kirigami/wheelhandler.h create mode 100644 src/3rdparty/kmessagewidget/kmessagewidget.cpp create mode 100644 src/3rdparty/kmessagewidget/kmessagewidget.h create mode 100644 src/3rdparty/qtlockedfile/README.txt create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile.cpp create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile.h create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile.pri create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile_win.cpp create mode 100644 src/3rdparty/qtsingleapplication/README.txt create mode 100644 src/3rdparty/qtsingleapplication/qtlocalpeer.cpp create mode 100644 src/3rdparty/qtsingleapplication/qtlocalpeer.h create mode 100644 src/3rdparty/qtsingleapplication/qtsingleapplication.cpp create mode 100644 src/3rdparty/qtsingleapplication/qtsingleapplication.h create mode 100644 src/3rdparty/qtsingleapplication/qtsingleapplication.pri create mode 100644 src/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp create mode 100644 src/3rdparty/qtsingleapplication/qtsinglecoreapplication.h create mode 100644 src/3rdparty/qtsingleapplication/qtsinglecoreapplication.pri create mode 100644 src/CMakeLists.txt create mode 100644 src/cmd/CMakeLists.txt create mode 100644 src/cmd/cmd.cpp create mode 100644 src/cmd/cmd.h create mode 100644 src/cmd/cmd.md create mode 100644 src/cmd/netrcparser.cpp create mode 100644 src/cmd/netrcparser.h create mode 100644 src/cmd/simplesslerrorhandler.cpp create mode 100644 src/cmd/simplesslerrorhandler.h create mode 100644 src/common/README create mode 100644 src/common/asserts.h create mode 100644 src/common/c_jhash.h create mode 100644 src/common/checksumcalculator.cpp create mode 100644 src/common/checksumcalculator.h create mode 100644 src/common/checksumconsts.h create mode 100644 src/common/checksums.cpp create mode 100644 src/common/checksums.h create mode 100644 src/common/common.cmake create mode 100644 src/common/constants.h create mode 100644 src/common/filesystembase.cpp create mode 100644 src/common/filesystembase.h create mode 100644 src/common/ownsql.cpp create mode 100644 src/common/ownsql.h create mode 100644 src/common/pinstate.cpp create mode 100644 src/common/pinstate.h create mode 100644 src/common/plugin.cpp create mode 100644 src/common/plugin.h create mode 100644 src/common/preparedsqlquerymanager.cpp create mode 100644 src/common/preparedsqlquerymanager.h create mode 100644 src/common/remotepermissions.cpp create mode 100644 src/common/remotepermissions.h create mode 100644 src/common/result.h create mode 100644 src/common/shellextensionutils.cpp create mode 100644 src/common/shellextensionutils.h create mode 100644 src/common/syncfilestatus.cpp create mode 100644 src/common/syncfilestatus.h create mode 100644 src/common/syncjournaldb.cpp create mode 100644 src/common/syncjournaldb.h create mode 100644 src/common/syncjournalfilerecord.cpp create mode 100644 src/common/syncjournalfilerecord.h create mode 100644 src/common/utility.cpp create mode 100644 src/common/utility.h create mode 100644 src/common/utility_mac.mm create mode 100644 src/common/utility_unix.cpp create mode 100644 src/common/utility_win.cpp create mode 100644 src/common/vfs.cpp create mode 100644 src/common/vfs.h create mode 100644 src/common/vfspluginmetadata.json.in create mode 100644 src/crashreporter/CMakeLists.txt create mode 100644 src/crashreporter/CrashReporterConfig.h.in create mode 100644 src/crashreporter/main.cpp create mode 100644 src/crashreporter/resources.qrc create mode 100644 src/csync/AUTHORS create mode 100644 src/csync/CMakeLists.txt create mode 100644 src/csync/COPYING create mode 100644 src/csync/ChangeLog create mode 100644 src/csync/ConfigureChecks.cmake create mode 100644 src/csync/DefineOptions.cmake create mode 100644 src/csync/INSTALL.md create mode 100644 src/csync/README.md create mode 100644 src/csync/config_csync.h.cmake create mode 100644 src/csync/csync.cpp create mode 100644 src/csync/csync.h create mode 100644 src/csync/csync_exclude.cpp create mode 100644 src/csync/csync_exclude.h create mode 100644 src/csync/csync_version.h.in create mode 100644 src/csync/std/c_lib.h create mode 100644 src/csync/std/c_private.h create mode 100644 src/csync/std/c_time.cpp create mode 100644 src/csync/std/c_time.h create mode 100644 src/csync/vio/csync_vio_local.h create mode 100644 src/csync/vio/csync_vio_local_unix.cpp create mode 100644 src/csync/vio/csync_vio_local_win.cpp create mode 100644 src/gui/CMakeLists.txt create mode 100644 src/gui/ConflictDelegate.qml create mode 100644 src/gui/ConflictItemFileInfo.qml create mode 100644 src/gui/EmojiPicker.qml create mode 100644 src/gui/EncryptionTokenSelectionWindow.qml create mode 100644 src/gui/ErrorBox.qml create mode 100644 src/gui/PredefinedStatusButton.qml create mode 100644 src/gui/ResolveConflictsDialog.qml create mode 100644 src/gui/UserStatusSelector.qml create mode 100644 src/gui/UserStatusSelectorButton.qml create mode 100644 src/gui/UserStatusSelectorPage.qml create mode 100644 src/gui/accountmanager.cpp create mode 100644 src/gui/accountmanager.h create mode 100644 src/gui/accountsettings.cpp create mode 100644 src/gui/accountsettings.h create mode 100644 src/gui/accountsettings.ui create mode 100644 src/gui/accountsetupcommandlinemanager.cpp create mode 100644 src/gui/accountsetupcommandlinemanager.h create mode 100644 src/gui/accountsetupfromcommandlinejob.cpp create mode 100644 src/gui/accountsetupfromcommandlinejob.h create mode 100644 src/gui/accountstate.cpp create mode 100644 src/gui/accountstate.h create mode 100644 src/gui/addcertificatedialog.cpp create mode 100644 src/gui/addcertificatedialog.h create mode 100644 src/gui/addcertificatedialog.ui create mode 100644 src/gui/application.cpp create mode 100644 src/gui/application.h create mode 100644 src/gui/authenticationdialog.cpp create mode 100644 src/gui/authenticationdialog.h create mode 100644 src/gui/callstatechecker.cpp create mode 100644 src/gui/callstatechecker.h create mode 100644 src/gui/caseclashfilenamedialog.cpp create mode 100644 src/gui/caseclashfilenamedialog.h create mode 100644 src/gui/caseclashfilenamedialog.ui create mode 100644 src/gui/cloudproviders/cloudproviderconfig.h.in create mode 100644 src/gui/cloudproviders/cloudprovidermanager.cpp create mode 100644 src/gui/cloudproviders/cloudprovidermanager.h create mode 100644 src/gui/cloudproviders/cloudproviderwrapper.cpp create mode 100644 src/gui/cloudproviders/cloudproviderwrapper.h create mode 100644 src/gui/cocoainitializer.h create mode 100644 src/gui/cocoainitializer_mac.mm create mode 100644 src/gui/configgui.h.in create mode 100644 src/gui/conflictdialog.cpp create mode 100644 src/gui/conflictdialog.h create mode 100644 src/gui/conflictdialog.ui create mode 100644 src/gui/conflictsolver.cpp create mode 100644 src/gui/conflictsolver.h create mode 100644 src/gui/connectionvalidator.cpp create mode 100644 src/gui/connectionvalidator.h create mode 100644 src/gui/creds/credentialsfactory.cpp create mode 100644 src/gui/creds/credentialsfactory.h create mode 100644 src/gui/creds/flow2auth.cpp create mode 100644 src/gui/creds/flow2auth.h create mode 100644 src/gui/creds/httpcredentialsgui.cpp create mode 100644 src/gui/creds/httpcredentialsgui.h create mode 100644 src/gui/creds/webflowcredentials.cpp create mode 100644 src/gui/creds/webflowcredentials.h create mode 100644 src/gui/creds/webflowcredentialsdialog.cpp create mode 100644 src/gui/creds/webflowcredentialsdialog.h create mode 100644 src/gui/editlocallyjob.cpp create mode 100644 src/gui/editlocallyjob.h create mode 100644 src/gui/editlocallymanager.cpp create mode 100644 src/gui/editlocallymanager.h create mode 100644 src/gui/editlocallyverificationjob.cpp create mode 100644 src/gui/editlocallyverificationjob.h create mode 100644 src/gui/elidedlabel.cpp create mode 100644 src/gui/elidedlabel.h create mode 100644 src/gui/emojimodel.cpp create mode 100644 src/gui/emojimodel.h create mode 100644 src/gui/fileactivitylistmodel.cpp create mode 100644 src/gui/fileactivitylistmodel.h create mode 100644 src/gui/filedetails/FileActivityView.qml create mode 100644 src/gui/filedetails/FileDetailsPage.qml create mode 100644 src/gui/filedetails/FileDetailsView.qml create mode 100644 src/gui/filedetails/FileDetailsWindow.qml create mode 100644 src/gui/filedetails/FileTag.qml create mode 100644 src/gui/filedetails/NCInputDateField.qml create mode 100644 src/gui/filedetails/NCInputTextArea.qml create mode 100644 src/gui/filedetails/NCInputTextField.qml create mode 100644 src/gui/filedetails/NCTabButton.qml create mode 100644 src/gui/filedetails/ShareDelegate.qml create mode 100644 src/gui/filedetails/ShareDetailsPage.qml create mode 100644 src/gui/filedetails/ShareView.qml create mode 100644 src/gui/filedetails/ShareeDelegate.qml create mode 100644 src/gui/filedetails/ShareeSearchField.qml create mode 100644 src/gui/filedetails/datefieldbackend.cpp create mode 100644 src/gui/filedetails/datefieldbackend.h create mode 100644 src/gui/filedetails/filedetails.cpp create mode 100644 src/gui/filedetails/filedetails.h create mode 100644 src/gui/filedetails/shareemodel.cpp create mode 100644 src/gui/filedetails/shareemodel.h create mode 100644 src/gui/filedetails/sharemodel.cpp create mode 100644 src/gui/filedetails/sharemodel.h create mode 100644 src/gui/filedetails/sortedsharemodel.cpp create mode 100644 src/gui/filedetails/sortedsharemodel.h create mode 100644 src/gui/filetagmodel.cpp create mode 100644 src/gui/filetagmodel.h create mode 100644 src/gui/folder.cpp create mode 100644 src/gui/folder.h create mode 100644 src/gui/foldercreationdialog.cpp create mode 100644 src/gui/foldercreationdialog.h create mode 100644 src/gui/foldercreationdialog.ui create mode 100644 src/gui/folderman.cpp create mode 100644 src/gui/folderman.h create mode 100644 src/gui/folderstatusdelegate.cpp create mode 100644 src/gui/folderstatusdelegate.h create mode 100644 src/gui/folderstatusmodel.cpp create mode 100644 src/gui/folderstatusmodel.h create mode 100644 src/gui/folderstatusview.cpp create mode 100644 src/gui/folderstatusview.h create mode 100644 src/gui/folderwatcher.cpp create mode 100644 src/gui/folderwatcher.h create mode 100644 src/gui/folderwatcher_linux.cpp create mode 100644 src/gui/folderwatcher_linux.h create mode 100644 src/gui/folderwatcher_mac.cpp create mode 100644 src/gui/folderwatcher_mac.h create mode 100644 src/gui/folderwatcher_win.cpp create mode 100644 src/gui/folderwatcher_win.h create mode 100644 src/gui/folderwizard.cpp create mode 100644 src/gui/folderwizard.h create mode 100644 src/gui/folderwizardsourcepage.ui create mode 100644 src/gui/folderwizardtargetpage.ui create mode 100644 src/gui/foregroundbackground_cocoa.h create mode 100644 src/gui/foregroundbackground_cocoa.mm create mode 100644 src/gui/foregroundbackground_interface.h create mode 100644 src/gui/foregroundbackground_mac.mm create mode 100644 src/gui/generalsettings.cpp create mode 100644 src/gui/generalsettings.h create mode 100644 src/gui/generalsettings.ui create mode 100644 src/gui/gui.md create mode 100644 src/gui/guiutility.cpp create mode 100644 src/gui/guiutility.h create mode 100644 src/gui/iconutils.cpp create mode 100644 src/gui/iconutils.h create mode 100644 src/gui/ignorelisteditor.cpp create mode 100644 src/gui/ignorelisteditor.h create mode 100644 src/gui/ignorelisteditor.ui create mode 100644 src/gui/ignorelisttablewidget.cpp create mode 100644 src/gui/ignorelisttablewidget.h create mode 100644 src/gui/ignorelisttablewidget.ui create mode 100644 src/gui/invalidfilenamedialog.cpp create mode 100644 src/gui/invalidfilenamedialog.h create mode 100644 src/gui/invalidfilenamedialog.ui create mode 100644 src/gui/legalnotice.cpp create mode 100644 src/gui/legalnotice.h create mode 100644 src/gui/legalnotice.ui create mode 100644 src/gui/lockwatcher.cpp create mode 100644 src/gui/lockwatcher.h create mode 100644 src/gui/logbrowser.cpp create mode 100644 src/gui/logbrowser.h create mode 120000 src/gui/macOS/ClientCommunicationProtocol.h create mode 100644 src/gui/macOS/fileprovider.h create mode 100644 src/gui/macOS/fileprovider_mac.mm create mode 100644 src/gui/macOS/fileproviderdomainmanager.h create mode 100644 src/gui/macOS/fileproviderdomainmanager_mac.mm create mode 100644 src/gui/macOS/fileproviderdomainsyncstatus.h create mode 100644 src/gui/macOS/fileproviderdomainsyncstatus_mac.mm create mode 100644 src/gui/macOS/fileprovidereditlocallyjob.cpp create mode 100644 src/gui/macOS/fileprovidereditlocallyjob.h create mode 100644 src/gui/macOS/fileprovidereditlocallyjob_mac.mm create mode 100644 src/gui/macOS/fileprovideritemmetadata.cpp create mode 100644 src/gui/macOS/fileprovideritemmetadata.h create mode 100644 src/gui/macOS/fileprovideritemmetadata_mac.mm create mode 100644 src/gui/macOS/fileprovidermaterialiseditemsmodel.cpp create mode 100644 src/gui/macOS/fileprovidermaterialiseditemsmodel.h create mode 100644 src/gui/macOS/fileprovidermaterialiseditemsmodel_mac.mm create mode 100644 src/gui/macOS/fileprovidersettingscontroller.h create mode 100644 src/gui/macOS/fileprovidersettingscontroller_mac.mm create mode 100644 src/gui/macOS/fileprovidersocketcontroller.cpp create mode 100644 src/gui/macOS/fileprovidersocketcontroller.h create mode 100644 src/gui/macOS/fileprovidersocketserver.cpp create mode 100644 src/gui/macOS/fileprovidersocketserver.h create mode 100644 src/gui/macOS/fileprovidersocketserver_mac.mm create mode 100644 src/gui/macOS/fileproviderstorageuseenumerationobserver.h create mode 100644 src/gui/macOS/fileproviderstorageuseenumerationobserver.m create mode 100644 src/gui/macOS/fileproviderutils.h create mode 100644 src/gui/macOS/fileproviderutils_mac.mm create mode 100644 src/gui/macOS/fileproviderxpc.h create mode 100644 src/gui/macOS/fileproviderxpc_mac.mm create mode 100644 src/gui/macOS/fileproviderxpc_mac_utils.h create mode 100644 src/gui/macOS/fileproviderxpc_mac_utils.mm create mode 100644 src/gui/macOS/progressobserver.h create mode 100644 src/gui/macOS/progressobserver.m create mode 100644 src/gui/macOS/ui/FileProviderEvictionDialog.qml create mode 100644 src/gui/macOS/ui/FileProviderFastEnumerationSettings.qml create mode 100644 src/gui/macOS/ui/FileProviderFileDelegate.qml create mode 100644 src/gui/macOS/ui/FileProviderSettings.qml create mode 100644 src/gui/macOS/ui/FileProviderStorageInfo.qml create mode 100644 src/gui/macOS/ui/FileProviderSyncStatus.qml create mode 100644 src/gui/main.cpp create mode 100644 src/gui/manifest-mingw.rc create mode 100644 src/gui/mnemonicdialog.ui create mode 100644 src/gui/navigationpanehelper.cpp create mode 100644 src/gui/navigationpanehelper.h create mode 100644 src/gui/networksettings.cpp create mode 100644 src/gui/networksettings.h create mode 100644 src/gui/networksettings.ui create mode 100644 src/gui/notificationconfirmjob.cpp create mode 100644 src/gui/notificationconfirmjob.h create mode 100644 src/gui/ocsjob.cpp create mode 100644 src/gui/ocsjob.h create mode 100644 src/gui/ocsnavigationappsjob.cpp create mode 100644 src/gui/ocsnavigationappsjob.h create mode 100644 src/gui/ocsshareejob.cpp create mode 100644 src/gui/ocsshareejob.h create mode 100644 src/gui/ocssharejob.cpp create mode 100644 src/gui/ocssharejob.h create mode 100644 src/gui/openfilemanager.cpp create mode 100644 src/gui/openfilemanager.h create mode 100644 src/gui/owncloud.exe.manifest-mingw create mode 100644 src/gui/owncloud.xml.in create mode 100644 src/gui/owncloudgui.cpp create mode 100644 src/gui/owncloudgui.h create mode 100644 src/gui/owncloudsetupwizard.cpp create mode 100644 src/gui/owncloudsetupwizard.h create mode 100644 src/gui/passwordinputdialog.cpp create mode 100644 src/gui/passwordinputdialog.h create mode 100644 src/gui/passwordinputdialog.ui create mode 100644 src/gui/profilepagewidget.cpp create mode 100644 src/gui/profilepagewidget.h create mode 100644 src/gui/proxyauthdialog.cpp create mode 100644 src/gui/proxyauthdialog.h create mode 100644 src/gui/proxyauthdialog.ui create mode 100644 src/gui/proxyauthhandler.cpp create mode 100644 src/gui/proxyauthhandler.h create mode 100644 src/gui/remotewipe.cpp create mode 100644 src/gui/remotewipe.h create mode 100644 src/gui/selectivesyncdialog.cpp create mode 100644 src/gui/selectivesyncdialog.h create mode 100644 src/gui/settingsdialog.cpp create mode 100644 src/gui/settingsdialog.h create mode 100644 src/gui/settingsdialog.ui create mode 100644 src/gui/sharee.cpp create mode 100644 src/gui/sharee.h create mode 100644 src/gui/sharemanager.cpp create mode 100644 src/gui/sharemanager.h create mode 100644 src/gui/sharepermissions.h create mode 100644 src/gui/shellextensionsserver.cpp create mode 100644 src/gui/shellextensionsserver.h create mode 100644 src/gui/socketapi/CMakeLists.txt create mode 100644 src/gui/socketapi/socketapi.cpp create mode 100644 src/gui/socketapi/socketapi.h create mode 100644 src/gui/socketapi/socketapi_mac.mm create mode 100644 src/gui/socketapi/socketapi_p.h create mode 100644 src/gui/socketapi/socketuploadjob.cpp create mode 100644 src/gui/socketapi/socketuploadjob.h create mode 100644 src/gui/sslbutton.cpp create mode 100644 src/gui/sslbutton.h create mode 100644 src/gui/sslerrordialog.cpp create mode 100644 src/gui/sslerrordialog.h create mode 100644 src/gui/sslerrordialog.ui create mode 100644 src/gui/syncconflictsmodel.cpp create mode 100644 src/gui/syncconflictsmodel.h create mode 100644 src/gui/syncrunfilelog.cpp create mode 100644 src/gui/syncrunfilelog.h create mode 100644 src/gui/systray.cpp create mode 100644 src/gui/systray.h create mode 100644 src/gui/systray_mac_common.mm create mode 100644 src/gui/systray_mac_usernotifications.mm create mode 100644 src/gui/tooltipupdater.cpp create mode 100644 src/gui/tooltipupdater.h create mode 100644 src/gui/tray/ActivityItem.qml create mode 100644 src/gui/tray/ActivityItemActions.qml create mode 100644 src/gui/tray/ActivityItemContent.qml create mode 100644 src/gui/tray/ActivityItemContextMenu.qml create mode 100644 src/gui/tray/ActivityList.qml create mode 100644 src/gui/tray/AutoSizingMenu.qml create mode 100644 src/gui/tray/CallNotificationDialog.qml create mode 100644 src/gui/tray/CurrentAccountHeaderButton.qml create mode 100644 src/gui/tray/EditFileLocallyLoadingDialog.qml create mode 100644 src/gui/tray/EncryptionTokenDiscoveryDialog.qml create mode 100644 src/gui/tray/EnforcedPlainTextLabel.qml create mode 100644 src/gui/tray/HeaderButton.qml create mode 100644 src/gui/tray/ListItemLineAndSubline.qml create mode 100644 src/gui/tray/MainWindow.qml create mode 100644 src/gui/tray/NCBusyIndicator.qml create mode 100644 src/gui/tray/NCIconWithBackgroundImage.qml create mode 100644 src/gui/tray/NCProgressBar.qml create mode 100644 src/gui/tray/NCToolTip.qml create mode 100644 src/gui/tray/SyncStatus.qml create mode 100644 src/gui/tray/TalkReplyTextField.qml create mode 100644 src/gui/tray/TrayFolderListItem.qml create mode 100644 src/gui/tray/TrayFoldersMenuButton.qml create mode 100644 src/gui/tray/TrayWindowHeader.qml create mode 100644 src/gui/tray/UnifiedSearchInputContainer.qml create mode 100644 src/gui/tray/UnifiedSearchPlaceholderView.qml create mode 100644 src/gui/tray/UnifiedSearchResultFetchMoreTrigger.qml create mode 100644 src/gui/tray/UnifiedSearchResultItem.qml create mode 100644 src/gui/tray/UnifiedSearchResultItemSkeleton.qml create mode 100644 src/gui/tray/UnifiedSearchResultItemSkeletonContainer.qml create mode 100644 src/gui/tray/UnifiedSearchResultItemSkeletonGradientRectangle.qml create mode 100644 src/gui/tray/UnifiedSearchResultListItem.qml create mode 100644 src/gui/tray/UnifiedSearchResultNothingFound.qml create mode 100644 src/gui/tray/UnifiedSearchResultSectionItem.qml create mode 100644 src/gui/tray/UserLine.qml create mode 100644 src/gui/tray/activitydata.cpp create mode 100644 src/gui/tray/activitydata.h create mode 100644 src/gui/tray/activitylistmodel.cpp create mode 100644 src/gui/tray/activitylistmodel.h create mode 100644 src/gui/tray/asyncimageresponse.cpp create mode 100644 src/gui/tray/asyncimageresponse.h create mode 100644 src/gui/tray/notificationhandler.cpp create mode 100644 src/gui/tray/notificationhandler.h create mode 100644 src/gui/tray/sortedactivitylistmodel.cpp create mode 100644 src/gui/tray/sortedactivitylistmodel.h create mode 100644 src/gui/tray/svgimageprovider.cpp create mode 100644 src/gui/tray/svgimageprovider.h create mode 100644 src/gui/tray/syncstatussummary.cpp create mode 100644 src/gui/tray/syncstatussummary.h create mode 100644 src/gui/tray/talkreply.cpp create mode 100644 src/gui/tray/talkreply.h create mode 100644 src/gui/tray/trayimageprovider.cpp create mode 100644 src/gui/tray/trayimageprovider.h create mode 100644 src/gui/tray/unifiedsearchresult.cpp create mode 100644 src/gui/tray/unifiedsearchresult.h create mode 100644 src/gui/tray/unifiedsearchresultslistmodel.cpp create mode 100644 src/gui/tray/unifiedsearchresultslistmodel.h create mode 100644 src/gui/tray/usermodel.cpp create mode 100644 src/gui/tray/usermodel.h create mode 100644 src/gui/updater/CMakeLists.txt create mode 100644 src/gui/updater/ocupdater.cpp create mode 100644 src/gui/updater/ocupdater.h create mode 100644 src/gui/updater/sparkleupdater.h create mode 100644 src/gui/updater/sparkleupdater_mac.mm create mode 100644 src/gui/updater/updateinfo.cpp create mode 100644 src/gui/updater/updateinfo.h create mode 100644 src/gui/updater/updater.cpp create mode 100644 src/gui/updater/updater.h create mode 100644 src/gui/userinfo.cpp create mode 100644 src/gui/userinfo.h create mode 100644 src/gui/userstatusselectormodel.cpp create mode 100644 src/gui/userstatusselectormodel.h create mode 100644 src/gui/version.rc.in create mode 100644 src/gui/vfsdownloaderrordialog.cpp create mode 100644 src/gui/vfsdownloaderrordialog.h create mode 100644 src/gui/vfsdownloaderrordialog.ui create mode 100644 src/gui/wizard/abstractcredswizardpage.cpp create mode 100644 src/gui/wizard/abstractcredswizardpage.h create mode 100644 src/gui/wizard/flow2authcredspage.cpp create mode 100644 src/gui/wizard/flow2authcredspage.h create mode 100644 src/gui/wizard/flow2authwidget.cpp create mode 100644 src/gui/wizard/flow2authwidget.h create mode 100644 src/gui/wizard/flow2authwidget.ui create mode 100644 src/gui/wizard/linklabel.cpp create mode 100644 src/gui/wizard/linklabel.h create mode 100644 src/gui/wizard/owncloudadvancedsetuppage.cpp create mode 100644 src/gui/wizard/owncloudadvancedsetuppage.h create mode 100644 src/gui/wizard/owncloudadvancedsetuppage.ui create mode 100644 src/gui/wizard/owncloudconnectionmethoddialog.cpp create mode 100644 src/gui/wizard/owncloudconnectionmethoddialog.h create mode 100644 src/gui/wizard/owncloudconnectionmethoddialog.ui create mode 100644 src/gui/wizard/owncloudhttpcredspage.cpp create mode 100644 src/gui/wizard/owncloudhttpcredspage.h create mode 100644 src/gui/wizard/owncloudhttpcredspage.ui create mode 100644 src/gui/wizard/owncloudsetupnocredspage.ui create mode 100644 src/gui/wizard/owncloudsetuppage.cpp create mode 100644 src/gui/wizard/owncloudsetuppage.h create mode 100644 src/gui/wizard/owncloudwizard.cpp create mode 100644 src/gui/wizard/owncloudwizard.h create mode 100644 src/gui/wizard/owncloudwizardcommon.cpp create mode 100644 src/gui/wizard/owncloudwizardcommon.h create mode 100644 src/gui/wizard/postfixlineedit.cpp create mode 100644 src/gui/wizard/postfixlineedit.h create mode 100644 src/gui/wizard/slideshow.cpp create mode 100644 src/gui/wizard/slideshow.h create mode 100644 src/gui/wizard/termsofservicecheckwidget.cpp create mode 100644 src/gui/wizard/termsofservicecheckwidget.h create mode 100644 src/gui/wizard/termsofservicecheckwidget.ui create mode 100644 src/gui/wizard/termsofservicewizardpage.cpp create mode 100644 src/gui/wizard/termsofservicewizardpage.h create mode 100644 src/gui/wizard/webview.cpp create mode 100644 src/gui/wizard/webview.h create mode 100644 src/gui/wizard/webview.ui create mode 100644 src/gui/wizard/webviewpage.cpp create mode 100644 src/gui/wizard/webviewpage.h create mode 100644 src/gui/wizard/welcomepage.cpp create mode 100644 src/gui/wizard/welcomepage.h create mode 100644 src/gui/wizard/welcomepage.ui create mode 100644 src/libsync/CMakeLists.txt create mode 100644 src/libsync/abstractnetworkjob.cpp create mode 100644 src/libsync/abstractnetworkjob.h create mode 100644 src/libsync/accessmanager.cpp create mode 100644 src/libsync/accessmanager.h create mode 100644 src/libsync/account.cpp create mode 100644 src/libsync/account.h create mode 100644 src/libsync/accountfwd.h create mode 100644 src/libsync/bandwidthmanager.cpp create mode 100644 src/libsync/bandwidthmanager.h create mode 100644 src/libsync/basepropagateremotedeleteencrypted.cpp create mode 100644 src/libsync/basepropagateremotedeleteencrypted.h create mode 100644 src/libsync/bulkpropagatorjob.cpp create mode 100644 src/libsync/bulkpropagatorjob.h create mode 100644 src/libsync/capabilities.cpp create mode 100644 src/libsync/capabilities.h create mode 100644 src/libsync/caseclashconflictsolver.cpp create mode 100644 src/libsync/caseclashconflictsolver.h create mode 100644 src/libsync/clientproxy.cpp create mode 100644 src/libsync/clientproxy.h create mode 100644 src/libsync/clientsideencryption.cpp create mode 100644 src/libsync/clientsideencryption.h create mode 100644 src/libsync/clientsideencryptionjobs.cpp create mode 100644 src/libsync/clientsideencryptionjobs.h create mode 100644 src/libsync/clientsideencryptionprimitives.cpp create mode 100644 src/libsync/clientsideencryptionprimitives.h create mode 100644 src/libsync/clientsideencryptiontokenselector.cpp create mode 100644 src/libsync/clientsideencryptiontokenselector.h create mode 100644 src/libsync/clientstatusreporting.cpp create mode 100644 src/libsync/clientstatusreporting.h create mode 100644 src/libsync/clientstatusreportingcommon.cpp create mode 100644 src/libsync/clientstatusreportingcommon.h create mode 100644 src/libsync/clientstatusreportingdatabase.cpp create mode 100644 src/libsync/clientstatusreportingdatabase.h create mode 100644 src/libsync/clientstatusreportingnetwork.cpp create mode 100644 src/libsync/clientstatusreportingnetwork.h create mode 100644 src/libsync/clientstatusreportingrecord.h create mode 100644 src/libsync/configfile.cpp create mode 100644 src/libsync/configfile.h create mode 100644 src/libsync/cookiejar.cpp create mode 100644 src/libsync/cookiejar.h create mode 100644 src/libsync/creds/abstractcredentials.cpp create mode 100644 src/libsync/creds/abstractcredentials.h create mode 100644 src/libsync/creds/credentialscommon.cpp create mode 100644 src/libsync/creds/credentialscommon.h create mode 100644 src/libsync/creds/dummycredentials.cpp create mode 100644 src/libsync/creds/dummycredentials.h create mode 100644 src/libsync/creds/httpcredentials.cpp create mode 100644 src/libsync/creds/httpcredentials.h create mode 100644 src/libsync/creds/keychainchunk.cpp create mode 100644 src/libsync/creds/keychainchunk.h create mode 100644 src/libsync/creds/tokencredentials.cpp create mode 100644 src/libsync/creds/tokencredentials.h create mode 100644 src/libsync/datetimeprovider.cpp create mode 100644 src/libsync/datetimeprovider.h create mode 100644 src/libsync/deletejob.cpp create mode 100644 src/libsync/deletejob.h create mode 100644 src/libsync/discovery.cpp create mode 100644 src/libsync/discovery.h create mode 100644 src/libsync/discoveryphase.cpp create mode 100644 src/libsync/discoveryphase.h create mode 100644 src/libsync/encryptedfoldermetadatahandler.cpp create mode 100644 src/libsync/encryptedfoldermetadatahandler.h create mode 100644 src/libsync/encryptfolderjob.cpp create mode 100644 src/libsync/encryptfolderjob.h create mode 100644 src/libsync/filesystem.cpp create mode 100644 src/libsync/filesystem.h create mode 100644 src/libsync/foldermetadata.cpp create mode 100644 src/libsync/foldermetadata.h create mode 100644 src/libsync/helpers.cpp create mode 100644 src/libsync/helpers.h create mode 100644 src/libsync/httplogger.cpp create mode 100644 src/libsync/httplogger.h create mode 100644 src/libsync/iconjob.cpp create mode 100644 src/libsync/iconjob.h create mode 100644 src/libsync/libsync.md create mode 100644 src/libsync/localdiscoverytracker.cpp create mode 100644 src/libsync/localdiscoverytracker.h create mode 100644 src/libsync/lockfilejobs.cpp create mode 100644 src/libsync/lockfilejobs.h create mode 100644 src/libsync/logger.cpp create mode 100644 src/libsync/logger.h create mode 100644 src/libsync/networkjobs.cpp create mode 100644 src/libsync/networkjobs.h create mode 100644 src/libsync/nextcloudtheme.cpp create mode 100644 src/libsync/nextcloudtheme.h create mode 100644 src/libsync/ocsprofileconnector.cpp create mode 100644 src/libsync/ocsprofileconnector.h create mode 100644 src/libsync/ocsuserstatusconnector.cpp create mode 100644 src/libsync/ocsuserstatusconnector.h create mode 100644 src/libsync/owncloudpropagator.cpp create mode 100644 src/libsync/owncloudpropagator.h create mode 100644 src/libsync/owncloudpropagator_p.h create mode 100644 src/libsync/progressdispatcher.cpp create mode 100644 src/libsync/progressdispatcher.h create mode 100644 src/libsync/propagatedownload.cpp create mode 100644 src/libsync/propagatedownload.h create mode 100644 src/libsync/propagatedownloadencrypted.cpp create mode 100644 src/libsync/propagatedownloadencrypted.h create mode 100644 src/libsync/propagateremotedelete.cpp create mode 100644 src/libsync/propagateremotedelete.h create mode 100644 src/libsync/propagateremotedeleteencrypted.cpp create mode 100644 src/libsync/propagateremotedeleteencrypted.h create mode 100644 src/libsync/propagateremotedeleteencryptedrootfolder.cpp create mode 100644 src/libsync/propagateremotedeleteencryptedrootfolder.h create mode 100644 src/libsync/propagateremotemkdir.cpp create mode 100644 src/libsync/propagateremotemkdir.h create mode 100644 src/libsync/propagateremotemove.cpp create mode 100644 src/libsync/propagateremotemove.h create mode 100644 src/libsync/propagateupload.cpp create mode 100644 src/libsync/propagateupload.h create mode 100644 src/libsync/propagateuploadencrypted.cpp create mode 100644 src/libsync/propagateuploadencrypted.h create mode 100644 src/libsync/propagateuploadng.cpp create mode 100644 src/libsync/propagateuploadv1.cpp create mode 100644 src/libsync/propagatorjobs.cpp create mode 100644 src/libsync/propagatorjobs.h create mode 100644 src/libsync/pushnotifications.cpp create mode 100644 src/libsync/pushnotifications.h create mode 100644 src/libsync/putmultifilejob.cpp create mode 100644 src/libsync/putmultifilejob.h create mode 100644 src/libsync/rootencryptedfolderinfo.cpp create mode 100644 src/libsync/rootencryptedfolderinfo.h create mode 100644 src/libsync/syncengine.cpp create mode 100644 src/libsync/syncengine.h create mode 100644 src/libsync/syncfileitem.cpp create mode 100644 src/libsync/syncfileitem.h create mode 100644 src/libsync/syncfilestatustracker.cpp create mode 100644 src/libsync/syncfilestatustracker.h create mode 100644 src/libsync/syncoptions.cpp create mode 100644 src/libsync/syncoptions.h create mode 100644 src/libsync/syncresult.cpp create mode 100644 src/libsync/syncresult.h create mode 100644 src/libsync/theme.cpp create mode 100644 src/libsync/theme.h create mode 100644 src/libsync/updatee2eefoldermetadatajob.cpp create mode 100644 src/libsync/updatee2eefoldermetadatajob.h create mode 100644 src/libsync/updatee2eefolderusersmetadatajob.cpp create mode 100644 src/libsync/updatee2eefolderusersmetadatajob.h create mode 100644 src/libsync/updatemigratede2eemetadatajob.cpp create mode 100644 src/libsync/updatemigratede2eemetadatajob.h create mode 100644 src/libsync/userstatusconnector.cpp create mode 100644 src/libsync/userstatusconnector.h create mode 100644 src/libsync/vfs/CMakeLists.txt create mode 100644 src/libsync/vfs/cfapi/CMakeLists.txt create mode 100644 src/libsync/vfs/cfapi/cfapiwrapper.cpp create mode 100644 src/libsync/vfs/cfapi/cfapiwrapper.h create mode 100644 src/libsync/vfs/cfapi/hydrationjob.cpp create mode 100644 src/libsync/vfs/cfapi/hydrationjob.h create mode 100644 src/libsync/vfs/cfapi/shellext/CMakeLists.txt create mode 100644 src/libsync/vfs/cfapi/shellext/CfApiShellIntegration.def create mode 100644 src/libsync/vfs/cfapi/shellext/CustomStateProvider.idl create mode 100644 src/libsync/vfs/cfapi/shellext/cfapishellintegrationclassfactory.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/cfapishellintegrationclassfactory.h create mode 100644 src/libsync/vfs/cfapi/shellext/configvfscfapishellext.h.in create mode 100644 src/libsync/vfs/cfapi/shellext/customstateprovider.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/customstateprovider.h create mode 100644 src/libsync/vfs/cfapi/shellext/customstateprovideripc.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/customstateprovideripc.h create mode 100644 src/libsync/vfs/cfapi/shellext/dllmain.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/ipccommon.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/ipccommon.h create mode 100644 src/libsync/vfs/cfapi/shellext/thumbnailprovider.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/thumbnailprovider.h create mode 100644 src/libsync/vfs/cfapi/shellext/thumbnailprovideripc.cpp create mode 100644 src/libsync/vfs/cfapi/shellext/thumbnailprovideripc.h create mode 100644 src/libsync/vfs/cfapi/vfs_cfapi.cpp create mode 100644 src/libsync/vfs/cfapi/vfs_cfapi.h create mode 100644 src/libsync/vfs/suffix/CMakeLists.txt create mode 100644 src/libsync/vfs/suffix/vfs_suffix.cpp create mode 100644 src/libsync/vfs/suffix/vfs_suffix.h create mode 100644 src/libsync/vfs/xattr/CMakeLists.txt create mode 100644 src/libsync/vfs/xattr/vfs_xattr.cpp create mode 100644 src/libsync/vfs/xattr/vfs_xattr.h create mode 100644 src/libsync/vfs/xattr/xattrwrapper.h create mode 100644 src/libsync/vfs/xattr/xattrwrapper_linux.cpp create mode 100644 src/libsync/wordlist.cpp create mode 100644 src/libsync/wordlist.h create mode 100644 sync-exclude.lst create mode 100644 test/CMakeLists.txt create mode 100644 test/activitylistmodeltestutils.cpp create mode 100644 test/activitylistmodeltestutils.h create mode 100644 test/benchmarks/benchlargesync.cpp create mode 100644 test/csync/AUTHORS create mode 100644 test/csync/CMakeLists.txt create mode 100644 test/csync/COPYING create mode 100644 test/csync/cmdline.c create mode 100644 test/csync/std_tests/check_std_c_jhash.c create mode 100644 test/csync/torture.c create mode 100644 test/csync/torture.h create mode 100644 test/csync/valgrind-csync.supp create mode 100644 test/csync/vio_tests/check_vio_ext.cpp create mode 100644 test/e2etestsfakecert.pem create mode 100644 test/e2etestsfakecertprivatekey.pem create mode 100644 test/e2etestsfakecertpublickey.pem create mode 100644 test/endtoendtestutils.cpp create mode 100644 test/endtoendtestutils.h create mode 100644 test/fake2eelocksucceeded.json create mode 100644 test/fakefiledrope2eefoldermetadata.json create mode 100644 test/fakeshortcut.base64 create mode 100644 test/manual/favlink/favlink.pro create mode 100644 test/manual/favlink/main.cpp create mode 100644 test/manual/favlink/owncloudlib.h create mode 100644 test/mockserver/CMakeLists.txt create mode 100644 test/mockserver/httpserver.cpp create mode 100644 test/mockserver/httpserver.h create mode 100644 test/mockserver/main.cpp create mode 100644 test/nextcloud_add_test.cmake create mode 100644 test/pushnotificationstestutils.cpp create mode 100644 test/pushnotificationstestutils.h create mode 100644 test/sharetestutils.cpp create mode 100644 test/sharetestutils.h create mode 100644 test/stubfolderman.cpp create mode 100644 test/stubremotewipe.cpp create mode 100644 test/syncenginetestutils.cpp create mode 100644 test/syncenginetestutils.h create mode 100644 test/test_journal.db create mode 100644 test/testaccount.cpp create mode 100644 test/testactivitydata.cpp create mode 100644 test/testactivitylistmodel.cpp create mode 100644 test/testallfilesdeleted.cpp create mode 100644 test/testasyncop.cpp create mode 100644 test/testblacklist.cpp create mode 100644 test/testcapabilities.cpp create mode 100644 test/testcfapishellextensionsipc.cpp create mode 100644 test/testchecksumvalidator.cpp create mode 100644 test/testchunkingng.cpp create mode 100644 test/testclientsideencryption.cpp create mode 100644 test/testclientsideencryptionv2.cpp create mode 100644 test/testclientstatusreporting.cpp create mode 100644 test/testconcaturl.cpp create mode 100644 test/testcookies.cpp create mode 100644 test/testdatabaseerror.cpp create mode 100644 test/testdatefieldbackend.cpp create mode 100644 test/testdownload.cpp create mode 100644 test/teste2efiletransfer.cpp create mode 100644 test/teste2eserversetup.cpp create mode 100644 test/testexcludedfiles.cpp create mode 100644 test/testfiletagmodel.cpp create mode 100644 test/testfolder.cpp create mode 100644 test/testfolderman.cpp create mode 100644 test/testfolderstatusmodel.cpp create mode 100644 test/testfolderwatcher.cpp create mode 100644 test/testhelper.cpp create mode 100644 test/testhelper.h create mode 100644 test/testiconutils.cpp create mode 100644 test/testinotifywatcher.cpp create mode 100644 test/testlocaldiscovery.cpp create mode 100644 test/testlockedfiles.cpp create mode 100644 test/testlockfile.cpp create mode 100644 test/testlongpath.cpp create mode 100644 test/testnetrcparser.cpp create mode 100644 test/testnextcloudpropagator.cpp create mode 100644 test/testownsql.cpp create mode 100644 test/testpermissions.cpp create mode 100644 test/testplan.txt create mode 100644 test/testpushnotifications.cpp create mode 100644 test/testremotediscovery.cpp create mode 100644 test/testremotewipe.cpp create mode 100644 test/testsecurefiledrop.cpp create mode 100644 test/testselectivesync.cpp create mode 100644 test/testsetuserstatusdialog.cpp create mode 100644 test/testshareemodel.cpp create mode 100644 test/testsharemodel.cpp create mode 100644 test/testsortedactivitylistmodel.cpp create mode 100644 test/testsortedsharemodel.cpp create mode 100644 test/testsynccfapi.cpp create mode 100644 test/testsyncconflict.cpp create mode 100644 test/testsyncconflictsmodel.cpp create mode 100644 test/testsyncdelete.cpp create mode 100644 test/testsyncengine.cpp create mode 100644 test/testsyncfileitem.cpp create mode 100644 test/testsyncfilestatustracker.cpp create mode 100644 test/testsyncjournaldb.cpp create mode 100644 test/testsyncmove.cpp create mode 100644 test/testsyncvirtualfiles.cpp create mode 100644 test/testsyncxattr.cpp create mode 100644 test/testtalkreply.cpp create mode 100644 test/testtheme.cpp create mode 100644 test/testunifiedsearchlistmodel.cpp create mode 100644 test/testupdater.cpp create mode 100644 test/testuploadreset.cpp create mode 100644 test/testutility.cpp create mode 100644 test/testxmlparse.cpp create mode 100644 test/themeutils.cpp create mode 100644 test/themeutils.h create mode 100644 theme.qrc.in create mode 100644 theme/Style/Style.qml create mode 100644 theme/Style/qmldir create mode 100644 theme/account.svg create mode 100644 theme/add.svg create mode 100644 theme/black/account-group.svg create mode 100644 theme/black/activity.svg create mode 100644 theme/black/add.svg create mode 100644 theme/black/bell.svg create mode 100644 theme/black/calendar.svg create mode 100644 theme/black/caret-down.svg create mode 100644 theme/black/change.svg create mode 100644 theme/black/clear.svg create mode 100644 theme/black/close.svg create mode 100644 theme/black/comment.svg create mode 100644 theme/black/confirm.svg create mode 100644 theme/black/control-next.svg create mode 100644 theme/black/control-prev.svg create mode 100644 theme/black/deck.svg create mode 100644 theme/black/edit.svg create mode 100644 theme/black/email.svg create mode 100644 theme/black/expand-less-black.svg create mode 100644 theme/black/external.png create mode 100644 theme/black/external.svg create mode 100644 theme/black/external@2x.png create mode 100644 theme/black/folder-group.svg create mode 100644 theme/black/folder.png create mode 100644 theme/black/folder.svg create mode 100644 theme/black/folder@2x.png create mode 100644 theme/black/more-apps.svg create mode 100644 theme/black/search.svg create mode 100644 theme/black/settings.svg create mode 100644 theme/black/state-error.svg create mode 100644 theme/black/state-info.svg create mode 100644 theme/black/state-offline.svg create mode 100644 theme/black/state-ok.svg create mode 100644 theme/black/state-pause.svg create mode 100644 theme/black/state-sync.svg create mode 100644 theme/black/state-warning.svg create mode 100644 theme/black/user.svg create mode 100644 theme/black/wizard-files.png create mode 100644 theme/black/wizard-files.svg create mode 100644 theme/black/wizard-files@2x.png create mode 100644 theme/black/wizard-groupware.png create mode 100644 theme/black/wizard-groupware.svg create mode 100644 theme/black/wizard-groupware@2x.png create mode 100644 theme/black/wizard-nextcloud.png create mode 100644 theme/black/wizard-nextcloud.svg create mode 100644 theme/black/wizard-nextcloud@2x.png create mode 100644 theme/black/wizard-talk.png create mode 100644 theme/black/wizard-talk.svg create mode 100644 theme/black/wizard-talk@2x.png create mode 100644 theme/call-notification.wav create mode 100644 theme/cfapishellext_custom_states/0-locked.svg create mode 100644 theme/cfapishellext_custom_states/1-shared.svg create mode 100644 theme/cfapishellext_custom_states/1024-0-locked.png create mode 100644 theme/cfapishellext_custom_states/1024-1-shared.png create mode 100644 theme/cfapishellext_custom_states/128-0-locked.png create mode 100644 theme/cfapishellext_custom_states/128-1-shared.png create mode 100644 theme/cfapishellext_custom_states/24-0-locked.png create mode 100644 theme/cfapishellext_custom_states/24-1-shared.png create mode 100644 theme/cfapishellext_custom_states/256-0-locked.png create mode 100644 theme/cfapishellext_custom_states/256-1-shared.png create mode 100644 theme/cfapishellext_custom_states/32-0-locked.png create mode 100644 theme/cfapishellext_custom_states/32-1-shared.png create mode 100644 theme/cfapishellext_custom_states/40-0-locked.png create mode 100644 theme/cfapishellext_custom_states/40-1-shared.png create mode 100644 theme/cfapishellext_custom_states/48-0-locked.png create mode 100644 theme/cfapishellext_custom_states/48-1-shared.png create mode 100644 theme/cfapishellext_custom_states/512-0-locked.png create mode 100644 theme/cfapishellext_custom_states/512-1-shared.png create mode 100644 theme/cfapishellext_custom_states/64-0-locked.png create mode 100644 theme/cfapishellext_custom_states/64-1-shared.png create mode 100644 theme/change.svg create mode 100644 theme/chevron-double-up.svg create mode 100644 theme/close.svg create mode 100644 theme/colored/Nextcloud-icon-square.svg create mode 100644 theme/colored/Nextcloud-icon.svg create mode 100644 theme/colored/Nextcloud-macOS-icon.svg create mode 100644 theme/colored/Nextcloud-macOS-sidebar.svg create mode 100644 theme/colored/Nextcloud-w10startmenu.svg create mode 100644 theme/colored/Nextcloud-w10starttile.png create mode 100644 theme/colored/add-bordered.svg create mode 100644 theme/colored/add.svg create mode 100644 theme/colored/change-bordered.svg create mode 100644 theme/colored/delete-bordered.svg create mode 100644 theme/colored/delete.svg create mode 100644 theme/colored/external.png create mode 100644 theme/colored/external.svg create mode 100644 theme/colored/external@2x.png create mode 100644 theme/colored/folder.png create mode 100644 theme/colored/folder.svg create mode 100644 theme/colored/folder@2x.png create mode 100644 theme/colored/icons/Nextcloud-icon-win-folder.svg create mode 100644 theme/colored/state-error.svg create mode 100644 theme/colored/state-offline.svg create mode 100644 theme/colored/state-ok.svg create mode 100644 theme/colored/state-pause.svg create mode 100644 theme/colored/state-sync.svg create mode 100644 theme/colored/state-warning.svg create mode 100644 theme/colored/talk-bordered.svg create mode 100644 theme/colored/user-status-away.svg create mode 100644 theme/colored/user-status-dnd.svg create mode 100644 theme/colored/user-status-invisible.svg create mode 100644 theme/colored/user-status-online.svg create mode 100644 theme/colored/wizard-files.png create mode 100644 theme/colored/wizard-files.svg create mode 100644 theme/colored/wizard-files@2x.png create mode 100644 theme/colored/wizard-groupware.png create mode 100644 theme/colored/wizard-groupware.svg create mode 100644 theme/colored/wizard-groupware@2x.png create mode 100644 theme/colored/wizard-nextcloud.png create mode 100644 theme/colored/wizard-nextcloud.svg create mode 100644 theme/colored/wizard-nextcloud@2x.png create mode 100644 theme/colored/wizard-talk.png create mode 100644 theme/colored/wizard-talk.svg create mode 100644 theme/colored/wizard-talk@2x.png create mode 100644 theme/colored/wizard_logo.png create mode 100644 theme/colored/wizard_logo.svg create mode 100644 theme/colored/wizard_logo@2x.png create mode 100644 theme/confirm.svg create mode 100644 theme/copy.svg create mode 100644 theme/delete.svg create mode 100644 theme/external.svg create mode 100644 theme/files.svg create mode 100644 theme/lock-broken.svg create mode 100644 theme/lock-http.svg create mode 100644 theme/lock-https.svg create mode 100644 theme/lock.svg create mode 100644 theme/magnifying-glass.svg create mode 100644 theme/more.svg create mode 100644 theme/network.svg create mode 100644 theme/nextcloud.VisualElementsManifest.xml create mode 100644 theme/public.svg create mode 100644 theme/reply.svg create mode 100644 theme/send.svg create mode 100644 theme/settings.svg create mode 100644 theme/share.svg create mode 100644 theme/sync-arrow.svg create mode 100644 theme/talk-app.svg create mode 100644 theme/white/activity.svg create mode 100644 theme/white/add.svg create mode 100644 theme/white/bell.svg create mode 100644 theme/white/calendar.svg create mode 100644 theme/white/caret-down.svg create mode 100644 theme/white/change.svg create mode 100644 theme/white/close.svg create mode 100644 theme/white/comment.svg create mode 100644 theme/white/confirm.svg create mode 100644 theme/white/control-next.svg create mode 100644 theme/white/control-prev.svg create mode 100644 theme/white/deck.svg create mode 100644 theme/white/edit.svg create mode 100644 theme/white/email.svg create mode 100644 theme/white/external.png create mode 100644 theme/white/external.svg create mode 100644 theme/white/external@2x.png create mode 100644 theme/white/folder.png create mode 100644 theme/white/folder.svg create mode 100644 theme/white/folder@2x.png create mode 100644 theme/white/more-apps.svg create mode 100644 theme/white/nc-assistant-app.svg create mode 100644 theme/white/settings.svg create mode 100644 theme/white/state-error.svg create mode 100644 theme/white/state-info.svg create mode 100644 theme/white/state-offline.svg create mode 100644 theme/white/state-ok.svg create mode 100644 theme/white/state-pause.svg create mode 100644 theme/white/state-sync.svg create mode 100644 theme/white/state-warning.svg create mode 100644 theme/white/talk-app.svg create mode 100644 theme/white/user.svg create mode 100644 theme/white/wizard-files.png create mode 100644 theme/white/wizard-files.svg create mode 100644 theme/white/wizard-files@2x.png create mode 100644 theme/white/wizard-groupware.png create mode 100644 theme/white/wizard-groupware.svg create mode 100644 theme/white/wizard-groupware@2x.png create mode 100644 theme/white/wizard-nextcloud.png create mode 100644 theme/white/wizard-nextcloud.svg create mode 100644 theme/white/wizard-nextcloud@2x.png create mode 100644 theme/white/wizard-talk.png create mode 100644 theme/white/wizard-talk.svg create mode 100644 theme/white/wizard-talk@2x.png create mode 100644 translations/client_TW.ts create mode 100644 translations/client_af.ts create mode 100644 translations/client_ar.ts create mode 100644 translations/client_bg.ts create mode 100644 translations/client_br.ts create mode 100644 translations/client_ca.ts create mode 100644 translations/client_cs.ts create mode 100644 translations/client_da.ts create mode 100644 translations/client_de.ts create mode 100644 translations/client_el.ts create mode 100644 translations/client_en.ts create mode 100644 translations/client_en_GB.ts create mode 100644 translations/client_eo.ts create mode 100644 translations/client_es.ts create mode 100644 translations/client_es_AR.ts create mode 100644 translations/client_es_CL.ts create mode 100644 translations/client_es_CO.ts create mode 100644 translations/client_es_CR.ts create mode 100644 translations/client_es_DO.ts create mode 100644 translations/client_es_EC.ts create mode 100644 translations/client_es_GT.ts create mode 100644 translations/client_es_HN.ts create mode 100644 translations/client_es_MX.ts create mode 100644 translations/client_es_SV.ts create mode 100644 translations/client_et.ts create mode 100644 translations/client_eu.ts create mode 100644 translations/client_fa.ts create mode 100644 translations/client_fi.ts create mode 100644 translations/client_fr.ts create mode 100644 translations/client_ga.ts create mode 100644 translations/client_gl.ts create mode 100644 translations/client_he.ts create mode 100644 translations/client_hr.ts create mode 100644 translations/client_hu.ts create mode 100644 translations/client_id.ts create mode 100644 translations/client_is.ts create mode 100644 translations/client_it.ts create mode 100644 translations/client_ja.ts create mode 100644 translations/client_ko.ts create mode 100644 translations/client_lt_LT.ts create mode 100644 translations/client_lv.ts create mode 100644 translations/client_mk.ts create mode 100644 translations/client_nb_NO.ts create mode 100644 translations/client_nl.ts create mode 100644 translations/client_oc.ts create mode 100644 translations/client_pl.ts create mode 100644 translations/client_pt.ts create mode 100644 translations/client_pt_BR.ts create mode 100644 translations/client_ro.ts create mode 100644 translations/client_ru.ts create mode 100644 translations/client_sc.ts create mode 100644 translations/client_sk.ts create mode 100644 translations/client_sl.ts create mode 100644 translations/client_sr.ts create mode 100644 translations/client_sv.ts create mode 100644 translations/client_th.ts create mode 100644 translations/client_tr.ts create mode 100644 translations/client_ug.ts create mode 100644 translations/client_uk.ts create mode 100644 translations/client_zh_CN.ts create mode 100644 translations/client_zh_HK.ts create mode 100644 translations/client_zh_TW.ts create mode 100644 version.h.in diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..cf5ff2c05 --- /dev/null +++ b/.clang-format @@ -0,0 +1,88 @@ +--- +# SPDX-FileCopyrightText: 2019 Christoph Cullmann +# SPDX-FileCopyrightText: 2019 Gernot Gebhard +# +# SPDX-License-Identifier: MIT + +# This file got automatically created by ECM, do not edit +# See https://clang.llvm.org/docs/ClangFormatStyleOptions.html for the config options +# and https://community.kde.org/Policies/Frameworks_Coding_Style#Clang-format_automatic_code_formatting +# for clang-format tips & tricks +--- +Language: JavaScript +DisableFormat: true +--- + +# Style for C++ +Language: Cpp + +# base is WebKit coding style: https://webkit.org/code-style-guidelines/ +# below are only things set that diverge from this style! +BasedOnStyle: WebKit + +# enforce C++11 (e.g. for std::vector> +Standard: Cpp11 + +# 4 spaces indent +TabWidth: 4 + +# 2 * 80 wide lines +ColumnLimit: 160 + +# sort includes inside line separated groups +SortIncludes: true + +# break before braces on function, namespace and class definitions. +BreakBeforeBraces: Linux + +# CrlInstruction *a; +PointerAlignment: Right + +# horizontally aligns arguments after an open bracket. +AlignAfterOpenBracket: Align + +# don't move all parameters to new line +AllowAllParametersOfDeclarationOnNextLine: false + +# no single line functions +AllowShortFunctionsOnASingleLine: None + +# always break before you encounter multi line strings +AlwaysBreakBeforeMultilineStrings: true + +# don't move arguments to own lines if they are not all on the same +BinPackArguments: false + +# don't move parameters to own lines if they are not all on the same +BinPackParameters: false + +# In case we have an if statement with multiple lines the operator should be at the beginning of the line +# but we do not want to break assignments +BreakBeforeBinaryOperators: NonAssignment + +# format C++11 braced lists like function calls +Cpp11BracedListStyle: true + +# do not put a space before C++11 braced lists +SpaceBeforeCpp11BracedList: false + +# remove empty lines +KeepEmptyLinesAtTheStartOfBlocks: false + +# no namespace indentation to keep indent level low +NamespaceIndentation: None + +# we use template< without space. +SpaceAfterTemplateKeyword: false + +# Always break after template declaration +AlwaysBreakTemplateDeclarations: true + +# macros for which the opening brace stays attached. +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE , wl_resource_for_each, wl_resource_for_each_safe ] + +# keep lambda formatting multi-line if not empty +AllowShortLambdasOnASingleLine: Empty + +# We do not want clang-format to put all arguments on a new line +AllowAllArgumentsOnNextLine: false diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 000000000..8e58c2c57 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,24 @@ +--- +kind: pipeline +name: Debian + +steps: +- name: build + image: ghcr.io/nextcloud/continuous-integration-client-debian:client-debian-3 + commands: + - /bin/bash -c "./admin/linux/debian/drone-build.sh" || echo "[WARNING] Debian build failed but this is a non-blocking CI event" + environment: + DEBIAN_SECRET_KEY: + from_secret: DEBIAN_SECRET_KEY + DEBIAN_SECRET_IV: + from_secret: DEBIAN_SECRET_IV +trigger: + branch: + - master + event: + - pull_request + - push +--- +kind: signature +hmac: e8978756454c02822b9b6b1b05013594fc5a6db04ac18537ef696fbf49700f7e +... diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..0bae470d7 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +c8d0f788e00bdae125a26d9159ce9efdd6325cd2 # Initial application of clang-format diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 000000000..94afcd1c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,185 @@ +name: "🐞 Bug report" +description: "Help us to improve by reporting a bug" +title: "[Bug]: " +labels: ["bug", "0. Needs triage"] +type: "Bug" +body: + - type: markdown + attributes: + value: | + ### 👍 Thank you for contributing to our project! + * This is the **issue tracker of Nextcloud**, please do NOT use this to get answers to your questions or get help for fixing your installation. You can find help debugging your system on our home user forums: https://help.nextcloud.com or, if you use Nextcloud in a large organization, ask our engineers on https://portal.nextcloud.com. See also https://nextcloud.com/support for support options. + * Please search the existing issues first, it's likely that your issue was already reported or even fixed. + - Go to https://github.com/nextcloud and type any word in the top search/command bar. You probably see something like "We couldn’t find any repositories matching ..." then click "Issues" in the left navigation. + - You can also filter by appending e. g. "state:open" to the search string. + - More info on search syntax within github: https://help.github.com/articles/searching-issues + - type: checkboxes + id: before-posting + attributes: + label: "⚠️ Before submitting, please verify the following: ⚠️" + description: All conditions are **required**. Your issue can be closed if these are checked incorrectly. + options: + - label: This is a **bug**, not a question or a configuration issue. + required: true + - label: This issue is **not** already reported on Github (I've searched it). + required: true + - label: Nextcloud Server and Desktop Client are **up to date**. See [Server Maintenance and Release Schedule](https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule) and [Desktop Releases](https://nextcloud.com/install/#install-clients) for supported versions. + required: true + - label: I agree to follow Nextcloud's [Code of Conduct](https://nextcloud.com/contribute/code-of-conduct/) + required: true + - type: textarea + id: bug-description + attributes: + label: Bug description + description: Provide a description of the bug you're experiencing. + value: | + The share dialog is looking incomplete. + ... + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Describe the steps to reproduce the bug. + value: | + 1. Right click on the file + 2. Click on Share Options + 3. The share dialog does not display the option to share by e-mail + ... + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: Describe what you expected to happen. + value: | + When clicking on the share dialog, share by e-mail should be an option. + ... + validations: + required: true + - type: input + id: files + attributes: + label: Which files are affected by this bug + description: Please, list **at least one file** that is affected by the issue reported. It will be easier to check the logs for errors. + validations: + required: true + - type: dropdown + id: system + attributes: + label: Operating system + description: In which operating system you are running the desktop client. + options: + - "Windows" + - "macOS" + - "Linux" + - "Other (e.g. FreeBSD)" + validations: + required: true + - type: input + id: distro + attributes: + label: Which version of the operating system you are running. + description: In case of Linux, provide the distribution + version. + placeholder: Windows 10 + validations: + required: true + - type: dropdown + id: install-method + attributes: + label: Package + description: Select installation method you used. + options: + - "Official Linux AppImage" + - "Official Windows MSI" + - "Official macOS 12+ universal pkg" + - "Community FlatPak" + - "Community SNAP package" + - "Distro package manager" + - "Compiled it myself" + - "Other" + validations: + required: true + - type: input + id: server-version + attributes: + label: Nextcloud Server version + description: Nextcloud Server version. + placeholder: 28.0.5 + validations: + required: true + - type: input + id: client-version + attributes: + label: Nextcloud Desktop Client version + description: Nextcloud Desktop Client version. + placeholder: 3.12.0 + validations: + required: true + - type: dropdown + id: fresh + attributes: + label: Is this bug present after an update or on a fresh install? + description: Select if bug is present after an update or on a fresh install. + options: + - "Updated from a minor version (ex. 3.4.2 to 3.4.4)" + - "Updated to a major version (ex. 3.3.6 to 3.4.0)" + - "Fresh desktop client install" + validations: + required: true + - type: dropdown + id: encryption + attributes: + label: Are you using the Nextcloud Server Encryption module? + description: | + Select if encryption is Enabled on your Nextcloud Server. + options: + - "Encryption is Enabled" + - "Encryption is Disabled" + validations: + required: true + - type: checkboxes + id: users + attributes: + label: Are you using an external user-backend? + description: | + Select all user-backends Enabled on your Nextcloud Server. + Describe in the "Additional info" section if you chose "Other". + options: + - label: "Default internal user-backend" + - label: "LDAP/ Active Directory" + - label: "SSO - SAML" + - label: "Other" + validations: + required: true + - type: textarea + id: desktop-logs + attributes: + label: Nextcloud Server logs + description: | + Provide Nextcloud Server logs lines. + Copy all contents from `data/nextcloud.log` or a RAW from `/settings/admin/logging` section: + > NOTE: This will be automatically formatted into code or attach the file to the issue. + render: shell + validations: + required: false + - type: textarea + id: additional-info + attributes: + label: Additional info + description: Any additional information related to the issue. + validations: + required: false + - type: markdown + attributes: + value: | + ## :warning: Desktop Client Logs + Under the "General" settings, you can click on **"Create Debug Archive"** to pick the location of where the desktop client will export the logs and the database to a zip file: https://docs.nextcloud.com/server/latest/admin_manual/desktop/troubleshooting.html#create-debug-archive + > Please attach the debug archive to this issue. You can edit it down to the bug report time window to reduce size. + - type: markdown + attributes: + value: | + ## :camera: Screenshots + Feel free to attach any screenshots that might help you to describe the bug your are experiencing. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..ad8a30caa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +contact_links: + - name: 🚨 Report a security or privacy issue + url: https://hackerone.com/nextcloud + about: Report security and privacy related issues privately to the Nextcloud team, so we can coordinate the fix and release without potentially exposing all Nextcloud servers and users in the meantime. + - name: ❓ Community Support and Help + url: https://help.nextcloud.com/ + about: Configuration, webserver/proxy or performance issues and other questions + - name: 💼 Nextcloud Enterprise + url: https://portal.nextcloud.com/ + about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 000000000..3abff5303 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,32 @@ +--- +name: 🚀 Feature request +about: Suggest an idea for this app +labels: 0. Needs triage +type: Enhancement +--- + + + +### How to use GitHub + +* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are interested into the same feature. +* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue. +* Subscribe to receive notifications on status change and new comments. + +--- + +## Feature request + +**Which Nextcloud Version are you currently using:** (see administration page) + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..22e46f7c7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..c2744c721 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,14 @@ + diff --git a/.github/workflows/check-translations.yml b/.github/workflows/check-translations.yml new file mode 100644 index 000000000..8c765e31d --- /dev/null +++ b/.github/workflows/check-translations.yml @@ -0,0 +1,18 @@ +name: Check translations + +on: + pull_request: + types: [opened, synchronize, reopened] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + checkTranslations: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3 + - name: Check German + run: | + [[ $(grep "Benötigt keine Übersetzung" translations/client_de.ts -c) -gt 0 ]] && exit 1 || exit 0 diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 000000000..8a7a32eee --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,20 @@ +name: Clang Format Checker +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: cpp-linter/cpp-linter-action@v2.13.4 + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: file + lines-changed-only: true + version: 14 + - name: Fail fast?! + if: steps.linter.outputs.checks-failed > 0 + run: echo "Some files failed the linting checks!" diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml new file mode 100644 index 000000000..547fcf415 --- /dev/null +++ b/.github/workflows/clang-tidy-review.yml @@ -0,0 +1,39 @@ +name: clang-tidy-review + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + clang-tidy: + runs-on: ubuntu-latest + container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.8.1-2 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Prepare compile_commands.json + run: | + cmake -G Ninja -B build -DCMAKE_PREFIX_PATH=/opt/qt -DQT_MAJOR_VERSION=6 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DOPENSSL_ROOT_DIR=/usr/local/lib64 + cd build && ninja + - name: Create results directory + run: | + mkdir clang-tidy-result + - name: Analyze + run: | + /usr/bin/git config --global --add safe.directory "$GITHUB_WORKSPACE" + /usr/bin/git diff -U0 HEAD^ | clang-tidy-diff-15.py -checks='-*,modernize-use-auto,modernize-use-using,modernize-use-nodiscard,modernize-use-nullptr,modernize-use-override,cppcoreguidelines-pro-type-static-cast-downcast' -p1 -path build -export-fixes clang-tidy-result/fixes.yml + - name: Run clang-tidy-pr-comments action + uses: platisd/clang-tidy-pr-comments@v1.6.1 # >1.4.3 switches to composite method w/ a forced python version and breaks things: https://github.com/actions/setup-python/issues/871 + with: + # The GitHub token (or a personal access token) + github_token: ${{ secrets.GITHUB_TOKEN }} + # The path to the clang-tidy fixes generated previously + clang_tidy_fixes: clang-tidy-result/fixes.yml + # Optionally set to true if you want the Action to request + # changes in case warnings are found + request_changes: true + # Optionally set the number of comments per review + # to avoid GitHub API timeouts for heavily loaded + # pull requests + suggestions_per_comment: 10 diff --git a/.github/workflows/fixup.yml b/.github/workflows/fixup.yml new file mode 100644 index 000000000..69da2bbb0 --- /dev/null +++ b/.github/workflows/fixup.yml @@ -0,0 +1,36 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Block fixup and squash commits + +on: + pull_request: + types: [opened, ready_for_review, reopened, synchronize] + +permissions: + contents: read + +concurrency: + group: fixup-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + commit-message-check: + if: github.event.pull_request.draft == false + + permissions: + pull-requests: write + name: Block fixup and squash commits + + runs-on: ubuntu-latest-low + + steps: + - name: Run check + uses: skjnldsv/block-fixup-merge-action@c138ea99e45e186567b64cf065ce90f7158c236a # v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux-appimage.yml b/.github/workflows/linux-appimage.yml new file mode 100644 index 000000000..020598b9e --- /dev/null +++ b/.github/workflows/linux-appimage.yml @@ -0,0 +1,74 @@ +name: Linux Appimage Package +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Linux Appimage Package + runs-on: ubuntu-latest + container: ghcr.io/nextcloud/continuous-integration-client-appimage-qt6:client-appimage-el8-6.8.2-1 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Configure, compile and package + id: build-appimage + env: + PR_ID: ${{ github.event.number }} + run: | + BUILDNR=${GITHUB_RUN_ID} VERSION_SUFFIX=${GITHUB_HEAD_REF} BUILD_UPDATER=ON DESKTOP_CLIENT_ROOT=`pwd` EXECUTABLE_NAME=nextcloud QT_BASE_DIR=/opt/qt OPENSSL_ROOT_DIR=/usr/local/lib64 /bin/bash -c "./admin/linux/build-appimage.sh" + + - name: Upload AppImage artifact + id: upload-appimage + uses: actions/upload-artifact@v4 + with: + name: nextcloud-appimage-pr-${{ github.event.number }} + path: ${{ steps.build-appimage.outputs.APPIMAGE_NAME }} + overwrite: true + compression-level: 0 # squashfs is already compressed + + - name: Comment AppImage + uses: actions/github-script@v7 + with: + script: | + const comment_identifier_string = ""; + + const comment_body = ` + ${comment_identifier_string} + + Artifact containing the AppImage: [nextcloud-appimage-pr-${{ github.event.number }}.zip](${{ steps.upload-appimage.outputs.artifact-url }}) + + SHA256 checksum: \`${{ steps.upload-appimage.outputs.artifact-digest }}\` + + To test this change/fix you can download the above artifact file, unzip it, and run it. + + Please make sure to quit your existing Nextcloud app and backup your data. + `; + + console.log("fetching old comments") + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + comments + .data + .filter(comment => comment.body?.includes(comment_identifier_string)) + .forEach(comment => { + console.log(`deleting previous AppImage comment with ID ${comment.id}`) + github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id, + }) + }); + + console.log("creating new comment") + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment_body, + }); diff --git a/.github/workflows/linux-clang-compile-tests.yml b/.github/workflows/linux-clang-compile-tests.yml new file mode 100644 index 000000000..ff3b49651 --- /dev/null +++ b/.github/workflows/linux-clang-compile-tests.yml @@ -0,0 +1,25 @@ +name: Linux Clang compilation and tests +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Linux Clang compilation and tests + runs-on: ubuntu-latest + container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.8.1-2 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Configure and compile + run: | + mkdir build + cd build + cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 + ninja + - name: Run tests + run: | + cd build + useradd -m -s /bin/bash test + chown -R test:test . + su -c 'xvfb-run ctest --output-on-failure' test diff --git a/.github/workflows/linux-gcc-compile-tests.yml b/.github/workflows/linux-gcc-compile-tests.yml new file mode 100644 index 000000000..679ea2472 --- /dev/null +++ b/.github/workflows/linux-gcc-compile-tests.yml @@ -0,0 +1,25 @@ +name: Linux GCC compilation and tests +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Linux GCC compilation and tests + runs-on: ubuntu-latest + container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.8.1-2 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Configure and compile + run: | + mkdir build + cd build + cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 + ninja + - name: Run tests + run: | + cd build + useradd -m -s /bin/bash test + chown -R test:test . + su -c 'xvfb-run ctest --output-on-failure' test diff --git a/.github/workflows/macos-build-and-test.yml b/.github/workflows/macos-build-and-test.yml new file mode 100644 index 000000000..f6c59d491 --- /dev/null +++ b/.github/workflows/macos-build-and-test.yml @@ -0,0 +1,71 @@ +name: macOS Build and Test +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: macOS Build and Test + timeout-minutes: 60 + runs-on: macos-14 + strategy: + matrix: + craft_options: [ + '--options nextcloud-client.buildFileProviderModule=False', + '--options nextcloud-client.buildFileProviderModule=True' + ] + env: + CRAFT_TARGET: macos-clang-arm64 + CRAFT_MASTER_LOCATION: ${{ github.workspace }}/CraftMaster + CRAFT_MASTER_CONFIG: ${{ github.workspace }}/craftmaster.ini + CRAFT_BLUEPRINT_OPTIONS: ${{ matrix.craft_options }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: List Xcode installations + run: sudo ls -1 /Applications | grep "Xcode" + + - name: Select Xcode 15.3 + run: sudo xcode-select -s /Applications/Xcode_15.3.app/Contents/Developer + + - name: Restore cache + uses: actions/cache@v4 + with: + path: ~/cache + key: macos-latest-${{ env.CRAFT_TARGET }} + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Install Homebrew dependencies + run: | + brew install homebrew/cask/inkscape + + - name: Download Craft + run: | + git clone -q --depth=1 https://invent.kde.org/packaging/craftmaster.git ${{ env.CRAFT_MASTER_LOCATION }} + + - name: Add Nextcloud client blueprints + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --add-blueprint-repository https://github.com/nextcloud/desktop-client-blueprints.git + + - name: Setup Craft + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c craft + + - name: Install Craft Nextcloud client dependencies + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --install-deps nextcloud-client + + - name: Build client + run: | + python "${{ env.CRAFT_MASTER_LOCATION }}/CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c --options nextcloud-client.srcDir=${{ github.workspace }} ${{ env.CRAFT_BLUEPRINT_OPTIONS }} nextcloud-client + + - name: Run tests + run: | + cd ${{ github.workspace }}/${{ env.CRAFT_TARGET }}/build/nextcloud-client/work/build + ctest --output-on-failure --output-junit testResult.xml + diff --git a/.github/workflows/needsinfo.yml b/.github/workflows/needsinfo.yml new file mode 100644 index 000000000..1d46f67c0 --- /dev/null +++ b/.github/workflows/needsinfo.yml @@ -0,0 +1,24 @@ +name: 'Close stale needs info issues' +on: + schedule: + - cron: '30 */8 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + operations-per-run: 1500 + days-before-stale: 28 + days-before-close: 14 + days-before-pr-close: -1 + only-labels: 'needs info' + stale-issue-label: 'stale needs info' + exempt-issue-labels: 'bug' + stale-issue-message: 'This issue has been marked as "needs info" 4 weeks ago. + Please take a look again and try to provide the information requested, + otherwise the issue will be automatically closed in 2 weeks. Thank you!' + close-issue-message: "This bug report is getting automatically closed due to no answer + since the issue has been staled. Thank you!" + exempt-all-pr-milestones: true diff --git a/.github/workflows/needsinfohelper.yaml b/.github/workflows/needsinfohelper.yaml new file mode 100644 index 000000000..daea688c4 --- /dev/null +++ b/.github/workflows/needsinfohelper.yaml @@ -0,0 +1,13 @@ +name: Remove Labels + +on: [issue_comment] + +jobs: + remove_labels: + runs-on: ubuntu-latest + steps: + - uses: actions-ecosystem/action-remove-labels@v1 + if: ${{ ! startsWith(github.event.comment.body, 'This issue has been marked as "needs info" 4 weeks ago.') && ! startsWith(github.event.comment.body, 'This bug report did not receive an update in the last 4 weeks.')}} + with: + labels: 'needs info' + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/qml-label-check.yml b/.github/workflows/qml-label-check.yml new file mode 100644 index 000000000..90c9e2619 --- /dev/null +++ b/.github/workflows/qml-label-check.yml @@ -0,0 +1,21 @@ +name: QML Label component check +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: QML Label component check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run label component count + run: | + MATCHESRESULT=$(find . -iname "*.qml" | xargs grep -r -e "^\s*Label\s*[{]" | wc -l | sed "s/ //g") + echo "MATCHES=${MATCHESRESULT}" >> $GITHUB_ENV + echo "EXPECTED_MATCHES=1" >> $GITHUB_ENV + - name: Check label component use count + if: env.MATCHES != env.EXPECTED_MATCHES + uses: actions/github-script@v7 + with: + script: | + core.setFailed('Using QML Labels! Make sure to use EnforcedPlainTextLabel instead!') diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 000000000..63652e10d --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,47 @@ +name: SonarCloud analysis +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: SonarCloud analysis + runs-on: ubuntu-latest + container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.8.1-2 + env: + SONAR_SERVER_URL: "https://sonarcloud.io" + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Restore cache + uses: actions/cache@v4 + with: + path: /cache + key: ${{ runner.os }} + + - name: Run build-wrapper + run: | + mkdir build + cd build + cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DQT_MAJOR_VERSION=6 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 -DBUILD_COVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} ninja + - name: Run tests + run: | + cd build + useradd -m -s /bin/bash test + chown -R test:test . + su -c 'xvfb-run ctest --output-on-failure --output-junit testResult.xml' test + - name: Generate coverage report + run: | + cd build + su -c 'ctest -T Coverage' test + - name: Run sonar-scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + cp sonar-project.properties build + cd build + sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..26d99a8cf --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: 'Close stale issues' +on: + schedule: + - cron: '30 */8 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + operations-per-run: 1500 + days-before-stale: 28 + days-before-close: 14 + days-before-pr-close: -1 + only-labels: 'bug,need info' + exempt-issue-labels: 'approved' + stale-issue-message: 'This bug report did not receive an update in the last 4 weeks. + Please take a look again and update the issue with new details, + otherwise the issue will be automatically closed in 2 weeks. Thank you!' + close-issue-message: "This bug report is getting automatically closed due to no answer + since the issue has been staled. Thank you!" + exempt-all-pr-milestones: true diff --git a/.github/workflows/windows-build-and-test.yml b/.github/workflows/windows-build-and-test.yml new file mode 100644 index 000000000..2aa869326 --- /dev/null +++ b/.github/workflows/windows-build-and-test.yml @@ -0,0 +1,91 @@ +name: Windows Build and Test +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Windows Build and Test + runs-on: windows-2022 + env: + CRAFT_TARGET: windows-msvc2022_64-cl + COBERTURA_COVERAGE_FILE: ${{ github.workspace }}\cobertura_coverage\coverage.xml + CRAFT_MASTER_LOCATION: ${{ github.workspace }}\CraftMaster + CRAFT_MASTER_CONFIG: ${{ github.workspace }}\craftmaster.ini + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install Craft Master with Nextcloud Client Deps + shell: pwsh + run: | + & cmd /C "git clone -q --depth=1 https://invent.kde.org/packaging/craftmaster.git ${{ env.CRAFT_MASTER_LOCATION }} 2>&1" + + function craft() { + python "${{ env.CRAFT_MASTER_LOCATION }}\CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c $args + if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE} + } + + craft --add-blueprint-repository [git]https://github.com/nextcloud/desktop-client-blueprints.git + craft craft + craft --install-deps nextcloud-client + + - name: Cache Install OpenCppCoverage + id: cache-install-opencppcoverage + uses: actions/cache@v4 + with: + path: C:\Program Files\OpenCppCoverage + key: ${{ runner.os }}-cache-install-opencppcoverage + + - name: Install OpenCppCoverage + if: steps.cache-install-opencppcoverage.outputs.cache-hit != 'true' + shell: pwsh + run: | + choco install opencppcoverage + + - name: Cache Install inkscape + id: cache-install-inkscape + uses: actions/cache@v4 + with: + path: C:\Program Files\inkscape + key: ${{ runner.os }}-cache-install-inkscape + + - name: Install inkscape + if: steps.cache-install-inkscape.outputs.cache-hit != 'true' + shell: pwsh + run: | + choco install inkscape + + - name: Setup PATH + shell: pwsh + run: | + echo "C:\Program Files\OpenCppCoverage" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "${{ github.workspace }}\${{ env.CRAFT_TARGET }}\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Compile + shell: pwsh + run: | + function craft() { + python "${{ env.CRAFT_MASTER_LOCATION }}\CraftMaster.py" --config "${{ env.CRAFT_MASTER_CONFIG }}" --target ${{ env.CRAFT_TARGET }} -c $args + if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE} + } + + craft --src-dir ${{ github.workspace }} nextcloud-client + + - name: Run tests with coverage + shell: pwsh + run: | + function runTests() { + $buildFolder = "${{ github.workspace }}\${{ env.CRAFT_TARGET }}\build\nextcloud-client\work\build" + + cd $buildFolder + + $binFolder = "$buildFolder\bin" + + & ctest --output-on-failure --timeout 300 + } + + runTests diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..0a40dfd41 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/3rdparty/libcrashreporter-qt"] + path = src/3rdparty/libcrashreporter-qt + url = https://github.com/dschmidt/libcrashreporter-qt.git diff --git a/.swift-format.json b/.swift-format.json new file mode 100644 index 000000000..722b5de35 --- /dev/null +++ b/.swift-format.json @@ -0,0 +1,69 @@ +{ + "fileScopedDeclarationPrivacy" : { + "accessLevel" : "private" + }, + "indentation" : { + "spaces" : 4 + }, + "indentConditionalCompilationBlocks" : true, + "indentSwitchCaseLabels" : false, + "lineBreakAroundMultilineExpressionChainComponents" : false, + "lineBreakBeforeControlFlowKeywords" : false, + "lineBreakBeforeEachArgument" : false, + "lineBreakBeforeEachGenericRequirement" : false, + "lineLength" : 100, + "maximumBlankLines" : 1, + "multiElementCollectionTrailingCommas" : true, + "noAssignmentInExpressions" : { + "allowedFunctions" : [ + "XCTAssertNoThrow" + ] + }, + "prioritizeKeepingFunctionOutputTogether" : false, + "respectsExistingLineBreaks" : true, + "rules" : { + "AllPublicDeclarationsHaveDocumentation" : false, + "AlwaysUseLiteralForEmptyCollectionInit" : false, + "AlwaysUseLowerCamelCase" : true, + "AmbiguousTrailingClosureOverload" : true, + "BeginDocumentationCommentWithOneLineSummary" : false, + "DoNotUseSemicolons" : true, + "DontRepeatTypeInStaticProperties" : true, + "FileScopedDeclarationPrivacy" : true, + "FullyIndirectEnum" : true, + "GroupNumericLiterals" : true, + "IdentifiersMustBeASCII" : true, + "NeverForceUnwrap" : false, + "NeverUseForceTry" : false, + "NeverUseImplicitlyUnwrappedOptionals" : false, + "NoAccessLevelOnExtensionDeclaration" : true, + "NoAssignmentInExpressions" : true, + "NoBlockComments" : true, + "NoCasesWithOnlyFallthrough" : true, + "NoEmptyTrailingClosureParentheses" : true, + "NoLabelsInCasePatterns" : true, + "NoLeadingUnderscores" : false, + "NoParensAroundConditions" : true, + "NoPlaygroundLiterals" : true, + "NoVoidReturnOnFunctionSignature" : true, + "OmitExplicitReturns" : false, + "OneCasePerLine" : true, + "OneVariableDeclarationPerLine" : true, + "OnlyOneTrailingClosureArgument" : true, + "OrderedImports" : true, + "ReplaceForEachWithForLoop" : true, + "ReturnVoidInsteadOfEmptyTuple" : true, + "TypeNamesShouldBeCapitalized" : true, + "UseEarlyExits" : false, + "UseLetInEveryBoundCaseVariable" : true, + "UseShorthandTypeNames" : true, + "UseSingleLinePropertyGetter" : true, + "UseSynthesizedInitializer" : true, + "UseTripleSlashForDocumentationComments" : true, + "UseWhereClausesInForLoops" : false, + "ValidateDocumentationComments" : false + }, + "spacesAroundRangeFormationOperators" : false, + "tabWidth" : 8, + "version" : 1 +} diff --git a/.tag b/.tag new file mode 100644 index 000000000..a56ab71cc --- /dev/null +++ b/.tag @@ -0,0 +1 @@ +d004c948bbdd5a0547e44e33e02899bf2f3046a9 diff --git a/.tx/config b/.tx/config new file mode 100644 index 000000000..5a64101d6 --- /dev/null +++ b/.tx/config @@ -0,0 +1,16 @@ +[main] +host = https://www.transifex.com +lang_map = bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja, pt_PT: pt, et_EE: et + +[o:nextcloud:p:nextcloud:r:client] +file_filter = translations/client_.ts +source_file = translations/client_en.ts +source_lang = en +type = QT + +[o:nextcloud:p:nextcloud:r:client-desktop] +file_filter = nextcloud.client-desktop/_translation.desktop +source_file = mirall.desktop.in +source_lang = en +type = DESKTOP + diff --git a/.tx/nextcloud.client-desktop/ar_translation b/.tx/nextcloud.client-desktop/ar_translation new file mode 100644 index 000000000..c2339b01f --- /dev/null +++ b/.tx/nextcloud.client-desktop/ar_translation @@ -0,0 +1,24 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +GenericName[ar]=مزامنة المجلد diff --git a/.tx/nextcloud.client-desktop/bg_translation b/.tx/nextcloud.client-desktop/bg_translation new file mode 100644 index 000000000..4d86ff2da --- /dev/null +++ b/.tx/nextcloud.client-desktop/bg_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[bg_BG]=@APPLICATION_ICON_NAME@ +Name[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране +Comment[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране +GenericName[bg_BG]=Синхронизиране на папка diff --git a/.tx/nextcloud.client-desktop/br_translation b/.tx/nextcloud.client-desktop/br_translation new file mode 100644 index 000000000..9cf82c6fe --- /dev/null +++ b/.tx/nextcloud.client-desktop/br_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[br]=@APPLICATION_ICON_NAME@ +Comment[br]=@APPLICATION_NAME@ burev kempreet an implijer +GenericName[br]=Tuliad kemprenan diff --git a/.tx/nextcloud.client-desktop/ca_translation b/.tx/nextcloud.client-desktop/ca_translation new file mode 100644 index 000000000..6c69c6600 --- /dev/null +++ b/.tx/nextcloud.client-desktop/ca_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[ca]=@APPLICATION_ICON_NAME@ +Name[ca]=@APPLICATION_NAME@ per a escriptori +Comment[ca]=Client de sincronització d'escriptori del @APPLICATION_NAME@ +GenericName[ca]=Sincronització de carpetes diff --git a/.tx/nextcloud.client-desktop/cs_translation b/.tx/nextcloud.client-desktop/cs_translation new file mode 100644 index 000000000..739d5dd46 --- /dev/null +++ b/.tx/nextcloud.client-desktop/cs_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[cs_CZ]=@APPLICATION_ICON_NAME@ +Name[cs_CZ]=@APPLICATION_NAME@ Desktop +Comment[cs_CZ]=@APPLICATION_NAME@ synchronizační klient pro desktop +GenericName[cs_CZ]=Synchronizace složek diff --git a/.tx/nextcloud.client-desktop/cy_GB_translation b/.tx/nextcloud.client-desktop/cy_GB_translation new file mode 100644 index 000000000..1a5970e04 --- /dev/null +++ b/.tx/nextcloud.client-desktop/cy_GB_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[cy_GB]=@APPLICATION_ICON_NAME@ +Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith +Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith +GenericName[cy_GB]=Cydweddu Ffolder diff --git a/.tx/nextcloud.client-desktop/da_translation b/.tx/nextcloud.client-desktop/da_translation new file mode 100644 index 000000000..7d2082605 --- /dev/null +++ b/.tx/nextcloud.client-desktop/da_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[da]=@APPLICATION_ICON_NAME@ +Name[da]=Skrivebordsklient til @APPLICATION_NAME@ +Comment[da]=Klient til @APPLICATION_NAME@-skrivebordssynkronisering +GenericName[da]=Mappesynkronisering diff --git a/.tx/nextcloud.client-desktop/de_translation b/.tx/nextcloud.client-desktop/de_translation new file mode 100644 index 000000000..a7f88b215 --- /dev/null +++ b/.tx/nextcloud.client-desktop/de_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[de]=@APPLICATION_ICON_NAME@ +Name[de]=@APPLICATION_NAME@ Desktop +Comment[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung +GenericName[de]=Ordner-Synchronisation diff --git a/.tx/nextcloud.client-desktop/el_translation b/.tx/nextcloud.client-desktop/el_translation new file mode 100644 index 000000000..f0e6ca9b6 --- /dev/null +++ b/.tx/nextcloud.client-desktop/el_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[el]=@APPLICATION_ICON_NAME@ +Name[el]=@APPLICATION_NAME@ Επιφάνεια Εργασίας +Comment[el]=@APPLICATION_NAME@ πρόγραμμα συγχρονισμού +GenericName[el]=Συγχρονισμός φακέλου diff --git a/.tx/nextcloud.client-desktop/en_GB_translation b/.tx/nextcloud.client-desktop/en_GB_translation new file mode 100644 index 000000000..44affaf91 --- /dev/null +++ b/.tx/nextcloud.client-desktop/en_GB_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[en_GB]=@APPLICATION_ICON_NAME@ +Name[en_GB]=@APPLICATION_NAME@ Desktop +Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client +GenericName[en_GB]=Folder Sync diff --git a/.tx/nextcloud.client-desktop/eo_translation b/.tx/nextcloud.client-desktop/eo_translation new file mode 100644 index 000000000..db0a67b87 --- /dev/null +++ b/.tx/nextcloud.client-desktop/eo_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[eo]=@APPLICATION_ICON_NAME@ +Comment[eo]=@APPLICATION_NAME@ sinkroniga kliento +GenericName[eo]=Dosieruja sinkronigo diff --git a/.tx/nextcloud.client-desktop/es_AR_translation b/.tx/nextcloud.client-desktop/es_AR_translation new file mode 100644 index 000000000..50155b2e6 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_AR_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[es_AR]=@APPLICATION_ICON_NAME@ +Name[es_AR]=@APPLICATION_NAME@ Desktop +Comment[es_AR]=@APPLICATION_NAME@ cliente de sincronización de escritorio +GenericName[es_AR]=Sincronización de carpetas diff --git a/.tx/nextcloud.client-desktop/es_CL_translation b/.tx/nextcloud.client-desktop/es_CL_translation new file mode 100644 index 000000000..7bfbb8d66 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_CL_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_CL]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_CL]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_CO_translation b/.tx/nextcloud.client-desktop/es_CO_translation new file mode 100644 index 000000000..53a4316b9 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_CO_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_CO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_CO]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_CR_translation b/.tx/nextcloud.client-desktop/es_CR_translation new file mode 100644 index 000000000..bf82091b6 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_CR_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_CR]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_CR]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_DO_translation b/.tx/nextcloud.client-desktop/es_DO_translation new file mode 100644 index 000000000..8ca7db555 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_DO_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[es_DO]=@APPLICATION_ICON_NAME@ +Comment[es_DO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_DO]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_EC_translation b/.tx/nextcloud.client-desktop/es_EC_translation new file mode 100644 index 000000000..00d19676d --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_EC_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_EC]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_EC]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_GT_translation b/.tx/nextcloud.client-desktop/es_GT_translation new file mode 100644 index 000000000..7392f512c --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_GT_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_GT]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_GT]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_MX_translation b/.tx/nextcloud.client-desktop/es_MX_translation new file mode 100644 index 000000000..f261ab017 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_MX_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[es_MX]=@APPLICATION_ICON_NAME@ +Name[es_MX]=@APPLICATION_NAME@ Desktop +Comment[es_MX]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_MX]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_SV_translation b/.tx/nextcloud.client-desktop/es_SV_translation new file mode 100644 index 000000000..b57616da0 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_SV_translation @@ -0,0 +1,25 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[es_SV]=@APPLICATION_NAME@ Cliente de sincronización de escritorio +GenericName[es_SV]=Sincronización de carpeta diff --git a/.tx/nextcloud.client-desktop/es_translation b/.tx/nextcloud.client-desktop/es_translation new file mode 100644 index 000000000..36cc4bab9 --- /dev/null +++ b/.tx/nextcloud.client-desktop/es_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[es]=@APPLICATION_ICON_NAME@ +Name[es]=@APPLICATION_NAME@ Desktop +Comment[es]=@APPLICATION_NAME@ desktop synchronization client +GenericName[es]=Sincronización de carpetas diff --git a/.tx/nextcloud.client-desktop/et_translation b/.tx/nextcloud.client-desktop/et_translation new file mode 100644 index 000000000..8f3c0c5cd --- /dev/null +++ b/.tx/nextcloud.client-desktop/et_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[et_EE]=@APPLICATION_ICON_NAME@ +Comment[et_EE]=@APPLICATION_NAME@ töölaua sünkroniseerimise klient +GenericName[et_EE]=Kausta Sünkroonimine diff --git a/.tx/nextcloud.client-desktop/eu_translation b/.tx/nextcloud.client-desktop/eu_translation new file mode 100644 index 000000000..b3b8719eb --- /dev/null +++ b/.tx/nextcloud.client-desktop/eu_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[eu]=@APPLICATION_ICON_NAME@ +Name[eu]=@APPLICATION_NAME@ Mahaigaina +Comment[eu]=@APPLICATION_NAME@ mahaigainerako sinkronizazio bezeroa +GenericName[eu]=Karpeta-sinkronizazioa diff --git a/.tx/nextcloud.client-desktop/fa_translation b/.tx/nextcloud.client-desktop/fa_translation new file mode 100644 index 000000000..41ff3d666 --- /dev/null +++ b/.tx/nextcloud.client-desktop/fa_translation @@ -0,0 +1,24 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Comment[fa]=@ APPLICATION_NAME @ مشتری هماهنگ سازی دسکتاپ diff --git a/.tx/nextcloud.client-desktop/fi_translation b/.tx/nextcloud.client-desktop/fi_translation new file mode 100644 index 000000000..85daf7e81 --- /dev/null +++ b/.tx/nextcloud.client-desktop/fi_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[fi_FI]=@APPLICATION_ICON_NAME@ +Name[fi_FI]=@APPLICATION_NAME@ Työpöytä +Comment[fi_FI]=@APPLICATION_NAME@ työpöydän synkronointipääte +GenericName[fi_FI]=Kansio synkronointi diff --git a/.tx/nextcloud.client-desktop/fr_translation b/.tx/nextcloud.client-desktop/fr_translation new file mode 100644 index 000000000..95215b978 --- /dev/null +++ b/.tx/nextcloud.client-desktop/fr_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[fr]=@APPLICATION_ICON_NAME@ +Name[fr]=@APPLICATION_NAME@ Bureau +Comment[fr]=Client de synchronisation @APPLICATION_NAME@ +GenericName[fr]=Synchro du dossier diff --git a/.tx/nextcloud.client-desktop/gl_translation b/.tx/nextcloud.client-desktop/gl_translation new file mode 100644 index 000000000..ee420804c --- /dev/null +++ b/.tx/nextcloud.client-desktop/gl_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[gl]=@APPLICATION_ICON_NAME@ +Comment[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio +GenericName[gl]=Sincronización de cartafol diff --git a/.tx/nextcloud.client-desktop/he_translation b/.tx/nextcloud.client-desktop/he_translation new file mode 100644 index 000000000..316e7460c --- /dev/null +++ b/.tx/nextcloud.client-desktop/he_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[he]=@APPLICATION_ICON_NAME@ +Comment[he]=@APPLICATION_NAME@ לקוח סנכרון לשולחן העבודה +GenericName[he]=סנכרון תיקיות diff --git a/.tx/nextcloud.client-desktop/hr_translation b/.tx/nextcloud.client-desktop/hr_translation new file mode 100644 index 000000000..3e73779fa --- /dev/null +++ b/.tx/nextcloud.client-desktop/hr_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[hr]=@APPLICATION_ICON_NAME@ +Name[hr]=@APPLICATION_NAME@ Desktop +Comment[hr]=@APPLICATION_NAME@ klijent za sinkronizaciju računala +GenericName[hr]=Sinkronizacija mapa diff --git a/.tx/nextcloud.client-desktop/hu_translation b/.tx/nextcloud.client-desktop/hu_translation new file mode 100644 index 000000000..34a3a89c6 --- /dev/null +++ b/.tx/nextcloud.client-desktop/hu_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[hu_HU]=@APPLICATION_ICON_NAME@ +Name[hu_HU]=@APPLICATION_NAME@ Desktop +Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizálási kliens +GenericName[hu_HU]=Mappaszinkronizálás diff --git a/.tx/nextcloud.client-desktop/id_translation b/.tx/nextcloud.client-desktop/id_translation new file mode 100644 index 000000000..072055884 --- /dev/null +++ b/.tx/nextcloud.client-desktop/id_translation @@ -0,0 +1,24 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +GenericName[id]=Sinkronisasi Folder diff --git a/.tx/nextcloud.client-desktop/is_translation b/.tx/nextcloud.client-desktop/is_translation new file mode 100644 index 000000000..521c9b557 --- /dev/null +++ b/.tx/nextcloud.client-desktop/is_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[is]=@APPLICATION_ICON_NAME@ +Name[is]=@APPLICATION_NAME@ forrit til samstillingar við tölvu +Comment[is]=@APPLICATION_NAME@ forrit til samstillingar við tölvu +GenericName[is]=Samstilling á möppum diff --git a/.tx/nextcloud.client-desktop/it_translation b/.tx/nextcloud.client-desktop/it_translation new file mode 100644 index 000000000..9f8d3fde5 --- /dev/null +++ b/.tx/nextcloud.client-desktop/it_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[it]=@APPLICATION_ICON_NAME@ +Name[it]=@APPLICATION_NAME@ Desktop +Comment[it]=Client di sincronizzazione desktop di @APPLICATION_NAME@ +GenericName[it]=Sincronizzazione cartelle diff --git a/.tx/nextcloud.client-desktop/ja_translation b/.tx/nextcloud.client-desktop/ja_translation new file mode 100644 index 000000000..73f19903d --- /dev/null +++ b/.tx/nextcloud.client-desktop/ja_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[ja_JP]=@APPLICATION_ICON_NAME@ +Name[ja_JP]=@APPLICATION_NAME@ デスクトップ +Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント +GenericName[ja_JP]=フォルダーを同期する diff --git a/.tx/nextcloud.client-desktop/ko_translation b/.tx/nextcloud.client-desktop/ko_translation new file mode 100644 index 000000000..1e58a8a6e --- /dev/null +++ b/.tx/nextcloud.client-desktop/ko_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[ko]=@APPLICATION_ICON_NAME@ +Name[ko]=@APPLICATION_NAME@ 데스크탑 +Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트 +GenericName[ko]=폴더 동기화 diff --git a/.tx/nextcloud.client-desktop/lt_LT_translation b/.tx/nextcloud.client-desktop/lt_LT_translation new file mode 100644 index 000000000..317815d39 --- /dev/null +++ b/.tx/nextcloud.client-desktop/lt_LT_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[lt_LT]=@APPLICATION_ICON_NAME@ +Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo kliento programa +GenericName[lt_LT]=Aplankų sinchronizavimas diff --git a/.tx/nextcloud.client-desktop/lv_translation b/.tx/nextcloud.client-desktop/lv_translation new file mode 100644 index 000000000..06cc4b44e --- /dev/null +++ b/.tx/nextcloud.client-desktop/lv_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[lv]=@APPLICATION_ICON_NAME@ +Comment[lv]=@APPLICATION_NAME@ darbavirsmas sinhronizešanas klients +GenericName[lv]=Mapju Sinhronizēšana diff --git a/.tx/nextcloud.client-desktop/mk_translation b/.tx/nextcloud.client-desktop/mk_translation new file mode 100644 index 000000000..200c1ea9d --- /dev/null +++ b/.tx/nextcloud.client-desktop/mk_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[mk]=@APPLICATION_ICON_NAME@ +Name[mk]=@APPLICATION_NAME@ Десктоп +Comment[mk]=@APPLICATION_NAME@ клиент за синхронизација на компјутер +GenericName[mk]=Папка за синхронизација diff --git a/.tx/nextcloud.client-desktop/nb_translation b/.tx/nextcloud.client-desktop/nb_translation new file mode 100644 index 000000000..c2b1a5b57 --- /dev/null +++ b/.tx/nextcloud.client-desktop/nb_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[nb_NO]=@APPLICATION_ICON_NAME@ +Name[nb_NO]=@APPLICATION_NAME@ skrivebord +Comment[nb_NO]=@APPLICATION_NAME@ klient for synkroinisering +GenericName[nb_NO]=Mappe synkroinisering diff --git a/.tx/nextcloud.client-desktop/nl_translation b/.tx/nextcloud.client-desktop/nl_translation new file mode 100644 index 000000000..a8dd86aa8 --- /dev/null +++ b/.tx/nextcloud.client-desktop/nl_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[nl]=@APPLICATION_ICON_NAME@ +Name[nl]=@APPLICATION_NAME@ Desktop +Comment[nl]=@APPLICATION_NAME@ desktopsynchronisatieclient +GenericName[nl]=Map synchronisatie diff --git a/.tx/nextcloud.client-desktop/oc_translation b/.tx/nextcloud.client-desktop/oc_translation new file mode 100644 index 000000000..b028591d4 --- /dev/null +++ b/.tx/nextcloud.client-desktop/oc_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[oc]=@APPLICATION_ICON_NAME@ +Name[oc]=@APPLICATION_NAME@ Burèu +Comment[oc]=@APPLICATION_NAME@ client de sincronizacion +GenericName[oc]=Sincro. dossièr diff --git a/.tx/nextcloud.client-desktop/pl_translation b/.tx/nextcloud.client-desktop/pl_translation new file mode 100644 index 000000000..6518082fc --- /dev/null +++ b/.tx/nextcloud.client-desktop/pl_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[pl]=@APPLICATION_ICON_NAME@ +Name[pl]=@APPLICATION_NAME@ Desktop +Comment[pl]=Desktopowy klient synchronizacji @APPLICATION_NAME@ +GenericName[pl]=Katalog synchronizacji diff --git a/.tx/nextcloud.client-desktop/pt_BR_translation b/.tx/nextcloud.client-desktop/pt_BR_translation new file mode 100644 index 000000000..775bcc7fe --- /dev/null +++ b/.tx/nextcloud.client-desktop/pt_BR_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[pt_BR]=@APPLICATION_ICON_NAME@ +Name[pt_BR]=@APPLICATION_NAME@ Desktop +Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização desktop +GenericName[pt_BR]=Sincronizar pasta diff --git a/.tx/nextcloud.client-desktop/pt_translation b/.tx/nextcloud.client-desktop/pt_translation new file mode 100644 index 000000000..984c5d2fc --- /dev/null +++ b/.tx/nextcloud.client-desktop/pt_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[pt_PT]=@APPLICATION_ICON_NAME@ +Name[pt_PT]=@APPLICATION_NAME@ - Área de Trabalho +Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização da Área de Trabalho +GenericName[pt_PT]=Sincronização de Pasta diff --git a/.tx/nextcloud.client-desktop/ro_translation b/.tx/nextcloud.client-desktop/ro_translation new file mode 100644 index 000000000..349fc983c --- /dev/null +++ b/.tx/nextcloud.client-desktop/ro_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[ro]=@APPLICATION_ICON_NAME@ +Name[ro]=@Numele_aplicației@ Client de sincronizare pentru PC +Comment[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop +GenericName[ro]=Sincronizare director diff --git a/.tx/nextcloud.client-desktop/ru_translation b/.tx/nextcloud.client-desktop/ru_translation new file mode 100644 index 000000000..521aaeb39 --- /dev/null +++ b/.tx/nextcloud.client-desktop/ru_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[ru]=@APPLICATION_ICON_NAME@ +Name[ru]=@APPLICATION_NAME@ Desktop +Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК +GenericName[ru]=Синхронизация папок diff --git a/.tx/nextcloud.client-desktop/sc_translation b/.tx/nextcloud.client-desktop/sc_translation new file mode 100644 index 000000000..b2e3d725b --- /dev/null +++ b/.tx/nextcloud.client-desktop/sc_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sc]=@NÙMENE_ICONA_APLICATZIONE@ +Name[sc]=@NÙMENE_APLICATZIONE@ Iscrivania +Comment[sc]=@NÙMENE_APLICATZIONE@ cliente de sincronizatzione iscrivania +GenericName[sc]=Sincronizadore de cartellas diff --git a/.tx/nextcloud.client-desktop/sk_translation b/.tx/nextcloud.client-desktop/sk_translation new file mode 100644 index 000000000..733db9bd2 --- /dev/null +++ b/.tx/nextcloud.client-desktop/sk_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sk_SK]=@APPLICATION_ICON_NAME@ +Name[sk_SK]=@APPLICATION_NAME@ Desktop +Comment[sk_SK]=@APPLICATION_NAME@ synchronizačný klient pre PC +GenericName[sk_SK]=Synchronizácia priečinkov diff --git a/.tx/nextcloud.client-desktop/sl_translation b/.tx/nextcloud.client-desktop/sl_translation new file mode 100644 index 000000000..359ba2c0f --- /dev/null +++ b/.tx/nextcloud.client-desktop/sl_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sl]=@APPLICATION_ICON_NAME@ +Name[sl]=Namizni program @APPLICATION_NAME@ +Comment[sl]=Program za usklajevanje @APPLICATION_NAME@ +GenericName[sl]=Usklajevanje map diff --git a/.tx/nextcloud.client-desktop/sr_translation b/.tx/nextcloud.client-desktop/sr_translation new file mode 100644 index 000000000..eed9f6803 --- /dev/null +++ b/.tx/nextcloud.client-desktop/sr_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sr]=@APPLICATION_ICON_NAME@ +Comment[sr]=@APPLICATION_NAME@ десктоп клијент за синхронизацију +GenericName[sr]=Синхронизација фасцикли diff --git a/.tx/nextcloud.client-desktop/sv_translation b/.tx/nextcloud.client-desktop/sv_translation new file mode 100644 index 000000000..218b8353d --- /dev/null +++ b/.tx/nextcloud.client-desktop/sv_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sv]=@APPLICATION_ICON_NAME@ +Name[sv]=@APPLICATION_NAME@ Skrivbord +Comment[sv]=@APPLICATION_NAME@ desktopssynkroniseringsklient +GenericName[sv]=Mappsynkronisering diff --git a/.tx/nextcloud.client-desktop/sw_translation b/.tx/nextcloud.client-desktop/sw_translation new file mode 100644 index 000000000..66e495421 --- /dev/null +++ b/.tx/nextcloud.client-desktop/sw_translation @@ -0,0 +1,26 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[sw]=@APPLICATION_ICON_NAME@ +Comment[sw]=Teja ya @APPLICATION_NAME@ ya kufanana faili kwa seva na faili ziko hapa +GenericName[sw]=Fanana Kabrasha diff --git a/.tx/nextcloud.client-desktop/th_translation b/.tx/nextcloud.client-desktop/th_translation new file mode 100644 index 000000000..5f0c3e2cb --- /dev/null +++ b/.tx/nextcloud.client-desktop/th_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[th_TH]=@APPLICATION_ICON_NAME@ +Name[th_TH]=@APPLICATION_NAME@ เดสก์ท็อป +Comment[th_TH]=ไคลเอ็นต์ซิงโครไนซ์ @APPLICATION_NAME@ บนเดสก์ท็อป +GenericName[th_TH]=ซิงค์โฟลเดอร์ diff --git a/.tx/nextcloud.client-desktop/tr_translation b/.tx/nextcloud.client-desktop/tr_translation new file mode 100644 index 000000000..67b1b1832 --- /dev/null +++ b/.tx/nextcloud.client-desktop/tr_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[tr]=@APPLICATION_ICON_NAME@ +Name[tr]=@APPLICATION_NAME@ Masaüstü +Comment[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi +GenericName[tr]=Klasör eşitleme diff --git a/.tx/nextcloud.client-desktop/uk_translation b/.tx/nextcloud.client-desktop/uk_translation new file mode 100644 index 000000000..3301d5f4b --- /dev/null +++ b/.tx/nextcloud.client-desktop/uk_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[uk]=@APPLICATION_ICON_NAME@ +Name[uk]=@APPLICATION_NAME@ Desktop +Comment[uk]=Клієнт синхронізації @APPLICATION_NAME@ для ПК +GenericName[uk]=Синхронізація тек diff --git a/.tx/nextcloud.client-desktop/vi_translation b/.tx/nextcloud.client-desktop/vi_translation new file mode 100644 index 000000000..a62e953f2 --- /dev/null +++ b/.tx/nextcloud.client-desktop/vi_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[vi]=@APPLICATION_ICON_NAME@ +Name[vi]=@APPLICATION_NAME@ Máy tính +Comment[vi]=Ứng dụng đồng bộ @APPLICATION_NAME@ cho máy tính +GenericName[vi]=Đồng bộ thư mục diff --git a/.tx/nextcloud.client-desktop/zh_CN_translation b/.tx/nextcloud.client-desktop/zh_CN_translation new file mode 100644 index 000000000..bff0acab6 --- /dev/null +++ b/.tx/nextcloud.client-desktop/zh_CN_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[zh_CN]=@APPLICATION_ICON_NAME@ +Name[zh_CN]=@APPLICATION_NAME@ 桌面 +Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端 +GenericName[zh_CN]=文件夹同步 diff --git a/.tx/nextcloud.client-desktop/zh_HK_translation b/.tx/nextcloud.client-desktop/zh_HK_translation new file mode 100644 index 000000000..ae62693be --- /dev/null +++ b/.tx/nextcloud.client-desktop/zh_HK_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[zh_HK]=@APPLICATION_ICON_NAME@ +Name[zh_HK]=@APPLICATION_NAME@ 桌面電腦 +Comment[zh_HK]= @APPLICATION_NAME@ 桌面同步客戶端 +GenericName[zh_HK]=資料夾同步 diff --git a/.tx/nextcloud.client-desktop/zh_TW_translation b/.tx/nextcloud.client-desktop/zh_TW_translation new file mode 100644 index 000000000..789c7023b --- /dev/null +++ b/.tx/nextcloud.client-desktop/zh_TW_translation @@ -0,0 +1,27 @@ +[Desktop Entry] +Categories=Utility;X-SuSE-SyncUtility; +Type=Application +Exec=@APPLICATION_EXECUTABLE@ %u +Name=@APPLICATION_NAME@ Desktop +Comment=@APPLICATION_NAME@ desktop synchronization client +GenericName=Folder Sync +Icon=@APPLICATION_ICON_NAME@ +Keywords=@APPLICATION_NAME@;syncing;file;sharing; +X-GNOME-Autostart-Delay=3 +MimeType=application/vnd.@APPLICATION_EXECUTABLE@;x-scheme-handler/@APPLICATION_URI_HANDLER_SCHEME@; +Actions=Quit; + +# Translations + + +[Desktop Action Quit] +Exec=@APPLICATION_EXECUTABLE@ --quit +Name=Quit @APPLICATION_NAME@ +Icon=@APPLICATION_EXECUTABLE@ + + +# Translations +Icon[zh_TW]=@APPLICATION_ICON_NAME@ +Name[zh_TW]=@APPLICATION_NAME@ 桌面版 +Comment[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端 +GenericName[zh_TW]=資料夾同步 diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 000000000..7c60e732f --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,392 @@ + +# Authors + +- adrb +- Adrian Brzezinski +- Adrien +- AJ Jordan +- ajasja +- Aldaris1985 +- Aleksandr Borisenko +- alex-z +- Alexander Batischev +- Alfie "Azelphur" Day +- alkl58 +- allexzander +- allexzander +- Andre-Schuiki +- Andrea Sosso +- Andreas Schneider +- Andreas Schneider +- Andreas Stallinger +- Andreas Wunderlich +- Andy Scherzinger +- Antonio Rojas +- Aputsiaĸ Niels Janussen +- Arthur Schiwon +- arthurchiao +- asapelkin +- asemmar +- Axel Lender +- Balázs Meskó +- Bartek Przybylski +- bceverly +- Benjamin Legrand +- Björn Bidar +- BMerz +- Brandon +- Brandon Coleman +- Brandon Philips +- Brian Kendall +- Bruno Perel +- Camila +- Camila Ayres +- Camila Ayres +- Camila Ayres +- Camila San +- Carl Csaposs +- Carl Schwan +- Carla Schroder +- Carla Schroder +- Carlos Damken +- castillo92 <37965565+castillo92@users.noreply.github.com> +- cclauss +- Cedric Bellegarde +- Chih-Hsuan Yen +- Chih-Hsuan Yen +- Christian Burger +- Christian Göttsche +- Christian Jann +- Christian Kamm +- Christian Kamm +- Christian Muehlhaeuser +- Christoph Dann +- Christoph Wurst +- Christoph Wurst +- ckamm +- ckamm +- Claas Augner +- Claudio Cambra +- Claudio Cambra +- Claudio Cambra +- Clemens Sonnleitner +- cmeh +- cmuck +- Corentin Noël +- Corentin Noël +- Craig Morrissey +- Dan Griffin +- Daniel Hansson +- Daniel Hansson +- Daniel Hansson +- Daniel Kesselberg +- Daniel Molkentin +- Daniel Molkentin +- Daniel Molkentin +- Daniel Nicoletti +- Daniel Vedder +- dark-eye +- David Kahles +- David Prévot +- Denis Dzyubenko +- dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +- dheule +- Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> +- Dmitry Mayorov +- Dmytro Korchynskyi +- Dominik Schmidt +- Dominik Schmidt +- Dominik Schmidt +- Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com> +- dragotin +- dragotin +- Dries Mys +- Duncan Mac-Vicar P +- Elan Ruusamäe +- Elsie Hupp <9206310+elsiehupp@users.noreply.github.com> +- Elsie Hupp +- Eran +- Eric Seigne +- Erik Verbruggen +- Erik Verbruggen +- Fabian Creutz +- fastfwd +- Felix Böhm +- Felix Eckhofer +- Felix Stupp +- Felix Tiede +- Felix Weilbach +- Felix Weilbach +- Florian Jacob +- Florian Reinhard +- Florian Schmaus +- Frederik Juul Christiani +- Georg Ehrke +- George Vlahavas +- Gerhard Gappmeier +- Gilbert Röhrbein +- Giovanni Capuano +- Git'Fellow +- Grigorii Horos +- gt-h6k +- Guido Falsi +- Guido Falsi +- Guillermo López Leal +- Hannah Rittich +- Hannah von Reth +- Hannah von Reth +- Harald Eilertsen +- hefee +- Hefee +- Heinz Wiesinger +- Helmut K. C. Tessarek +- hh.lohmann +- Hiroki Goto <46646213+gt-h6k@users.noreply.github.com> +- HouraisanNEET +- Hugo Gonzalez Labrador +- Individual IT Services +- István Váradi +- István Váradi +- István Váradi +- Ivan Sein +- Ivan Čukić +- Ivan Čukić +- Ivoline Ngong +- ivyclare +- Izabela Bakollari +- J-P Nurmi +- Jacob Neplokh +- Jakob Nixdorf +- Jakub Moscicki +- James Botting +- James Horsley +- Jan Schmidt +- Jan-Christoph Borchardt +- JanDragon <40271530+JanDragon@users.noreply.github.com> +- Jani Uusitalo +- Javier Llorente +- Jenkins for ownCloud +- Jenkins for ownCloud +- Jeremy Plsek +- Jeroen Hoek +- Jim McDonough +- Joachim Schiele +- Joas Schilling <213943+nickvergessen@users.noreply.github.com> +- Joas Schilling +- Joas Schilling +- Jocelyn Turcotte +- Jocelyn Turcotte +- Jocelyn Turcotte +- Joda Stößer +- Johannes Lorenz +- John Molakvoæ +- John Molakvoæ +- Jonathan Kawohl +- Jos Poortvliet +- Josh +- Josh Richards +- Joshua Sterner +- Joss Brown +- Juan Carlos Cornejo +- Juan Carlos Cornejo +- Julius Härtl +- Jyrki Gadinger +- Jérôme Herbinet <33763786+Jerome-Herbinet@users.noreply.github.com> +- Jürgen Weigert +- Jürgen Weigert +- Kashyap Prajapati +- Kaustubh Welankar +- kesselb +- Kevin Ottens +- Kevin Ottens +- Kevin Ottens +- Kevin Ottens +- kevin147147 +- Kilian Pfeiffer +- Kilian Pfeiffer +- kilian.pfeiffer +- Kiril Vladimiroff +- Kirill Bychkov +- Klaas Freitag +- Klaas Freitag +- Klaas Freitag +- Klaas Freitag +- Klaas Freitag +- Klaas Freitag +- Krzesimir Nowak +- Kuba Serafinowski +- Kyle Fazzari +- Kyle Fazzari +- Kyle Fazzari +- Lilian Besson +- Lorenzo Tanganelli +- Luca Lorenzetto +- Luca Lorenzetto +- Luca Niccoli +- Lukas Reschke +- Lukas Reschke +- LukeOwncloud +- Mackie Messer +- Manuel Padron Martinez +- Manuel Stahl +- Marcin Wilk +- Marco Hald +- marcohald +- Marcus Hoffmann +- Mario Enrico Ragucci +- Marius Blüm +- Mariusz Wasak +- Markus Doits +- Markus Goetz +- Martin +- Martin +- Martin Sucha +- Marvin Schmidt +- Masoud Kazemi +- Mathias Eggert +- Mathieu Arnold +- Matt Tuchfarber +- Matthew Leeds +- Matthew Setter +- Matthew Setter +- Matthieu Gallien +- Matthieu Gallien +- Max Rees +- mayonezo +- Michael Georg Hansen +- Michael Kent +- Michael Nutt +- Michael Schuster <48932272+misch7@users.noreply.github.com> +- Michael Schuster +- Michael Stingl <214010+michaelstingl@users.noreply.github.com> +- Michael Stingl +- Michael Stingl +- Micke Nordin +- Micke Nordin +- mjkent +- Morris Jobke +- morriswinkler +- Mr. Jenkins +- Nathan Pratta Teodosio +- NeroBurner +- nextch <97217716+nextch@users.noreply.github.com> +- Nextcloud bot +- Nicolas Fella <6377822+nicolasfella@users.noreply.github.com> +- Nicolas Fella +- Niels van Adrichem +- Nourredine +- octotree +- Oleg Solovyov +- Olivier Goffart +- Olivier Goffart +- onnozweers +- orion1024 +- Oskar Kruschitz +- Oskar Kruschitz +- pascalBokBok +- Patrick Cernko +- Phil Davis +- Philip Allgaier +- Philipp Heckel +- Pierre Ozoux +- Piotr M +- Piotr Mrowczynski +- Piotr Mrówczyński +- pokoli +- r2evans +- rakekniven <2069590+rakekniven@users.noreply.github.com> +- rakekniven +- raldone01 +- RealRancor +- RealRancor +- Reinhold Gschweicher +- Rello +- renyhp +- Rick van der Zwet +- ritsute +- Robert Oostenveld +- Robin Geuze +- rockihack +- Roeland Douma +- Roeland Jago Douma +- Roeland Jago Douma +- Roeland Jago Douma +- Roeland Jago Douma +- Roeland Jago Douma +- Romain Mekarni +- rominf +- Ronny +- Ronny Kunze +- Ryo ONODERA +- Samir Benmendil +- samu-workopen <18331541+samu-workopen@users.noreply.github.com> +- samu-workopen +- Samuel +- Samuel Alfageme +- Sandro Knauß +- Sandro Knauß +- Sandro Knauß +- Sascha Vincent Kurowski +- Sascha Wiswedel +- Sebastian Grund +- Sebastian Kügler +- Sebastian Meßmer +- Sergey Zolotarev +- shile <13051960278@163.com> +- shobha +- Simon L +- skjnldsv +- Stefan Agner +- Stefan Profanter +- Stefan Suhren +- Stephan Beyer +- Stephen Colebrook +- Stephen Colebrook +- storca +- storca +- Stéphane Guillou +- suiso67 +- Sven Strickroth +- szaimen +- Terence Eden +- Thatoo +- Thomas Mueller +- Thomas Müller +- Thomas Müller +- Thomas Witt +- Tim Klocke +- Tim Vandecasteele +- tnixeu <4436784+tnixeu@users.noreply.github.com> +- Tobia De Koninck +- Tobias Haeussler +- Tobias Kaminsky +- tobiasKaminsky +- Tom Swartz +- Tom Swartz +- Tomaz Canabrava +- tomdereub +- Tommy Sparber +- Tommy Sparber +- tuxmaster5000 <837503+tuxmaster5000@users.noreply.github.com> +- unknown +- V.C +- Valdnet <47037905+Valdnet@users.noreply.github.com> +- Vidar Tysse +- Ville Skyttä +- Vincent Petry +- Volkan Gezer +- Vyronas Tsingaras +- whitequark +- xavi-b +- xjzsq +- XNG +- Yaron Shahrabani +- Yoann Laissus +- yopito +- Zhang Sheng +- znerol +- Óscar Nájera +- İsmail Dönmez diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..e155cefbb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,656 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [3.8.2] - 2023-05-16 + +### Added +* Implement missing share settings by @allexzander in https://github.com/nextcloud/desktop/pull/5622 + +### Changed +* Edit locally: elide loading dialog filename label in the middle by @allexzander in https://github.com/nextcloud/desktop/pull/5612 +* Properly handle all fatal errors during edit locally setup procedure by by @claucambra in https://github.com/nextcloud/desktop/pull/5583 +* Parse sharees 'lookup' key to include federated sharees by @allexzander in https://github.com/nextcloud/desktop/pull/5613 +* No longer override the pixman default version by @mgallien in https://github.com/nextcloud/desktop/pull/5630 +* Remove some SQL debug logs to unclutter the output by @allexzander in https://github.com/nextcloud/desktop/pull/5634 +* Attempt sign in when an account state is added in AccountManager by @claucambra in https://github.com/nextcloud/desktop/pull/5493 + +### Fixed +* Fix crash on entering new log file after file size of 512kb reached by @claucambra in https://github.com/nextcloud/desktop/pull/5603 +* Fix MacOS UTF-8 normalization issue by @xavi-b in https://github.com/nextcloud/desktop/pull/4957 +* Edit locally: fix crash on _chekTokenJob pointer deref by @allexzander in https://github.com/nextcloud/desktop/pull/5637 +* E2EE: Fix freeze on metadata checksum validation by @allexzander in https://github.com/nextcloud/desktop/pull/5655 +* Fix folder progress bar positioning in account settings on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/5645 +* Use addLayout to insert the VFS option when setting account by @camilasan in https://github.com/nextcloud/desktop/pull/5665 +* Fix update request channel being set to wrong localised string by @claucambra in https://github.com/nextcloud/desktop/pull/5462 +* Fix setting [undefined] to QFont in 'Sync now' button by @claucambra in https://github.com/nextcloud/desktop/pull/5628 +* Fix account migration from legacy desktop clients (again) by @claucambra in https://github.com/nextcloud/desktop/pull/5640 +* Fix unrecoverable freezing when PutMultiFileJob is used with upload rate limits enabled by @claucambra in https://github.com/nextcloud/desktop/pull/5680 + +## [3.8.1] - 2023-04-19 + +### Changed +* Do not display error status and messages when aborting a sync during hydration request in VFS mode by @allexzander in https://github.com/nextcloud/desktop/pull/5579 +* In case server has no private key, let e2ee init fail by @mgallien in https://github.com/nextcloud/desktop/pull/5566 +* Edit locally: restart current folder sync immediately after file opened by @allexzander in https://github.com/nextcloud/desktop/pull/5588 + +### Fixed +* Sort encrypted files by their id to compute checksum by @mgallien in https://github.com/nextcloud/desktop/pull/5568 +* Try different permutation to recover the broken checksum by @mgallien in https://github.com/nextcloud/desktop/pull/5572 +* Fix secure file drop unit tests by @allexzander in https://github.com/nextcloud/desktop/pull/5574 +* Always add the item at the end of the layout by @camilasan in https://github.com/nextcloud/desktop/pull/5595 +* Properly preserve the format of E2EE metadata during DB operations by @mgallien in https://github.com/nextcloud/desktop/pull/5577 + +## [3.8.0] - 2023-03-31 + +### Added +* Secure file drop by @allexzander in https://github.com/nextcloud/desktop/pull/5327 +* Multiple bug fixes in E2EE by @mgallien in https://github.com/nextcloud/desktop/pull/5560 +* Add Ubuntu Lunar by @ivaradi in https://github.com/nextcloud/desktop/pull/5520 + +### Changed +* Log to stdout when built in Debug config by @claucambra in https://github.com/nextcloud/desktop/pull/5410 + +### Fixed +* E2EE cut extra zeroes from derypted byte array by @allexzander in https://github.com/nextcloud/desktop/pull/5534 +* Prevent ShareModel crash from accessing bad pointers by @claucambra in https://github.com/nextcloud/desktop/pull/5391 +* Show server name in tray main window by @Alkl58 in https://github.com/nextcloud/desktop/pull/5513 +* Enter next log file if the current log file is larger than 512 KB by @claucambra in https://github.com/nextcloud/desktop/pull/5580 +* Debian build classification 'beta' cannot override 'release' by @ivaradi in https://github.com/nextcloud/desktop/pull/5521 +* Follow shouldNotify flag to hide notifications when needed by @mgallien in https://github.com/nextcloud/desktop/pull/5530 +* Only accept folder setup page if --overridelocaldir option is set by @camilasan in https://github.com/nextcloud/desktop/pull/5385 +* Exit after creating config file when using --overrideserverurl option by @mgallien in https://github.com/nextcloud/desktop/pull/5532 +* Respect --overridelocaldir option by @mgallien in https://github.com/nextcloud/desktop/pull/5546 +* L10n: Correct word by @Valdnet in https://github.com/nextcloud/desktop/pull/5378 +* L10n: Added dot to end of sentence by @rakekniven in https://github.com/nextcloud/desktop/pull/5427 +* L10n: Fixed grammar by @rakekniven in https://github.com/nextcloud/desktop/pull/5430 + +## [3.7.4] - 2023-03-09 + +### Changed +* Clean up account creation and deletion code by @claucambra in https://github.com/nextcloud/desktop/pull/5416 +* CI/clang tidy checks init variables by @mgallien in https://github.com/nextcloud/desktop/pull/5436 + +### Fixed +* Check German translation for wrong wording by @tobiasKaminsky in https://github.com/nextcloud/desktop/pull/5351 +* Fix "Create new folder" menu entries in settings not working correctly on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/5435 +* Fix share dialog infinite loading by @claucambra in https://github.com/nextcloud/desktop/pull/5442 +* Fix edit locally job not finding the user account: wrong user id by @mgallien in https://github.com/nextcloud/desktop/pull/5444 +* Skip e2e encrypted files with empty filename in metadata by @mgallien in https://github.com/nextcloud/desktop/pull/5448 +* Always discover blacklisted folders to avoid data loss when modifying selectivesync list by @allexzander in https://github.com/nextcloud/desktop/pull/5459 +* Use new connect syntax by @mgallien in https://github.com/nextcloud/desktop/pull/5451 +* Add missing flag when dehydrating files with CFAPI by @mgallien in https://github.com/nextcloud/desktop/pull/5474 +* Fix avatars not showing up in settings dialog account actions until clicked on by @claucambra in https://github.com/nextcloud/desktop/pull/5453 +* Fix text labels in Sync Status component by @claucambra in https://github.com/nextcloud/desktop/pull/5478 +* Fix infinite loading in the share dialog when public link shares are disabled on the server by @claucambra in https://github.com/nextcloud/desktop/pull/5472 +* Display 'Search globally' as the last sharees list element by @allexzander in https://github.com/nextcloud/desktop/pull/5485 +* Resize WebView widget once the loginpage rendered by @xllndr in https://github.com/nextcloud/desktop/pull/5161 +* Fix: do not restore virtual files by @mgallien in https://github.com/nextcloud/desktop/pull/5498 +* Fix display of 2FA notification @camilasan in https://github.com/nextcloud/desktop/pull/5486 + +## [3.7.1] - 2023-02-07 + +### Fixed +* Init value for pointers by @mgallien in https://github.com/nextcloud/desktop/pull/5393 + +## [3.7.0] - 2023-02-02 + +### Added +* Feature: syncjournaldb handle errors by @allexzander in https://github.com/nextcloud/desktop/pull/4819 +* Add a placeholder item for empty activity list by @claucambra in https://github.com/nextcloud/desktop/pull/4959 +* Configure a list of checks for clang-tidy by @mgallien in https://github.com/nextcloud/desktop/pull/5004 +* Feature: VFS windows sharing and lock state by @allexzander in https://github.com/nextcloud/desktop/pull/4942 +* Add a 'Sync now' button to the sync status header in the tray window by @claucambra in https://github.com/nextcloud/desktop/pull/5018 +* Use new public API to open an edit locally URL by @mgallien in https://github.com/nextcloud/desktop/pull/5116 +* Add a new file details window, unify file activity and sharing by @claucambra in https://github.com/nextcloud/desktop/pull/4929 +* Add support cmake unity build by @tnixeu in https://github.com/nextcloud/desktop/pull/5109 +* Implement context menu entry "Leave this share" by @allexzander in https://github.com/nextcloud/desktop/pull/5081 +* Add end-to-end tests to our CI by @claucambra in https://github.com/nextcloud/desktop/pull/5124 +* Edit file locally restart sync by @allexzander in https://github.com/nextcloud/desktop/pull/5175 +* Add interactive NC Talk notifications on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/5143 +* Add an "Encrypt" menu entry in file browser context menu for folders by @claucambra in https://github.com/nextcloud/desktop/pull/5263 +* Add a nix flake for easy building and dev environments by @claucambra in https://github.com/nextcloud/desktop/pull/5007 +* Add an internal link share to the share dialog by @claucambra in https://github.com/nextcloud/desktop/pull/5131 +* Sets a fixed version for pixman when buildign desktop client via Craft by @mgallien in https://github.com/nextcloud/desktop/pull/5269 +* Remove obsolete names by @mgallien in https://github.com/nextcloud/desktop/pull/5271 +* Do not sync enc folders if e2ee is not setup by @allexzander in https://github.com/nextcloud/desktop/pull/5258 +* Move shellextensions to root installdir by @allexzander in https://github.com/nextcloud/desktop/pull/5295 +* Allow setting up an account with apppasword and folder via command-line arguments. For deployment. by @allexzander in https://github.com/nextcloud/desktop/pull/5296 +* Allow forceoverrideurl via command line by @allexzander in https://github.com/nextcloud/desktop/pull/5329 +* Add ability to disable E2EE by @claucambra in https://github.com/nextcloud/desktop/pull/5167 +* Sync with case clash names by @mgallien in https://github.com/nextcloud/desktop/pull/5232 + +### Changed +* Set UnifiedSearchResultNothingFound visibility less messily by @claucambra in https://github.com/nextcloud/desktop/pull/4751 +* Clean up QML type and singleton registration by @claucambra in https://github.com/nextcloud/desktop/pull/4817 +* Simplify activity list delegates by making them ItemDelegates, clean up by @claucambra in https://github.com/nextcloud/desktop/pull/4786 +* Improve activity list highlighting/keyboard item selection by @claucambra in https://github.com/nextcloud/desktop/pull/4781 +* Replace private API QZipWriter with KArchive by @claucambra in https://github.com/nextcloud/desktop/pull/4768 +* Makes Qt WebEngine optional only on macOS by @mgallien in https://github.com/nextcloud/desktop/pull/4875 +* Updated link to documentation by @BMerz in https://github.com/nextcloud/desktop/pull/4792 +* Accept valid lsColJob reply XML content types by @claucambra in https://github.com/nextcloud/desktop/pull/4919 +* Refactor ActivityListModel population mechanisms by @claucambra in https://github.com/nextcloud/desktop/pull/4736 +* Make account setup wizard's adjustWizardSize resize to current page size instead of largest wizard page by @claucambra in https://github.com/nextcloud/desktop/pull/4911 +* Deallocate call notification dialog objects when closed by @claucambra in https://github.com/nextcloud/desktop/pull/4939 +* Do not format text in QML components as HTML by @claucambra in https://github.com/nextcloud/desktop/pull/4944 +* Ensure strings in main window QML are presented as plain text and not HTML by @claucambra in https://github.com/nextcloud/desktop/pull/4972 +* Improve handling of file name clashes by @claucambra in https://github.com/nextcloud/desktop/pull/4970 +* Add a QSortFilterProxyModel-based SortedActivityListModel by @claucambra in https://github.com/nextcloud/desktop/pull/4933 +* Bring back .lnk files on Windows and always treat them as non-virtual files. by @allexzander in https://github.com/nextcloud/desktop/pull/4968 +* Ensure placeholder message in emoji picker wraps correctly by @claucambra in https://github.com/nextcloud/desktop/pull/4960 +* Make activity action button an actual button, clean up contents by @claucambra in https://github.com/nextcloud/desktop/pull/4784 +* Improve the error box QML component by @claucambra in https://github.com/nextcloud/desktop/pull/4976 +* Don't set up tray context menu on macOS, even if not building app bundle by @claucambra in https://github.com/nextcloud/desktop/pull/4988 +* CI: check clang tidy in ci by @mgallien in https://github.com/nextcloud/desktop/pull/4995 +* Check our code with clang-tidy by @mgallien in https://github.com/nextcloud/desktop/pull/4999 +* Always use constexpr for all text constants by @mgallien in https://github.com/nextcloud/desktop/pull/4996 +* Switch AppImage CI to latest tag: client-appimage-6 by @mgallien in https://github.com/nextcloud/desktop/pull/5003 +* Apply modernize-use-using via clang-tidy by @mgallien in https://github.com/nextcloud/desktop/pull/4993 +* Use [[nodiscard]] by @mgallien in https://github.com/nextcloud/desktop/pull/4992 +* Update client image by @camilasan in https://github.com/nextcloud/desktop/pull/5002 +* Check the format via some github action by @mgallien in https://github.com/nextcloud/desktop/pull/4991 +* Update after tx migrate by @tobiasKaminsky in https://github.com/nextcloud/desktop/pull/5019 +* Improve 'Handle local file editing' feature. Add loading popup. Add force sync before opening a file. by @allexzander in https://github.com/nextcloud/desktop/pull/4990 +* Do not ignore return value by @mgallien in https://github.com/nextcloud/desktop/pull/4998 +* Improve logs when adding sync errors in activity list of main dialog by @mgallien in https://github.com/nextcloud/desktop/pull/5032 +* Improve "pretty user name"-related strings, display in webflow credentials by @claucambra in https://github.com/nextcloud/desktop/pull/5013 +* Update CMake usage in README build instructions by @NeroBurner in https://github.com/nextcloud/desktop/pull/5086 +* Clean up methods in sync engine by @claucambra in https://github.com/nextcloud/desktop/pull/5071 +* Make Systray's void methods slots by @claucambra in https://github.com/nextcloud/desktop/pull/5042 +* Remove unneeded parameter from CleanupPollsJob constructor by @claucambra in https://github.com/nextcloud/desktop/pull/5070 +* Modernise and improve code in AccountManager by @claucambra in https://github.com/nextcloud/desktop/pull/5026 +* Validate and sanitise edit locally token and relpath before sending to server by @claucambra in https://github.com/nextcloud/desktop/pull/5093 +* Refactor FolderMan's "Edit Locally" capabilities as separate class by @claucambra in https://github.com/nextcloud/desktop/pull/5107 +* Modernise and improve code in AccountSettings by @claucambra in https://github.com/nextcloud/desktop/pull/5027 +* Remove unused internal link widget from old share dialog by @claucambra in https://github.com/nextcloud/desktop/pull/5123 +* Use separate variable for cfg file name in CMAKE. by @allexzander in https://github.com/nextcloud/desktop/pull/5136 +* Remove unused app pointer in CocoaInitializer by @claucambra in https://github.com/nextcloud/desktop/pull/5127 +* Do not use copy-assignment of QDialog. by @allexzander in https://github.com/nextcloud/desktop/pull/5148 +* Remove unused remotePath in User::processCompletedSyncItem by @claucambra in https://github.com/nextcloud/desktop/pull/5118 +* Properly escape a path when creating a test file during tests by @mgallien in https://github.com/nextcloud/desktop/pull/5151 +* Fully qualify types in signals and slots by @mgallien in https://github.com/nextcloud/desktop/pull/5088 +* Switch back to upstream craft by @mgallien in https://github.com/nextcloud/desktop/pull/5178 +* Modernize the Dolphin action plugin by @ivaradi in https://github.com/nextcloud/desktop/pull/5192 +* CI: do not modify configuration file during tests by @mgallien in https://github.com/nextcloud/desktop/pull/5200 +* cmake: Use FindPkgConfig's pkg_get_variable instead of custom macro by @marv in https://github.com/nextcloud/desktop/pull/5199 +* Clearly tell user that E2EE has been enabled for an account by @claucambra in https://github.com/nextcloud/desktop/pull/5164 +* Remove close/dismiss button from encryption message by @claucambra in https://github.com/nextcloud/desktop/pull/5163 +* Update macOS shell integration deployment targets by @claucambra in https://github.com/nextcloud/desktop/pull/5227 +* Differentiate between E2EE not being enabled at all vs. E2EE being enabled already through another device in account settings message by @claucambra in https://github.com/nextcloud/desktop/pull/5179 +* Ensure more QML text components are rendering things as plain text by @claucambra in https://github.com/nextcloud/desktop/pull/5231 +* Make use of plain text-enforcing qml labels by @claucambra in https://github.com/nextcloud/desktop/pull/5233 +* Format some QLabels as plain text by @claucambra in https://github.com/nextcloud/desktop/pull/5247 +* Do not create GUI from a random thread and show error on real error by @mgallien in https://github.com/nextcloud/desktop/pull/5253 +* Only show mnemonic request dialog when user explicitly wants to enable E2EE by @claucambra in https://github.com/nextcloud/desktop/pull/5181 +* Replace share settings popup with a page on a StackView by @claucambra in https://github.com/nextcloud/desktop/pull/5194 +* Show file details within the tray dialog, rather than in a separate dialog by @claucambra in https://github.com/nextcloud/desktop/pull/5139 +* Silence sync termination errors when running EditLocallyJob. by @allexzander in https://github.com/nextcloud/desktop/pull/5261 +* Remove unused HeaderBanner component by @claucambra in https://github.com/nextcloud/desktop/pull/5245 +* Use QFileInfo::exists where we are only creating a QFileInfo to check if file exists by @claucambra in https://github.com/nextcloud/desktop/pull/5291 +* Make correct use of Qt signal 'emit' keyword by @claucambra in https://github.com/nextcloud/desktop/pull/5287 +* Remove unused variables by @claucambra in https://github.com/nextcloud/desktop/pull/5290 +* Declare all QRegularExpressions statically by @claucambra in https://github.com/nextcloud/desktop/pull/5289 +* Improve backup dark mode palette for Windows by @claucambra in https://github.com/nextcloud/desktop/pull/5298 +* Replace now deprecated FSEventStreamScheduleWithRunLoop with FSEventStreamSetDispatchQueue by @claucambra in https://github.com/nextcloud/desktop/pull/5272 +* Drop dependency on Qt Quick Controls 1 by @Flowdalic in https://github.com/nextcloud/desktop/pull/5309 +* Update legal notice to 2023 by @claucambra in https://github.com/nextcloud/desktop/pull/5361 +* Don't try to lock folders when editing locally by @claucambra in https://github.com/nextcloud/desktop/pull/5317 +* Remove unused monochrome icons setting by @claucambra in https://github.com/nextcloud/desktop/pull/5366 +* Always unlock E2EE folders, even when network failure or crash. by @allexzander in https://github.com/nextcloud/desktop/pull/5370 +* Improve config upgrade warning dialog by @camilasan in https://github.com/nextcloud/desktop/pull/5384 + +### Fixed +* Fix wrong estimated time when doing sync. by @allexzander in https://github.com/nextcloud/desktop/pull/4902 +* Fix: selective sync abort error by @allexzander in https://github.com/nextcloud/desktop/pull/4903 +* Fix: onflict resolution when selecting folder by @allexzander in https://github.com/nextcloud/desktop/pull/4914 +* Fix fileactivitylistmodel QML registration by @claucambra in https://github.com/nextcloud/desktop/pull/4920 +* Fix menu bar height calculation on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4917 +* Fix ActivityItem activityHover error by @claucambra in https://github.com/nextcloud/desktop/pull/4921 +* Fix add account window text clipping, enlarge text by @claucambra in https://github.com/nextcloud/desktop/pull/4910 +* Fix low-resolution file changed overlay icons in activities by @claucambra in https://github.com/nextcloud/desktop/pull/4930 +* Ensure that the file being processed has had its etag properly sanitised, log etag more by @claucambra in https://github.com/nextcloud/desktop/pull/4940 +* Fix two factor authentication notification by @camilasan in https://github.com/nextcloud/desktop/pull/4967 +* Fix 'Reply' primary property. by @camilasan in https://github.com/nextcloud/desktop/pull/4985 +* Fix sync progress bar colours in dark mode by @claucambra in https://github.com/nextcloud/desktop/pull/4986 +* Fix predefined status text formatting by @claucambra in https://github.com/nextcloud/desktop/pull/4987 +* Avoid possibly crashing static_cast by @mgallien in https://github.com/nextcloud/desktop/pull/4994 +* Fix link shares default expire date being enforced as maximum expire date even when maximum date enforcement is disabled on the server by @claucambra in https://github.com/nextcloud/desktop/pull/4982 +* Fix files not unlocking after lock time expired by @claucambra in https://github.com/nextcloud/desktop/pull/4962 +* Command-line client. Do not trust SSL certificates by default, unless '--trust' option is set. by @allexzander in https://github.com/nextcloud/desktop/pull/5022 +* Fix files lock fail metadata by @mgallien in https://github.com/nextcloud/desktop/pull/5024 +* Fix invisible user status selector button not being checked when user is in Offline mode by @claucambra in https://github.com/nextcloud/desktop/pull/5012 +* Use correct version copmparison on NSIS updater: fix update from rc by @mgallien in https://github.com/nextcloud/desktop/pull/4979 +* Check token for edit locally requests by @mgallien in https://github.com/nextcloud/desktop/pull/5039 +* Fix the dismiss button: display it whenever possible. by @camilasan in https://github.com/nextcloud/desktop/pull/4989 +* Fix account not found when doing local file editing. by @allexzander in https://github.com/nextcloud/desktop/pull/5040 +* Fix call notification dialog buttons by @claucambra in https://github.com/nextcloud/desktop/pull/5074 +* Validate certificate for E2EE against private key by @mgallien in https://github.com/nextcloud/desktop/pull/4949 +* Emit missing signal to update folder sync status icon by @mgallien in https://github.com/nextcloud/desktop/pull/5087 +* Fix macOS autoupdater settings by @claucambra in https://github.com/nextcloud/desktop/pull/5102 +* Fix compatibility with newer python3-nautilus by @nteodosio in https://github.com/nextcloud/desktop/pull/5105 +* Only show Sync Now button if account is connected by @claucambra in https://github.com/nextcloud/desktop/pull/5097 +* E2EE. Do not generate keypair without user request. by @allexzander in https://github.com/nextcloud/desktop/pull/5067 +* Fix incorrect current user index when adding or removing a user account. Also fix incorrect user avatar lookup by id. by @allexzander in https://github.com/nextcloud/desktop/pull/5092 +* Fix: delete folders during propagation even when propagation has errors by @mgallien in https://github.com/nextcloud/desktop/pull/5104 +* Ensure 'Sync now' button doesn't have its text elided by @claucambra in https://github.com/nextcloud/desktop/pull/5129 +* Fix share delegate button icon colors in dark mode by @claucambra in https://github.com/nextcloud/desktop/pull/5132 +* Make user status selector modal, show user header by @claucambra in https://github.com/nextcloud/desktop/pull/5145 +* Fix typo of connector by @hefee in https://github.com/nextcloud/desktop/pull/5157 +* Remove reference to inexistent property in NCCustomButton by @claucambra in https://github.com/nextcloud/desktop/pull/5173 +* Fix ActivityList delegate warnings by @claucambra in https://github.com/nextcloud/desktop/pull/5172 +* Ensure forcing a folder to be synced unpauses syncing on said folder by @claucambra in https://github.com/nextcloud/desktop/pull/5152 +* Fix renaming of folders with a deep hierarchy inside them by @mgallien in https://github.com/nextcloud/desktop/pull/5182 +* Fix instances of: c++11 range-loop might detach Qt container warnings by @mgallien in https://github.com/nextcloud/desktop/pull/5089 +* Fix tray window margins, stop cutting into window border by @claucambra in https://github.com/nextcloud/desktop/pull/5202 +* Fix bad custom button alignments, sizings, etc. by @claucambra in https://github.com/nextcloud/desktop/pull/5189 +* CI: do not override configuration file by @mgallien in https://github.com/nextcloud/desktop/pull/5206 +* Fix CfApiShellExtensionsIPCTest by @allexzander in https://github.com/nextcloud/desktop/pull/5209 +* l10n: Fixed grammar by @rakekniven in https://github.com/nextcloud/desktop/pull/5220 +* Prevent bad encrypting of folder if E2EE has not been correctly set up by @claucambra in https://github.com/nextcloud/desktop/pull/5223 +* Case clash conflicts should not terminate sync by @mgallien in https://github.com/nextcloud/desktop/pull/5224 +* l10n: Correct spelling by @Valdnet in https://github.com/nextcloud/desktop/pull/5221 +* Fix CI errors for Edit Locally. by @allexzander in https://github.com/nextcloud/desktop/pull/5241 +* Lock file when editing locally by @claucambra in https://github.com/nextcloud/desktop/pull/5226 +* Fix BasicComboBox internal layout by @claucambra in https://github.com/nextcloud/desktop/pull/5216 +* Explicitly size and align user status selector text input to avoid bugs with alternate QtQuick styles by @claucambra in https://github.com/nextcloud/desktop/pull/5214 +* So not use bulk upload for e2ee files by @mgallien in https://github.com/nextcloud/desktop/pull/5256 +* Avoid the Get-Task-Allow Entitlement (macOS Notarization) by @claucambra in https://github.com/nextcloud/desktop/pull/5274 +* Fix migration from old settings configuration files by @mgallien in https://github.com/nextcloud/desktop/pull/5141 +* l10n: Remove space by @Valdnet in https://github.com/nextcloud/desktop/pull/5297 +* Update file's metadata in the local database when the etag changes while file remains unchanged. Fix subsequent conflict when locking and unlocking. by @allexzander in https://github.com/nextcloud/desktop/pull/5293 +* Fix warnings on QPROPERTY-s by @claucambra in https://github.com/nextcloud/desktop/pull/5286 +* Fix full-text search results not being opened in browser by @claucambra in https://github.com/nextcloud/desktop/pull/5279 +* Fix bad string for translation. by @allexzander in https://github.com/nextcloud/desktop/pull/5358 +* Fix migration from legacy client when override server url is set by @claucambra in https://github.com/nextcloud/desktop/pull/5322 +* Fix fetch more unified search result item not being clickable by @claucambra in https://github.com/nextcloud/desktop/pull/5266 +* Edit locally. Do not lock if locking is disabled on the server. by @allexzander in https://github.com/nextcloud/desktop/pull/5371 +* Revert "Merge pull request #5366 from nextcloud/bugfix/remove-mono-icons-setting" by @claucambra in https://github.com/nextcloud/desktop/pull/5372 +* Open calendar notifications in the browser. by @camilasan in https://github.com/nextcloud/desktop/pull/4684 +* Migrate old configs by @camilasan in https://github.com/nextcloud/desktop/pull/5362 +* Fix displaying of file details button for local syncfileitem activities by @claucambra in https://github.com/nextcloud/desktop/pull/5379 + +### Security +* Validate and sanitise edit locally token and relpath before sending to server by @claucambra in https://github.com/nextcloud/desktop/pull/5093 + +## [3.6.6] - 2023-01-19 + +### Fixed +* Revert "Fix(l10n): capital_abcd Update translations from Transifex" by @allexzander in https://github.com/nextcloud/desktop/commit/33f3975529c0c5028c840a4c5ada037d92e12253 + +## [3.6.5] - 2023-01-19 + +### Added +* Allow forceoverrideurl via command line by @allexzander in https://github.com/nextcloud/desktop/pull/5329 + +### Changed +* Drop dependency on Qt Quick Controls 1 by @Flowdalic in https://github.com/nextcloud/desktop/pull/5309 + +### Fixed +* Do not assert when sharing to a circle by @mgallien in https://github.com/nextcloud/desktop/pull/5310 +* Fix macOS shell integration class inits by @claucambra in https://github.com/nextcloud/desktop/pull/5299 +* Fix typo by @cgzones in https://github.com/nextcloud/desktop/pull/5257 +* Check that we update local file mtime on changes from server by @mgallien in https://github.com/nextcloud/desktop/pull/5188 +* Fix regressions on pinState management when doing renames by @mgallien in https://github.com/nextcloud/desktop/pull/5201 +* Fix SyncEngineTest failure when localstate is destroyed by @allexzander in https://github.com/nextcloud/desktop/pull/5273 + +### Security +* Always generate random initialization vector when uploading encrypted file by @allexzander in https://github.com/nextcloud/desktop/pull/5324 +* Fix security vulnerability when receiving empty metadataKeys from the server by @allexzander in https://github.com/nextcloud/desktop/pull/5323 + +## [3.6.4] - 2022-12-08 + +### Fixed +* Do not create GUI from a random thread and show error on real error by @mgallien in https://github.com/nextcloud/desktop/pull/5253 + +## [3.6.3] - 2022-12-08 + +### Added +* Feature: edit file locally restart sync by @allexzander in https://github.com/nextcloud/desktop/pull/5175 +* Add forcefoldersync method to folder manager by @claucambra in https://github.com/nextcloud/desktop/pull/5239 + +### Changed +* Make user status selector modal, show user header by claucambra in https://github.com/nextcloud/desktop/pull/5145 +* Make use of plain text-enforcing qml labels by @claucambra in https://github.com/nextcloud/desktop/pull/5233 +* Format some QLabels as plain text by @claucambra in https://github.com/nextcloud/desktop/pull/5247 + +### Fixed +* Fix typo of connector by @hefee in https://github.com/nextcloud/desktop/pull/5157 +* Fix renaming of folders with a deep hierarchy inside them by @mgallien in https://github.com/nextcloud/desktop/pull/5182 +* Prevent bad encrypting of folder if E2EE has not been correctly set up by @claucambra in https://github.com/nextcloud/desktop/pull/5223 +* Lock file when editing locally by @claucambra in +https://github.com/nextcloud/desktop/pull/5226 + +## [3.6.2] - 2022-11-10 + +### Added +* Validate and sanitise edit locally token and relpath before sending to server by @claucambra in https://github.com/nextcloud/desktop/pull/5093 + +### Changed +* Refactor FolderMan's "Edit Locally" capabilities as separate class by @claucambra in https://github.com/nextcloud/desktop/pull/5107 +* Use new public API to open an edit locally URL by @mgallien in https://github.com/nextcloud/desktop/pull/5116 +* Use separate variable for cfg file name in CMAKE by @allexzander in https://github.com/nextcloud/desktop/pull/5136 +* Do not use copy-assignment of QDialog by @allexzander in https://github.com/nextcloud/desktop/pull/5148 + +### Fixed +* Fix call notification dialog buttons by @claucambra in https://github.com/nextcloud/desktop/pull/5074 +* Emit missing signal to update folder sync status icon by @mgallien in https://github.com/nextcloud/desktop/pull/5087 +* Fix macOS autoupdater settings by @claucambra in https://github.com/nextcloud/desktop/pull/5102 +* Fix compatibility with newer python3-nautilus by @nteodosio in https://github.com/nextcloud/desktop/pull/5105 +* Fix stable-3.6 compile on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/5154 +* Fix bad backport of CustomButton changes in Stable-3.6 by @claucambra in https://github.com/nextcloud/desktop/pull/5155 +* E2EE: Do not generate keypair without user request by @allexzander in https://github.com/nextcloud/desktop/pull/5067 +* Fix incorrect current user index when adding or removing a user account by @allexzander in https://github.com/nextcloud/desktop/pull/5092 +* Properly escape a path when creating a test file during tests by @mgallien in https://github.com/nextcloud/desktop/pull/5151 + +## [3.6.1] - 2022-10-18 + +### Added + +### Changed +* Improve 'Handle local file editing' feature by @mgallien in https://github.com/nextcloud/desktop/pull/5054 +* Update after tx migrate by @tobiasKaminsky in https://github.com/nextcloud/desktop/pull/5019 +* Bring back .lnk files on Windows and always treat them as non-virtual files by @allexzander in https://github.com/nextcloud/desktop/pull/4968 + +### Fixed +* Fix two factor auth notification: activity item was disabled by @camilasan in https://github.com/nextcloud/desktop/pull/5057 +* Fix account not found when doing local file editing by @mgallien in https://github.com/nextcloud/desktop/pull/5056 +* Check token for edit locally requests by @mgallien in https://github.com/nextcloud/desktop/pull/5055 +* Fix command-line client: do not trust SSL certificates by default, unless '--trust' option is set by @allexzander in https://github.com/nextcloud/desktop/pull/5022 +* Fix invisible user status selector button not being checked when user is in Offline mode by @claucambra in https://github.com/nextcloud/desktop/pull/5012 +* Fix the dismiss button: display it whenever possible by @camilasan in https://github.com/nextcloud/desktop/pull/4989 +* Fix predefined status text formatting by @claucambra in https://github.com/nextcloud/desktop/pull/4987 +* Fix sync progress bar colours in dark mode by @claucambra in https://github.com/nextcloud/desktop/pull/4986 +* Fix 'Reply' primary property. by @camilasan in https://github.com/nextcloud/desktop/pull/4985 +* Fix link shares default expire date being enforced as maximum expire date even when maximum date enforcement is disabled on the server by @claucambra in https://github.com/nextcloud/desktop/pull/4982 +* Use correct version copmparison on NSIS updater: fix update from rc by @mgallien in https://github.com/nextcloud/desktop/pull/4979 +* Ensure strings in main window QML are presented as plain text and not HTML by @claucambra in https://github.com/nextcloud/desktop/pull/4972 +* Improve handling of file name clashes by @claucambra in https://github.com/nextcloud/desktop/pull/4970 +* Ensure placeholder message in emoji picker wraps correctly by @claucambra in https://github.com/nextcloud/desktop/pull/4960 +* Do not format text in QML components as HTML by @claucambra in https://github.com/nextcloud/desktop/pull/4944 +* Ensure that the file being processed has had its etag properly sanitised, log etag more by @claucambra in https://github.com/nextcloud/desktop/pull/4940 +* Deallocate call notification dialog objects when closed by @claucambra in https://github.com/nextcloud/desktop/pull/4939 +* Fix low-resolution file changed overlay icons in activities by @claucambra in https://github.com/nextcloud/desktop/pull/4930 +* Accept valid lsColJob reply XML content types by @claucambra in https://github.com/nextcloud/desktop/pull/4919 +* Fix menu bar height calculation on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4917 +* Bugfix/conflict resolution when selecting folder by @allexzander in https://github.com/nextcloud/desktop/pull/4914 +* Fix add account window text clipping, enlarge text by @claucambra in https://github.com/nextcloud/desktop/pull/4910 +* Fix selective sync abort error by @allexzander in https://github.com/nextcloud/desktop/pull/4903 +* Fix wrong estimated time when doing sync by @allexzander in https://github.com/nextcloud/desktop/pull/4902 + +## [3.6.0] - 2022-09-06 + +### Added +* Enable more warnings also for gcc by @mgallien in https://github.com/nextcloud/desktop/pull/4804 +* Make UserStatusSelector a dismissible page pushed onto the tray window by @claucambra in https://github.com/nextcloud/desktop/pull/4760 +* Add Debian Bullseye build by @ivaradi in https://github.com/nextcloud/desktop/pull/4773 +* Handle edit locally from web by @allexzander in https://github.com/nextcloud/desktop/pull/4771 +* Double-clicking tray icon opens currently-selected user's local folder (if available) by @claucambra in https://github.com/nextcloud/desktop/pull/4774 +* Virtual file system Windows thumbnails by @allexzander in https://github.com/nextcloud/desktop/pull/4713 +* Use macOS-specific application icon by @claucambra in https://github.com/nextcloud/desktop/pull/4707 +* Limit concurrent notifications by @claucambra in https://github.com/nextcloud/desktop/pull/4706 +* Add a placeholder message for the recents tab of the emoji picker by @claucambra in https://github.com/nextcloud/desktop/pull/4628 +* Add a custom back button to the account wizard's advanced setup page by @claucambra in https://github.com/nextcloud/desktop/pull/4686 +* Add SVG icon styled for macOS Big Sur by @elsiehupp in https://github.com/nextcloud/desktop/pull/4631 +* Enable Windows CI unit tests and test coverage by @allexzander in https://github.com/nextcloud/desktop/pull/4609 +* Prevent call dialogs from being presented when do not disturb is set as the user status by @claucambra in https://github.com/nextcloud/desktop/pull/4611 +* Generate state icons from svg by @allexzander in https://github.com/nextcloud/desktop/pull/4622 +* Ignore Office temp folders on Mac ('.sb-' in folder name). by @allexzander in https://github.com/nextcloud/desktop/pull/4615 +* Display chat message inside the OS notification. by @allexzander in https://github.com/nextcloud/desktop/pull/4575 +* Bump up minimum macOS version by @claucambra in https://github.com/nextcloud/desktop/pull/4564 +* Add new fixup workflow from nextcloud org by @mgallien in https://github.com/nextcloud/desktop/pull/4560 + +### Changed +* Ensure file activity dialog is centered on screen and appears at top of window stack by @claucambra in https://github.com/nextcloud/desktop/pull/4853 +* Do not build qt keychain already included in the CI images by @mgallien in https://github.com/nextcloud/desktop/pull/4882 +* Reads and store fileId and remote permissions during bulk upload by @mgallien in https://github.com/nextcloud/desktop/pull/4869 +* Refactor user line by @claucambra in https://github.com/nextcloud/desktop/pull/4797 +* Eliminate padding around the menu separator in the account menu by @claucambra in https://github.com/nextcloud/desktop/pull/4802 +* Restyle unified search skeleton items animation and simplify their code by @claucambra in https://github.com/nextcloud/desktop/pull/4718 +* Clean up TalkReplyTextField, remove unnecessary parent Item by @claucambra in https://github.com/nextcloud/desktop/pull/4790 +* Clicking on an activity list item for a file opens the local file if available by @claucambra in https://github.com/nextcloud/desktop/pull/4748 +* Switch to using the main client CI image based on ubuntu 22.04 by @mgallien in https://github.com/nextcloud/desktop/pull/4704 +* Always run MSI with full UI. by @allexzander in https://github.com/nextcloud/desktop/pull/4801 +* Replace unified search text field busy indicator with custom indicator by @claucambra in https://github.com/nextcloud/desktop/pull/4753 +* Make apps menu scrollable when content taller than available vertical space, preventing borking of layout by @claucambra in https://github.com/nextcloud/desktop/pull/4723 +* Remove Ubuntu Impish, add Kinetic by @ivaradi in https://github.com/nextcloud/desktop/pull/4758 +* Stop styling QML unified search items hierarchically, use global Style constants by @claucambra in https://github.com/nextcloud/desktop/pull/4719 +* print sync direction in SyncFileStatusTracker::slotAboutToPropagate by @mgallien in https://github.com/nextcloud/desktop/pull/4679 +* Use preprocessor directive rather than normal 'if' for UNNotification types by @claucambra in https://github.com/nextcloud/desktop/pull/4720 +* QML-ify the UserModel, use properties rather than setter methods by @claucambra in https://github.com/nextcloud/desktop/pull/4710 +* Take ints by value rather than reference in UserModel methods by @claucambra in https://github.com/nextcloud/desktop/pull/4712 +* Refactor tray window opening code for clarity and efficiency by @claucambra in https://github.com/nextcloud/desktop/pull/4688 +* Properly adapt the UserStatusSelectorModel to QML, eliminate hacks, make code more declarative by @claucambra in https://github.com/nextcloud/desktop/pull/4650 +* Clean up systray methods, make more QML-friendly by @claucambra in https://github.com/nextcloud/desktop/pull/4687 +* Add 'db/local/remote' reference to log string. by @camilasan in https://github.com/nextcloud/desktop/pull/4683 +* Work around issues with window positioning on Linux DEs, hardcode tray window to screen center when new account added by @claucambra in https://github.com/nextcloud/desktop/pull/4685 +* Increase the call state checking interval to not overload the server by @claucambra in https://github.com/nextcloud/desktop/pull/4693 +* Use an en-dash for the userstatus panel by @szaimen in https://github.com/nextcloud/desktop/pull/4671 +* Windows CI. Use specific Craft revision. by @allexzander in https://github.com/nextcloud/desktop/pull/4682 +* Reply button size should be same as the input field, smaller + text color by @camilasan in https://github.com/nextcloud/desktop/pull/4577 +* Make user status dialog look in line with the rest of the desktop client tray and Nextcloud by @claucambra in https://github.com/nextcloud/desktop/pull/4624 +* Make client language gender-neutral and more clear by @claucambra in https://github.com/nextcloud/desktop/pull/4667 +* Make the share dialog resizeable by @claucambra in https://github.com/nextcloud/desktop/pull/4663 +* Redesign local folder information in the account-adding wizard by @claucambra in https://github.com/nextcloud/desktop/pull/4638 +* Remove tooltip because it is only repeating the label of the link. by @camilasan in https://github.com/nextcloud/desktop/pull/4657 +* Fix general section by @jospoortvliet in https://github.com/nextcloud/desktop/pull/4439 +* Ensure call notification stays on top of other windows by @claucambra in https://github.com/nextcloud/desktop/pull/4659 +* Rephrase login dialog button text to be in line with clients on other platforms by @claucambra in https://github.com/nextcloud/desktop/pull/4637 +* Add a transparent background to the send reply button. by @camilasan in https://github.com/nextcloud/desktop/pull/4578 +* Reduce spacing above the buttons: spacing should be same as space between lines in the text above by @camilasan in https://github.com/nextcloud/desktop/pull/4572 +* Update autoupdater doc with info about the macOS autoupdater by @claucambra in https://github.com/nextcloud/desktop/pull/4587 +* Add explicit capture for lambda by @mgallien in https://github.com/nextcloud/desktop/pull/4553 +* Change three dots to an ellipsis and add a space by @Valdnet in https://github.com/nextcloud/desktop/pull/4551 +* Simplify and remove the notification "cache" by @claucambra in https://github.com/nextcloud/desktop/pull/4508 +* Use proper online status for user ('dnd', 'online', 'invisible', etc.) to enable or disable desktop notifications. by @allexzander in https://github.com/nextcloud/desktop/pull/4507 +* Do not replace strings in action links coming from the notification api. by @camilasan in https://github.com/nextcloud/desktop/pull/4522 +* Revamp notifications for macOS and add support for actionable update notifications by @claucambra in https://github.com/nextcloud/desktop/pull/4512 +* Make the make_universal.py script more verbose for easier debugging by @claucambra in https://github.com/nextcloud/desktop/pull/4501 +* docs: Replace "preceded" with "followed" by @carlcsaposs in https://github.com/nextcloud/desktop/pull/4249 +* Remove "…" from "Create Debug Archive" button by @spacegaier in https://github.com/nextcloud/desktop/pull/4380 + + +### Fixed +* Prevent the 'Cancel' button of the user status selector getting squashed by @claucambra in https://github.com/nextcloud/desktop/pull/4843 +* Ensure that clear status message combo box is at least implicit width by @claucambra in https://github.com/nextcloud/desktop/pull/4844 +* Fix alignment of predefined status contents regardless of emoji fonts by @claucambra in https://github.com/nextcloud/desktop/pull/4845 +* Prevent crashing when trying to create error-ing QML component in systray.cpp, output error to log by @mgallien in https://github.com/nextcloud/desktop/pull/4850 +* Build script for AppImage should not assume Nextcloud is the name by @mgallien in https://github.com/nextcloud/desktop/pull/4866 +* Fix File Activities dialog not showing up by @allexzander in https://github.com/nextcloud/desktop/pull/4867 +* Fix account switching and hover issues with UserLine component by @claucambra in https://github.com/nextcloud/desktop/pull/4839 +* Fix unified search item placeholder image source by @claucambra in https://github.com/nextcloud/desktop/pull/4831 +* Fix greek translation for application name in menu by @gapan in https://github.com/nextcloud/desktop/pull/4827 +* Remove libglib-2.0.so.0 and libgobject-2.0.so.0 from Appimage. by @camilasan in https://github.com/nextcloud/desktop/pull/4830 +* Fix QML warnings by @claucambra in https://github.com/nextcloud/desktop/pull/4818 +* Fix bugs with setting 'Away' user status by @claucambra in https://github.com/nextcloud/desktop/pull/4822 +* ensure SyncEngine use an initialized instance of SyncOptions by @mgallien in https://github.com/nextcloud/desktop/pull/4816 +* Fix crash: 'Failed to create OpenGL context'. by @allexzander in https://github.com/nextcloud/desktop/pull/4821 +* i18n: Spelling unification by @Valdnet in https://github.com/nextcloud/desktop/pull/4820 +* Ensure that throttled notifications still appear in tray activity model by @claucambra in https://github.com/nextcloud/desktop/pull/4734 +* Do not reboot PC when running an MSI via autoupdate. by @allexzander in https://github.com/nextcloud/desktop/pull/4799 +* Update macOS Info.plist by @claucambra in https://github.com/nextcloud/desktop/pull/4755 +* Ensure debug archive contents are readable by any user by @claucambra in https://github.com/nextcloud/desktop/pull/4756 +* Stop clearing notifications when new notifications are received by @claucambra in https://github.com/nextcloud/desktop/pull/4735 +* Fix ActivityItemContent QML paintedWidth errors by @claucambra in https://github.com/nextcloud/desktop/pull/4738 +* Respect skipAutoUpdateCheck in nextcloud.cfg with Sparkle on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4717 +* Only set _FORTIFY_SOURCE when a higher level of this flag has not been set by @claucambra in https://github.com/nextcloud/desktop/pull/4703 +* Fix bad quote in CMakeLists PNG generation message by @claucambra in https://github.com/nextcloud/desktop/pull/4700 +* Ensure the dispatch source only gets deallocated after the dispatch_source_cancel is done, avoiding crashing of the Finder Sync Extension on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4643 +* Close call notifications when the call has been joined by the user, or the call has ended by @claucambra in https://github.com/nextcloud/desktop/pull/4672 +* Correct spelling by @Valdnet in https://github.com/nextcloud/desktop/pull/4678 +* Fix the system tray menu not being correctly replaced in setupContextMenu on GNOME by @claucambra in https://github.com/nextcloud/desktop/pull/4655 +* Fix crashing when selecting user status and predefined statuses not appearing by @claucambra in https://github.com/nextcloud/desktop/pull/4616 +* Force OpenGL via Angle and using warp direct3d software rasterizer by @mgallien in https://github.com/nextcloud/desktop/pull/4582 +* Fix for the share dialog: mode.absolutePath being undefined prevented the share dialog from being opened by the user. by @camilasan in https://github.com/nextcloud/desktop/pull/4640 +* Add contrast to the text/icon of buttons if the server defined color is light. by @camilasan in https://github.com/nextcloud/desktop/pull/4641 +* Fix segfault when _transferDataSocket is nullptr. by @camilasan in https://github.com/nextcloud/desktop/pull/4656 +* Remove assert from test, it is no longer useful. by @camilasan in https://github.com/nextcloud/desktop/pull/4645 +* Fix building the client on macOS without the application bundle by @claucambra in https://github.com/nextcloud/desktop/pull/4612 +* Fix build on macOS versions pre-11 (down to 10.14) by @claucambra in https://github.com/nextcloud/desktop/pull/4563 +* l10n: Fixed grammar by @rakekniven in https://github.com/nextcloud/desktop/pull/4495 +* Fix 'TypeError: Cannot readproperty 'messageSent' of undefined'. by @camilasan in https://github.com/nextcloud/desktop/pull/4573 +* Fix crash caused by overflow in FinderSyncExtension by @claucambra in https://github.com/nextcloud/desktop/pull/4562 +* Explicitly ask user for notification authorisation on launch (macOS) by @claucambra in https://github.com/nextcloud/desktop/pull/4556 +* Stretch WebView to fit dialog's height. by @allexzander in https://github.com/nextcloud/desktop/pull/4554 +* Add and use DO_NOT_REBOOT_IN_SILENT=1 parameter for MSI to not reboot during the auto-update. by @allexzander in https://github.com/nextcloud/desktop/pull/4566 +* Fix visual borking in the share dialog by @claucambra in https://github.com/nextcloud/desktop/pull/4540 +* Fix two factor authentication notification: 'Mark as read' was being displayed in both action buttons. by @camilasan in https://github.com/nextcloud/desktop/pull/4518 +* If an exclude file is deleted, skip it and remove it from internal list by @mgallien in https://github.com/nextcloud/desktop/pull/4519 +* Fixed share link expiration box being ineditable and always attempting to set invalid date by @claucambra in https://github.com/nextcloud/desktop/pull/4543 +* Fix: allow manual rename files with spaces by @allexzander in https://github.com/nextcloud/desktop/pull/4454 +* Fix activity list item issues with colours/layout/etc. by @claucambra in https://github.com/nextcloud/desktop/pull/4472 +* Fix tray icon not displaying "Open main dialog" by @claucambra in https://github.com/nextcloud/desktop/pull/4484 +* Fix: take root folder's files size into account when displaying the total size in selective sync dialog. by @allexzander in https://github.com/nextcloud/desktop/pull/4532 +* Fix crashing of finder sync extension caused by dispatch_source_cancel of nullptr by @claucambra in https://github.com/nextcloud/desktop/pull/4520 +* Ask for Desktop Client version by @solracsf in https://github.com/nextcloud/desktop/pull/4499 +* Only add OCS-APIREQUEST header for 1st request of webflow v1 by @mgallien in https://github.com/nextcloud/desktop/pull/4510 +* Use full-bleed Start Tile by @elsiehupp in https://github.com/nextcloud/desktop/pull/2982 +* l10n: Remove string from translation by @rakekniven in https://github.com/nextcloud/desktop/pull/4473 +* Add new and correct sparkle update signature by @claucambra in https://github.com/nextcloud/desktop/pull/4478 +* Ensure cache is stored in default cache location by @claucambra in https://github.com/nextcloud/desktop/pull/4485 +* l10n: Changed triple dot to ellipsis by @rakekniven in https://github.com/nextcloud/desktop/pull/4469 +* Move URI scheme variable from Nextcloud.cmake to root CMakeListsts. by @allexzander in https://github.com/nextcloud/desktop/pull/4815 +* Move CFAPI shell extensions variables to root CMakeLists. by @allexzander in https://github.com/nextcloud/desktop/pull/4810] + + +## [3.6.0-rc1] - 2022-08-16 + +### Added +* Enable more warnings also for gcc by @mgallien in https://github.com/nextcloud/desktop/pull/4804 +* Make UserStatusSelector a dismissible page pushed onto the tray window by @claucambra in https://github.com/nextcloud/desktop/pull/4760 +* Add Debian Bullseye build by @ivaradi in https://github.com/nextcloud/desktop/pull/4773 +* Handle edit locally from web by @allexzander in https://github.com/nextcloud/desktop/pull/4771 +* Double-clicking tray icon opens currently-selected user's local folder (if available) by @claucambra in https://github.com/nextcloud/desktop/pull/4774 +* Virtual file system Windows thumbnails by @allexzander in https://github.com/nextcloud/desktop/pull/4713 +* Use macOS-specific application icon by @claucambra in https://github.com/nextcloud/desktop/pull/4707 +* Limit concurrent notifications by @claucambra in https://github.com/nextcloud/desktop/pull/4706 +* Add a placeholder message for the recents tab of the emoji picker by @claucambra in https://github.com/nextcloud/desktop/pull/4628 +* Add a custom back button to the account wizard's advanced setup page by @claucambra in https://github.com/nextcloud/desktop/pull/4686 +* Add SVG icon styled for macOS Big Sur by @elsiehupp in https://github.com/nextcloud/desktop/pull/4631 +* Enable Windows CI unit tests and test coverage by @allexzander in https://github.com/nextcloud/desktop/pull/4609 +* Prevent call dialogs from being presented when do not disturb is set as the user status by @claucambra in https://github.com/nextcloud/desktop/pull/4611 +* Generate state icons from svg by @allexzander in https://github.com/nextcloud/desktop/pull/4622 +* Ignore Office temp folders on Mac ('.sb-' in folder name). by @allexzander in https://github.com/nextcloud/desktop/pull/4615 +* Display chat message inside the OS notification. by @allexzander in https://github.com/nextcloud/desktop/pull/4575 +* Bump up minimum macOS version by @claucambra in https://github.com/nextcloud/desktop/pull/4564 +* Add new fixup workflow from nextcloud org by @mgallien in https://github.com/nextcloud/desktop/pull/4560 + +### Changed +* Refactor user line by @claucambra in https://github.com/nextcloud/desktop/pull/4797 +* Eliminate padding around the menu separator in the account menu by @claucambra in https://github.com/nextcloud/desktop/pull/4802 +* Restyle unified search skeleton items animation and simplify their code by @claucambra in https://github.com/nextcloud/desktop/pull/4718 +* Clean up TalkReplyTextField, remove unnecessary parent Item by @claucambra in https://github.com/nextcloud/desktop/pull/4790 +* Clicking on an activity list item for a file opens the local file if available by @claucambra in https://github.com/nextcloud/desktop/pull/4748 +* Switch to using the main client CI image based on ubuntu 22.04 by @mgallien in https://github.com/nextcloud/desktop/pull/4704 +* Always run MSI with full UI. by @allexzander in https://github.com/nextcloud/desktop/pull/4801 +* Replace unified search text field busy indicator with custom indicator by @claucambra in https://github.com/nextcloud/desktop/pull/4753 +* Make apps menu scrollable when content taller than available vertical space, preventing borking of layout by @claucambra in https://github.com/nextcloud/desktop/pull/4723 +* Remove Ubuntu Impish, add Kinetic by @ivaradi in https://github.com/nextcloud/desktop/pull/4758 +* Stop styling QML unified search items hierarchically, use global Style constants by @claucambra in https://github.com/nextcloud/desktop/pull/4719 +* print sync direction in SyncFileStatusTracker::slotAboutToPropagate by @mgallien in https://github.com/nextcloud/desktop/pull/4679 +* Use preprocessor directive rather than normal 'if' for UNNotification types by @claucambra in https://github.com/nextcloud/desktop/pull/4720 +* QML-ify the UserModel, use properties rather than setter methods by @claucambra in https://github.com/nextcloud/desktop/pull/4710 +* Take ints by value rather than reference in UserModel methods by @claucambra in https://github.com/nextcloud/desktop/pull/4712 +* Refactor tray window opening code for clarity and efficiency by @claucambra in https://github.com/nextcloud/desktop/pull/4688 +* Properly adapt the UserStatusSelectorModel to QML, eliminate hacks, make code more declarative by @claucambra in https://github.com/nextcloud/desktop/pull/4650 +* Clean up systray methods, make more QML-friendly by @claucambra in https://github.com/nextcloud/desktop/pull/4687 +* Add 'db/local/remote' reference to log string. by @camilasan in https://github.com/nextcloud/desktop/pull/4683 +* Work around issues with window positioning on Linux DEs, hardcode tray window to screen center when new account added by @claucambra in https://github.com/nextcloud/desktop/pull/4685 +* Increase the call state checking interval to not overload the server by @claucambra in https://github.com/nextcloud/desktop/pull/4693 +* Use an en-dash for the userstatus panel by @szaimen in https://github.com/nextcloud/desktop/pull/4671 +* Windows CI. Use specific Craft revision. by @allexzander in https://github.com/nextcloud/desktop/pull/4682 +* Reply button size should be same as the input field, smaller + text color by @camilasan in https://github.com/nextcloud/desktop/pull/4577 +* Make user status dialog look in line with the rest of the desktop client tray and Nextcloud by @claucambra in https://github.com/nextcloud/desktop/pull/4624 +* Make client language gender-neutral and more clear by @claucambra in https://github.com/nextcloud/desktop/pull/4667 +* Make the share dialog resizeable by @claucambra in https://github.com/nextcloud/desktop/pull/4663 +* Redesign local folder information in the account-adding wizard by @claucambra in https://github.com/nextcloud/desktop/pull/4638 +* Remove tooltip because it is only repeating the label of the link. by @camilasan in https://github.com/nextcloud/desktop/pull/4657 +* Fix general section by @jospoortvliet in https://github.com/nextcloud/desktop/pull/4439 +* Ensure call notification stays on top of other windows by @claucambra in https://github.com/nextcloud/desktop/pull/4659 +* Rephrase login dialog button text to be in line with clients on other platforms by @claucambra in https://github.com/nextcloud/desktop/pull/4637 +* Add a transparent background to the send reply button. by @camilasan in https://github.com/nextcloud/desktop/pull/4578 +* Reduce spacing above the buttons: spacing should be same as space between lines in the text above by @camilasan in https://github.com/nextcloud/desktop/pull/4572 +* Update autoupdater doc with info about the macOS autoupdater by @claucambra in https://github.com/nextcloud/desktop/pull/4587 +* Add explicit capture for lambda by @mgallien in https://github.com/nextcloud/desktop/pull/4553 +* Change three dots to an ellipsis and add a space by @Valdnet in https://github.com/nextcloud/desktop/pull/4551 +* Simplify and remove the notification "cache" by @claucambra in https://github.com/nextcloud/desktop/pull/4508 +* Use proper online status for user ('dnd', 'online', 'invisible', etc.) to enable or disable desktop notifications. by @allexzander in https://github.com/nextcloud/desktop/pull/4507 +* Do not replace strings in action links coming from the notification api. by @camilasan in https://github.com/nextcloud/desktop/pull/4522 +* Revamp notifications for macOS and add support for actionable update notifications by @claucambra in https://github.com/nextcloud/desktop/pull/4512 +* Make the make_universal.py script more verbose for easier debugging by @claucambra in https://github.com/nextcloud/desktop/pull/4501 +* docs: Replace "preceded" with "followed" by @carlcsaposs in https://github.com/nextcloud/desktop/pull/4249 +* Remove "…" from "Create Debug Archive" button by @spacegaier in https://github.com/nextcloud/desktop/pull/4380 + +### Fixed +* Fix account switching and hover issues with UserLine component by @claucambra in https://github.com/nextcloud/desktop/pull/4839 +* Fix unified search item placeholder image source by @claucambra in https://github.com/nextcloud/desktop/pull/4831 +* Fix greek translation for application name in menu by @gapan in https://github.com/nextcloud/desktop/pull/4827 +* Remove libglib-2.0.so.0 and libgobject-2.0.so.0 from Appimage. by @camilasan in https://github.com/nextcloud/desktop/pull/4830 +* Fix QML warnings by @claucambra in https://github.com/nextcloud/desktop/pull/4818 +* Fix bugs with setting 'Away' user status by @claucambra in https://github.com/nextcloud/desktop/pull/4822 +* ensure SyncEngine use an initialized instance of SyncOptions by @mgallien in https://github.com/nextcloud/desktop/pull/4816 +* Fix crash: 'Failed to create OpenGL context'. by @allexzander in https://github.com/nextcloud/desktop/pull/4821 +* i18n: Spelling unification by @Valdnet in https://github.com/nextcloud/desktop/pull/4820 +* Ensure that throttled notifications still appear in tray activity model by @claucambra in https://github.com/nextcloud/desktop/pull/4734 +* Do not reboot PC when running an MSI via autoupdate. by @allexzander in https://github.com/nextcloud/desktop/pull/4799 +* Update macOS Info.plist by @claucambra in https://github.com/nextcloud/desktop/pull/4755 +* Ensure debug archive contents are readable by any user by @claucambra in https://github.com/nextcloud/desktop/pull/4756 +* Stop clearing notifications when new notifications are received by @claucambra in https://github.com/nextcloud/desktop/pull/4735 +* Fix ActivityItemContent QML paintedWidth errors by @claucambra in https://github.com/nextcloud/desktop/pull/4738 +* Respect skipAutoUpdateCheck in nextcloud.cfg with Sparkle on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4717 +* Only set _FORTIFY_SOURCE when a higher level of this flag has not been set by @claucambra in https://github.com/nextcloud/desktop/pull/4703 +* Fix bad quote in CMakeLists PNG generation message by @claucambra in https://github.com/nextcloud/desktop/pull/4700 +* Ensure the dispatch source only gets deallocated after the dispatch_source_cancel is done, avoiding crashing of the Finder Sync Extension on macOS by @claucambra in https://github.com/nextcloud/desktop/pull/4643 +* Close call notifications when the call has been joined by the user, or the call has ended by @claucambra in https://github.com/nextcloud/desktop/pull/4672 +* Correct spelling by @Valdnet in https://github.com/nextcloud/desktop/pull/4678 +* Fix the system tray menu not being correctly replaced in setupContextMenu on GNOME by @claucambra in https://github.com/nextcloud/desktop/pull/4655 +* Fix crashing when selecting user status and predefined statuses not appearing by @claucambra in https://github.com/nextcloud/desktop/pull/4616 +* Force OpenGL via Angle and using warp direct3d software rasterizer by @mgallien in https://github.com/nextcloud/desktop/pull/4582 +* Fix for the share dialog: mode.absolutePath being undefined prevented the share dialog from being opened by the user. by @camilasan in https://github.com/nextcloud/desktop/pull/4640 +* Add contrast to the text/icon of buttons if the server defined color is light. by @camilasan in https://github.com/nextcloud/desktop/pull/4641 +* Fix segfault when _transferDataSocket is nullptr. by @camilasan in https://github.com/nextcloud/desktop/pull/4656 +* Remove assert from test, it is no longer useful. by @camilasan in https://github.com/nextcloud/desktop/pull/4645 +* Fix building the client on macOS without the application bundle by @claucambra in https://github.com/nextcloud/desktop/pull/4612 +* Fix build on macOS versions pre-11 (down to 10.14) by @claucambra in https://github.com/nextcloud/desktop/pull/4563 +* l10n: Fixed grammar by @rakekniven in https://github.com/nextcloud/desktop/pull/4495 +* Fix 'TypeError: Cannot readproperty 'messageSent' of undefined'. by @camilasan in https://github.com/nextcloud/desktop/pull/4573 +* Fix crash caused by overflow in FinderSyncExtension by @claucambra in https://github.com/nextcloud/desktop/pull/4562 +* Explicitly ask user for notification authorisation on launch (macOS) by @claucambra in https://github.com/nextcloud/desktop/pull/4556 +* Stretch WebView to fit dialog's height. by @allexzander in https://github.com/nextcloud/desktop/pull/4554 +* Add and use DO_NOT_REBOOT_IN_SILENT=1 parameter for MSI to not reboot during the auto-update. by @allexzander in https://github.com/nextcloud/desktop/pull/4566 +* Fix visual borking in the share dialog by @claucambra in https://github.com/nextcloud/desktop/pull/4540 +* Fix two factor authentication notification: 'Mark as read' was being displayed in both action buttons. by @camilasan in https://github.com/nextcloud/desktop/pull/4518 +* If an exclude file is deleted, skip it and remove it from internal list by @mgallien in https://github.com/nextcloud/desktop/pull/4519 +* Fixed share link expiration box being ineditable and always attempting to set invalid date by @claucambra in https://github.com/nextcloud/desktop/pull/4543 +* Fix: allow manual rename files with spaces by @allexzander in https://github.com/nextcloud/desktop/pull/4454 +* Fix activity list item issues with colours/layout/etc. by @claucambra in https://github.com/nextcloud/desktop/pull/4472 +* Fix tray icon not displaying "Open main dialog" by @claucambra in https://github.com/nextcloud/desktop/pull/4484 +* Fix: take root folder's files size into account when displaying the total size in selective sync dialog. by @allexzander in https://github.com/nextcloud/desktop/pull/4532 +* Fix crashing of finder sync extension caused by dispatch_source_cancel of nullptr by @claucambra in https://github.com/nextcloud/desktop/pull/4520 +* Ask for Desktop Client version by @solracsf in https://github.com/nextcloud/desktop/pull/4499 +* Only add OCS-APIREQUEST header for 1st request of webflow v1 by @mgallien in https://github.com/nextcloud/desktop/pull/4510 +* Use full-bleed Start Tile by @elsiehupp in https://github.com/nextcloud/desktop/pull/2982 +* l10n: Remove string from translation by @rakekniven in https://github.com/nextcloud/desktop/pull/4473 +* Add new and correct sparkle update signature by @claucambra in https://github.com/nextcloud/desktop/pull/4478 +* Ensure cache is stored in default cache location by @claucambra in https://github.com/nextcloud/desktop/pull/4485 +* l10n: Changed triple dot to ellipsis by @rakekniven in https://github.com/nextcloud/desktop/pull/4469 +* Move URI scheme variable from Nextcloud.cmake to root CMakeListsts. by @allexzander in https://github.com/nextcloud/desktop/pull/4815 +* Move CFAPI shell extensions variables to root CMakeLists. by @allexzander in https://github.com/nextcloud/desktop/pull/4810 + +## [ChangeLog - Legacy][legacy] +[3.8.2]: https://github.com/nextcloud/desktop/compare/v3.8.1...v3.8.2 +[3.8.1]: https://github.com/nextcloud/desktop/compare/v3.8.0...v3.8.1 +[3.8.0]: https://github.com/nextcloud/desktop/compare/v3.7.4...v3.8.0 +[3.7.4]: https://github.com/nextcloud/desktop/compare/v3.7.1...v3.7.4 +[3.7.1]: https://github.com/nextcloud/desktop/compare/v3.7.0...v3.7.1 +[3.7.0]: https://github.com/nextcloud/desktop/compare/v3.6.6...v3.7.0 +[3.6.6]: https://github.com/nextcloud/desktop/compare/v3.6.5...v3.6.6 +[3.6.5]: https://github.com/nextcloud/desktop/compare/v3.6.4...v3.6.5 +[3.6.4]: https://github.com/nextcloud/desktop/compare/v3.6.3...v3.6.4 +[3.6.3]: https://github.com/nextcloud/desktop/compare/v3.6.2...v3.6.3 +[3.6.2]: https://github.com/nextcloud/desktop/compare/v3.6.1...v3.6.2 +[3.6.1]: https://github.com/nextcloud/desktop/compare/v3.6.0...v3.6.1 +[3.6.0]: https://github.com/nextcloud/desktop/compare/v3.6.0-rc1...v3.6.0 +[3.6.0-rc1]: https://github.com/nextcloud/desktop/compare/v3.5.0...v3.6.0-rc1 +[legacy]: https://github.com/nextcloud/desktop/blob/master/ChangeLog%20-%20Legacy diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..5b7448b2e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,360 @@ +cmake_minimum_required(VERSION 3.16) +cmake_policy(SET CMP0071 NEW) # Enable use of QtQuick compiler/generated code + +project(client) + +if(APPLE) + set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OSX deployment version") +endif() + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED 17) + +include(FeatureSummary) + +find_program(CLANG_TIDY_EXE NAMES "clang-tidy") +if (CLANG_TIDY_EXE) + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} -checks=-*,modernize-use-auto,modernize-use-using,modernize-use-nodiscard,modernize-use-nullptr,modernize-use-override,cppcoreguidelines-pro-type-static-cast-downcast,modernize-use-default-member-init,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-init-variables) +endif() + +set(CMAKE_XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME YES) + +set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") + +include(${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake) + +set(QT_VERSION_MAJOR "6") +set(REQUIRED_QT_VERSION "6.8.0") + +# CfAPI Shell Extensions +set( CFAPI_SHELL_EXTENSIONS_LIB_NAME CfApiShellExtensions ) + +set( CFAPI_SHELLEXT_APPID_REG "{E314A650-DCA4-416E-974E-18EA37C213EA}") +set( CFAPI_SHELLEXT_APPID_DISPLAY_NAME "${APPLICATION_NAME} CfApi Shell Extensions" ) + +set( CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID "1E62D59A-6EA4-476C-B707-4A32E88ED822" ) +set( CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID_REG "{${CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID}}" ) +set( CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_DISPLAY_NAME "${APPLICATION_NAME} Custom State Handler" ) + +set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID "6FF9B5B6-389F-444A-9FDD-A286C36EA079" ) +set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG "{${CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID}}" ) +set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME "${APPLICATION_NAME} Thumbnail Handler" ) + +# URI Handler Scheme for Local File Editing +set( APPLICATION_URI_HANDLER_SCHEME "nc") + +# 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") +else() + set(APPLICATION_REV_DOMAIN_INSTALLER ${APPLICATION_REV_DOMAIN}) +endif() + +option( APPLICATION_DISPLAY_LEGACY_IMPORT_DIALOG "Display legacy import dialog" ON ) + +# For usage in XML files we preprocess +string(REPLACE "&" "&" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME}") +string(REPLACE "<" "<" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}") +string(REPLACE ">" ">" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}") + +string(REPLACE "&" "&" APPLICATION_VENDOR_XML_ESCAPED "${APPLICATION_VENDOR}") +string(REPLACE "<" "<" APPLICATION_VENDOR_XML_ESCAPED "${APPLICATION_VENDOR_XML_ESCAPED}") +string(REPLACE ">" ">" APPLICATION_VENDOR_XML_ESCAPED "${APPLICATION_VENDOR_XML_ESCAPED}") + +if (NOT DEFINED LINUX_PACKAGE_SHORTNAME) + set(LINUX_PACKAGE_SHORTNAME "${APPLICATION_SHORTNAME}") +endif() + +if (NOT DEFINED PACKAGE) + set(PACKAGE "${LINUX_PACKAGE_SHORTNAME}-client") +endif() + +set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ) + +include(ECMCoverageOption) + +if(NOT CRASHREPORTER_EXECUTABLE) + set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter") +endif() + +include(Warnings) + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + add_compile_options(-fdiagnostics-color=always) +elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + add_compile_options(-fcolor-diagnostics) +endif() + +include(${CMAKE_SOURCE_DIR}/VERSION.cmake) +# For config.h +include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +# Allows includes based on src/ like #include "common/utility.h" or #include "csync/csync.h" +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}/src +) + +# disable the crashreporter if libcrashreporter-qt is not available or we're building for ARM +if( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/libcrashreporter-qt/CMakeLists.txt") + set( WITH_CRASHREPORTER OFF ) +endif() + +if(NOT WITH_CRASHREPORTER) + message(STATUS "Build of crashreporter disabled.") +endif() + +include(GNUInstallDirs) +include(DefineInstallationPaths) +include(GenerateExportHeader) + +include(GetGitRevisionDescription) + +get_git_head_revision(GIT_REFSPEC GIT_SHA1) + +add_definitions( + -DQT_DISABLE_DEPRECATED_BEFORE=0x051200 + -DQT_DEPRECATED_WARNINGS + -DQT_USE_QSTRINGBUILDER + -DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output +) + +# if we cannot get it from git, directly try .tag (packages) +# this will work if the tar balls have been properly created +# via git-archive. +if ("${GIT_SHA1}" STREQUAL "GITDIR-NOTFOUND") + file(READ ${CMAKE_SOURCE_DIR}/.tag sha1_candidate) + string(REPLACE "\n" "" sha1_candidate ${sha1_candidate}) + if (NOT ${sha1_candidate} STREQUAL "$Format:%H$") + message("${sha1_candidate}") + set (GIT_SHA1 "${sha1_candidate}") + endif() +endif() +message(STATUS "GIT_SHA1 ${GIT_SHA1}") + +set(SYSCONFDIR ${SYSCONF_INSTALL_DIR}) +set(SHAREDIR ${CMAKE_INSTALL_FULL_DATADIR}) + +# Build MacOS app bundle if wished +if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE) + message(STATUS "Build MacOS app bundle") + set(OWNCLOUD_OSX_BUNDLE "${APPLICATION_NAME}.app") + set(LIB_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS") + set(BIN_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS") + add_definitions(-DBUILD_OWNCLOUD_OSX_BUNDLE) +endif() + +find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Core) +option(QUICK_COMPILER "Use QtQuick compiler to improve performance" OFF) + +# this option removes Http authentication, keychain, shibboleth etc and is intended for +# external authentication mechanisms +option(TOKEN_AUTH_ONLY "TOKEN_AUTH_ONLY" OFF) +if(TOKEN_AUTH_ONLY) + message("Compiling with token authentication") + add_definitions(-DTOKEN_AUTH_ONLY=1) +endif() + +option(NO_MSG_HANDLER "Don't redirect QDebug outputs to the log window/file" OFF) +if(NO_MSG_HANDLER) + add_definitions(-DNO_MSG_HANDLER=1) +endif() + +if(BUILD_UPDATER) + message("Compiling with updater") +else() + message("Compiling without updater") +endif() + +# this option builds the shell integration +option(BUILD_SHELL_INTEGRATION "BUILD_SHELL_INTEGRATION" ON) + +# this option builds/installs the generic shell integration icons +option(BUILD_SHELL_INTEGRATION_ICONS "BUILD_SHELL_INTEGRATION_ICONS" ON) + +# this options builds the dolphin integration plugin +option(BUILD_SHELL_INTEGRATION_DOLPHIN "BUILD_SHELL_INTEGRATION_DOLPHIN" ON) + +# this options builds the nautilus (like) integration plugins +option(BUILD_SHELL_INTEGRATION_NAUTILUS "BUILD_SHELL_INTEGRATION_NAUTILUS" ON) + +# this option builds the client +option(BUILD_CLIENT "BUILD_CLIENT" ON) + +# this option creates only libocsync and libowncloudsync (NOTE: BUILD_CLIENT needs to be on) +option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF) + +# build the GUI component, when disabled only nextcloudcmd is built +option(BUILD_GUI "BUILD_GUI" ON) + +# build the tests +option(BUILD_TESTING "BUILD_TESTING" ON) + +# allows to run nextclouddev in parallel to nextcloud + logs +option(NEXTCLOUD_DEV "NEXTCLOUD_DEV" OFF) + +option(ENABLE_CLANG_TIDY "ENABLE_CLANG_TIDY" OFF) +if(ENABLE_CLANG_TIDY) + find_program(CLANG_TIDY_EXE NAMES "clang-tidy") + if (CLANG_TIDY_EXE) + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} -checks=-*,modernize-use-auto,modernize-use-using,modernize-use-nodiscard,modernize-use-nullptr,modernize-use-override,cppcoreguidelines-pro-type-static-cast-downcast,modernize-use-default-member-init,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-init-variables) + endif() +else() + unset(CLANG_TIDY_EXE) + unset(CMAKE_CXX_CLANG_TIDY) +endif() + +# When this option is enabled, 5xx errors are not added to the blacklist +# Normally you don't want to enable this option because if a particular file +# triggers a bug on the server, you want the file to be blacklisted. +option(OWNCLOUD_5XX_NO_BLACKLIST "OWNCLOUD_5XX_NO_BLACKLIST" OFF) +if(OWNCLOUD_5XX_NO_BLACKLIST) + add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1) +endif() + +if(APPLE) + set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" ) +endif() + +if(BUILD_CLIENT) + OPTION(GUI_TESTING "Build with gui introspection features of socket api" OFF) + + if(APPLE AND BUILD_UPDATER) + find_package(Sparkle) + endif() + + if(UNIX AND NOT APPLE) + find_package(Inotify REQUIRED) + endif() + find_package(Sphinx) + find_package(PdfLatex) + find_package(OpenSSL 1.1 REQUIRED ) + find_package(PkgConfig REQUIRED) + pkg_check_modules(OPENSC-LIBP11 libp11 REQUIRED IMPORTED_TARGET) + + set(ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH "" CACHE PATH "Path to the driver for end-to-end encryption token") + option(CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN "Enforce use of an hardware token for end-to-end encryption" false) + + find_package(ZLIB REQUIRED) + find_package(SQLite3 3.9.0 REQUIRED) + + if(NOT WIN32 AND NOT APPLE) + find_package(PkgConfig REQUIRED) + pkg_check_modules(CLOUDPROVIDERS cloudproviders IMPORTED_TARGET) + + if(CLOUDPROVIDERS_FOUND) + pkg_check_modules(DBUS-1 REQUIRED dbus-1 IMPORTED_TARGET) + pkg_check_modules(GIO REQUIRED gio-2.0 IMPORTED_TARGET) + pkg_check_modules(GLIB2 REQUIRED glib-2.0 IMPORTED_TARGET) + endif() + endif() +endif() + +option(BUILD_WITH_WEBENGINE "BUILD_WITH_WEBENGINE" ON) +if (BUILD_WITH_WEBENGINE) + find_package(Qt${QT_VERSION_MAJOR}WebEngineCore ${REQUIRED_QT_VERSION} CONFIG QUIET) + if(APPLE) + set_package_properties(Qt${QT_VERSION_MAJOR}WebEngineCore PROPERTIES + DESCRIPTION "Qt${QT_VERSION_MAJOR} WebEngineCore component." + TYPE RECOMMENDED + ) + else() + set_package_properties(Qt${QT_VERSION_MAJOR}WebEngineCore PROPERTIES + DESCRIPTION "Qt${QT_VERSION_MAJOR} WebEngine component." + TYPE REQUIRED + ) + endif() + + find_package(Qt${QT_MAJOR_VERSION}WebEngineWidgets ${REQUIRED_QT_VERSION} CONFIG QUIET) + if(APPLE) + set_package_properties(Qt${QT_MAJOR_VERSION}WebEngineWidgets PROPERTIES + DESCRIPTION "Qt${QT_MAJOR_VERSION} WebEngineWidgets component." + TYPE RECOMMENDED + ) + else() + set_package_properties(Qt${QT_MAJOR_VERSION}WebEngineWidgets PROPERTIES + DESCRIPTION "Qt${QT_MAJOR_VERSION} WebEngineWidgets component." + TYPE REQUIRED + ) + endif() + + if(Qt${QT_MAJOR_VERSION}WebEngineCore_FOUND AND Qt${QT_MAJOR_VERSION}WebEngineWidgets_FOUND) + message(STATUS "Enable use of Qt6 WebEngine module") + set(WITH_WEBENGINE 1) + else() + unset(WITH_WEBENGINE) + message(STATUS "Disable use of Qt6 WebEngine module") + endif() +endif() + +if (NOT DEFINED APPLICATION_ICON_NAME) + set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME}) +endif() + +include(NextcloudCPack.cmake) + +add_definitions(-DUNICODE) +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=0x0601) +add_definitions(-DWINVER=0x0601) +add_definitions(-DNTDDI_VERSION=0x0A000004) + if( MSVC ) + # Use automatic overload for suitable CRT safe-functions + # See https://docs.microsoft.com/de-de/cpp/c-runtime-library/security-features-in-the-crt?view=vs-2019 + add_definitions( -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1 ) + # Also: Disable compiler warnings because we don't use Windows CRT safe-functions explicitly and don't intend to + # as this is a pure cross-platform source the only alternative would be a ton of ifdefs with calls to the _s version + add_definitions( -D_CRT_SECURE_NO_WARNINGS ) + endif( MSVC ) +endif( WIN32 ) + +if (APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +endif() + +# Handle Translations, pick all client_* files from trans directory. +file( GLOB TRANS_FILES ${CMAKE_SOURCE_DIR}/translations/client_*.ts) +set(TRANSLATIONS ${TRANS_FILES}) + +if(BUILD_CLIENT) + add_subdirectory(src) + if(NOT BUILD_LIBRARIES_ONLY) + add_subdirectory(man) + add_subdirectory(doc) + add_subdirectory(doc/dev) + if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin) + add_subdirectory(admin) + endif(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin) + endif(NOT BUILD_LIBRARIES_ONLY) +endif() + +if(BUILD_SHELL_INTEGRATION) + add_subdirectory(shell_integration) +endif() + +if(BUILD_TESTING) + include(CTest) + enable_testing() + add_subdirectory(test) +endif() + +configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) +configure_file(version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +if(BUILD_OWNCLOUD_OSX_BUNDLE) + install(FILES sync-exclude.lst DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/) + configure_file(sync-exclude.lst bin/${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/sync-exclude.lst COPYONLY) +elseif(BUILD_CLIENT) + install( FILES sync-exclude.lst DESTINATION ${SYSCONFDIR}/${APPLICATION_SHORTNAME} ) + configure_file(sync-exclude.lst bin/sync-exclude.lst COPYONLY) +endif() + +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES INCLUDE_QUIET_PACKAGES) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..30db22a4a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +## Submitting Desktop Client issues + +If you have questions about how to use the Nextcloud Desktop Client, please +visit our [support site][support] or our [forum][forum]. +We are also available on [IRC][irc]. + +### Bug Reporting Guidelines +* __Important__: Report the issue using our [template][template], it includes all the + information we need to track down the issue. +* __SECURITY__: Report any potential security bug by following our [security policy](https://nextcloud.com/security/) instead of filing an issue in our bug tracker +* This repository is *only* for issues within the Nextcloud desktop client. + Issues in other components should be reported in their own repositores: + - [Nextcloud server](https://github.com/nextcloud/server/issues) + - [Android client](https://github.com/nextcloud/android/issues) + - [iOS client](https://github.com/nextcloud/ios/issues) +* Search the existing issues first, it's likely that your issue was already + reported. + +If your issue appears to be a bug, and hasn't been reported, open a new issue. + +Help us to maximize the effort we can spend fixing issues and adding new +features, by not reporting duplicate issues. + +[template]: https://raw.githubusercontent.com/nextcloud/desktop/master/.github/issue_template.md +[support]: https://nextcloud.com/support/ +[forum]: https://help.nextcloud.com/categories +[irc]: https://webchat.freenode.net/?channels=nextcloud + +## Contributing to Source Code + +Thanks for wanting to contribute source code to Nextcloud. That's great! + +You do not need to sign a Contributor Agreement, but we ask that you follow our +[Code of Conduct](https://nextcloud.com/code-of-conduct/). + +Please read the [Contribution Guide](https://nextcloud.com/contribute/) to get +started and follow the [Coding Style](https://github.com/nextcloud/desktop/wiki/Coding-Style) +when writing new code. + +## Translations +Please submit translations via [Transifex](https://www.transifex.com/nextcloud/nextcloud/). diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/COPYING.documentation b/COPYING.documentation new file mode 100644 index 000000000..1d658d6d3 --- /dev/null +++ b/COPYING.documentation @@ -0,0 +1,319 @@ +Creative Commons Legal Code + +Attribution 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined above) for the purposes of this + License. + c. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + d. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + e. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + f. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + g. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + h. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + i. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(b), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(b), as requested. + b. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Section 3(b), in the case of an Adaptation, + a credit identifying the use of the Work in the Adaptation (e.g., + "French translation of the Work by Original Author," or "Screenplay + based on original Work by Original Author"). The credit required by + this Section 4 (b) may be implemented in any reasonable manner; + provided, however, that in the case of a Adaptation or Collection, at + a minimum such credit will appear, if a credit for all contributing + authors of the Adaptation or Collection appears, then as part of these + credits and in a manner at least as prominent as the credits for the + other contributing authors. For the avoidance of doubt, You may only + use the credit required by this Section for the purpose of attribution + in the manner set out above and, by exercising Your rights under this + License, You may not implicitly or explicitly assert or imply any + connection with, sponsorship or endorsement by the Original Author, + Licensor and/or Attribution Parties, as appropriate, of You or Your + use of the Work, without the separate, express prior written + permission of the Original Author, Licensor and/or Attribution + Parties. + c. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION +OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of this License. + + Creative Commons may be contacted at http://creativecommons.org/. diff --git a/CPackOptions.cmake.in b/CPackOptions.cmake.in new file mode 100644 index 000000000..109af43d2 --- /dev/null +++ b/CPackOptions.cmake.in @@ -0,0 +1,21 @@ +# This file is configured at cmake time, and loaded at cpack time. +# To pass variables to cpack from cmake, they must be configured +# in this file. + +if(CPACK_GENERATOR MATCHES "NSIS") + SET( CPACK_PACKAGE_ICON @CMAKE_SOURCE_DIR@/admin/win/nsi/installer.ico ) # A branding image that will be displayed on the top bar inside the installer. installer.bmp + SET( CPACK_NSIS_COMPRESSOR "/SOLID lzma" ) # The arguments that will be passed to the NSIS SetCompressor command. /SOLID lzma +endif(CPACK_GENERATOR MATCHES "NSIS") + +set( CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@ ) +set( CMAKE_BINARY_DIR @CMAKE_BINARY_DIR@ ) + +include("${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake") + +set( CRASHREPORTER_EXECUTABLE @CRASHREPORTER_EXECUTABLE@) + +set( BUILD_OWNCLOUD_OSX_BUNDLE @BUILD_OWNCLOUD_OSX_BUNDLE@) +if(APPLE AND NOT BUILD_OWNCLOUD_OSX_BUNDLE) + message( FATAL_ERROR "You're trying to build a bundle although you haven't built the client in bundle mode.\n Add -DBUILD_OWNCLOUD_OSX_BUNDLE=ON") +endif() + diff --git a/ChangeLog - Legacy b/ChangeLog - Legacy new file mode 100644 index 000000000..f67944863 --- /dev/null +++ b/ChangeLog - Legacy @@ -0,0 +1,1364 @@ +ChangeLog - Legacy +==================== +For details check https://nextcloud.com/blog/category/release. + +2.6 Series ChangeLog +==================== + +version 2.6.4 (release 2020-03-04) +* Fix Explorer pinning: Add fallbacks for Shell commands (fixes #1599) +* WebFlowCredentials: Make username comparison case-insensitive (fix #1741) +* ActivityListModel: Show full date and time as a Tooltip only +* Disable HTTP/2 for now due to Qt bug, allow enabling it via env var +* Fix Explorer integration re-save and hide option on non-Windows +* l10n: Changes to improve source strings +* Updater: Add query-parameter 'updatesegment' to the update check +* Allow Desktop translation merging and custom backport branches + +version 2.6.3 (release 2020-02-17) +* Add UserInfo class and fetch quota via API instead of PropfindJob +* l10n: Changed grammar and triple dots to ellipsis +* l10n: Changed spelling of "user name" to "username" +* Start the client in background if activated by D-Bus +* Do not install files related to cloud providers under Xenial +* Make sure that the libcloudprovider integration is using a valid D-Bus path +* Changed product name to Nextcloud +* Update autoupdate.rst +* Use system proxy by default if no config file is present +* Install libcloudproviders files by default on debian +* Windows 7 is out of support +* BugFix: Handle broken shared file error gracefully +* Fix Explorer integration on Windows and the crash on other systems +* Welcome to 2020 +* Updated year in legalnotice.cpp +* apply http2 qt resend patch from owncloud + +version 2.6.2 (release 2019-12-24) +* Revert DEFAULT_REMOTE_POLL_INTERVAL back from 5 seconds to 30 seconds +* Use user-provided username in displayName() - Fix #836 +* Fix typo +* Build with libcloudproviders on debian and in the AppImage +* Fix tests for Windows platform +* Merge the list of ignored files/symlinks into one Activity notification. +* Fix clang's variadic macro warnings +* Add libdbus-1-dev to the build dependencies +* Compare QDateTime objects more efficient +* Improve the translation of "Share via …" +* Upgrade for Qt 5.12.5 in docker-ci +* Bump Qt 5.12.5 image +* Add timestamp to Mac installer code signing +* MacOS build: Avoid the Get-Task-Allow Entitlement (Notarization) +* Build for Debian stable and oldstable +* Happy new year +* Fall back to old login flow on GS as this is not yet ready +* [stable-2.6] macOS build: Avoid the Get-Task-Allow Entitlement (Notarization) +* Fix remote wipe keychain storage (issue #1592) +* Fix copyright year in MacOSXBundleInfo.plist.in for 2019 +* Fix macOS GUI (Qt 5.12) +* Windows: Workaround for storing >= 4k (4096 bit) client-cert SSL keys +* Fix Activity List: Add check to avoid first empty entry +* Fix macOS GUI (Qt 5.12) No. 2 (continuation of #1651) +* Show date and time in activity log (fixes issue #1683) +* Login Flow v2 enhancements +* Activity List: Fix crash and folder opening +* Fix issue #1237: White text on almost-white background +* Heavy refactoring: Windows workaround for >= 4k (4096 bit) client-cert SSL keys and large certs +* Fix date in ActivityWidget and remove unnecessary string conversion + +version 2.6.1 (release 2019-11-04) +* Changed max GUI bandwidth limits +* Add sync date next to "Synchronized with local folder" +* Slideshow buttons +* Fix qt warning about registering a URL sheme first. +* Issue #1216: added sync-exclude entry for emacs recovery files +* Race condition in the remote size loading logic +* Review of msvc/gcc warnings -> code cleanup, prevention of implicit casts, variadic macros +* Fix double slashes +* Fixing E2E CSR transmission failure for new connections +* Fixed missing 'translatable' exclusions, added missing window titles +* Checks if exclude file is empty before creating the regular expressions. +* Add server info to menu +* Fixed grammar +* Prevent jumping of tray menu +* Don't run connection wizard when quitting the application +* Avoiding copying in range-based loops +* Add a 'Content-Length: 0' header to initial POST requests +* Remote wipe. +* Pick from upstream: Update qtmacgoodies for an OSX crash fix #6930 +* fix for issue no. #1351 +* Merge the list of ignored files/symlinks into one Activity notification. +* Update submodules for Qt 5.12.5 (qtmacgoodies) +* Fix duplicate items in Apps menu (a bug introduced in #1477) +* Fix #1182 +* Fix remote wipe when a proxy is configured. +* Fix updater message: Download link instead of "use the system's update + +version 2.6.0 Login flow v2 (release 2019-09-27) +* Reinstate Debian build in the new Drone config +* Typo +* Marking unused strings as unstranslatable +* Fixes #607 +* Fixes issue #878 +* Fixes issue #1187 +* Displays FileIgnored activities with an info icon +* Minor text change in the link to help in the tab 'General'. +* Update Qt 5.5 compatibility patch for Xenial +* Remove Ubuntu Cosmic and add Eoan package +* Add proper CA to client side certificate connection +* Remove dependency on libgnome-keyring0 on Eoan +* Read .sync_exclude.lst in each subdirectory +* Updates ChangeLog. +* Login flow v2 +* Adds SSL client cert storage to webflow + Login Flow v2 +* Windows: Workaround for CredWriteW used by QtKeychain +* Integrated registry check on windows when hasDarkSystray is called. +* Logo update +* Updated .gitignore to integrate unwanted files when working with VSC … +* Full-Scaled new logo in Windows 10 start menu tile +* Qt5.5 compatiblity patch for login flow V2 + UI improvement (Use newer digest algorithms in TLS error dialog) +* Fix for #1382 "linux client crashes for no discernable reason" +* UI improvement: Message box: Delete / Keep all files +* Improve wording of the context menu in the file manager extension. +* Changes wording in the share context menu. +* Fix White Window issue on Windows by upgrading to Qt 5.12.5 + +2.5 Series ChangeLog +==================== + +version 2.5.3 (release 2019-07-22) +* Fix empty file wording in error log (small) +* Add Qt-5.12 to CI +* Fix a minor typo +* Libcloudproviders: Add missing check for Qt5DBus +* Fix several memory leaks in cloudproviders and add translation support +* Share link fixing +* New drone config +* Uses configuraion to determine if it should show empty folder popup. +* Simplify cmake command to make copy-pastable +* Updated default remote poll to 5 seconds #1115 +* Fix memory leak with device pointer +* Added a nice UI for the E2E-enabled account first connect +* This should fix issue #1000 +* Adds parameter to retrieve shares with its reshares. +* Fixed typo +* Fixed typo in "certificate" +* WebView: Properly handle usernames with spaces and plus signs in it +* Add error category for http file lock error status 423. +* Displays the uid_owner of a shared file. +* Minor text change in the link to help in the tab 'General'. + +version 2.5.2 (release 2019-04-11) +* Handle spaces in username properly in login flow +* Wizard: show an error message if there is no enough free space in the local folder +* Removed whitespace from string +* Do not add double slash to login flow url +* Fix login flow with system proxy +* Start with easier theming +* Do not display dismissed notifications +* Fixed l18n issue. Added space for separating string +* Add invalid certiticate messagebox +* Correct app passwords link +* Be less verbose with logging +* Fix typo in translation string +* Add a command line option to launch the client in the background +* Support Ubuntu Disco Dingo +* Added missing Include +* Make sure _profile and _page are deleted in the correct order +* Fix KDEInstallDirs deprecation warnings +* Removed Stylesheet + +version 2.5.1 (release 2019-01-06) +* Fixup the port in server notification URLs +* GUI: let Clang-Tidy modernize nullptr & override usage +* Improve the slide show +* Libsync: let Clang-Tidy modernize nullptr & override usage +* SettingsDialog: fix a little glitch in the account tool button size +* SettingsDialog: tweak color aware icons +* More verbose error and proper app name on configuration read error +* Fix cmake build using WITH_PROVIDERS=OFF +* Debian/Ubuntu target repository update +* Change man page names and contents for nextcloud +* Share dialog alignment +* Fixed typo +* Change link to docs for NC 15 +* Do not fetch activities if they are not enabled +* Do not read system exclude list if user exclude is present +* Fix the activity loop +* Write the actual folder to the log +* Fix appname for Nautilus integration script + +version 2.5.0 (release 2018-11-14) +* End to end encryption +* New Web login flow +* UI improvements: Notifications +* UI improvements: refactoring of Activities +* SyncJournal: Clear etag filter before sync +* Partial local discovery: Fix scheduling logic +* Sync hidden files by default +* Larger Windows App Icon +* Show a tray message when a folder watcher becomes unreliable #6119 +* Create symlinks for the small-letter application icon file names +* In setup wizard put link to nextcloud installation +* Web view scales vertically +* Add a WebFlowCredentialsAccessManager +* Mac Application Icon +* Ensure GETFileJob notices finishing #6581 +* OAuth2: Try to refresh the token even if the credentials weren't ready. +* Tray workarounds #6545 +* UpdateInfo: Remove unused code +* OAuth: Remove the timeout +* TestOAuth: Don't have global static QObject +* Log: Adjust update/reconcile log verbosity +* Reconcile: When detecting a local move, keep the local mtime +* Wizard enhancement +* FolderMan::checkPathValidityForNewFolder: make sure to work when fold… +* Update: Report on readdir() errors #6610 +* Use encode()/decode() with Python 3 only +* Sqlite: Update bundled version to 3.24.0 +* Do not require server replies to contain an mtime +* Settings: Attempt to fix rename issue on old macOS +* Support higher resolution theme icons +* OAuth: Fix infinite loop when the refresh token is expired +* Windows: Don't ignore files with FILE_ATTRIBUTE_TEMPORARY +* Data-Fingerprint: Fix backup detection when fingerprint is empty +* Nautilus: Fix GET_MENU_ITEMS with utf8 filenames #6643 +* Windows: Release handle/fd when file open fails #6699 +* SettingsDialog: Show the page for the newly created account +* Updates submodule qtmacgoodies. +* Fixes #665 Adds slot for confirmShare button. +* Rename INSTALL to INSTALL.md for Preview :) +* Add cmake temporary stuff +* Inform user that configuration is not writable +* Uses QByteArray to store private key. +* Fix cmake command for linux in README too +* Build fix: remove an unused QtSvg/QSvgRenderer include +* Qtkeychain: 0.8.0 -> 0.9.1 +* Setup wizard: implement an animated and interactive slide show +* Theming for general settings ui +* Make the "Add Folder Sync Connection" button act like a button +* Allow to use the login flow with a self signed certificate +* Fix warning in ShareUserGroupWidget +* Copy over config file to new location on windows +* Update to translate strings +* Migrate http auth to webflow +* Margins +* Qt 5.5 compatibility patch for Xenial +* Fix cmake build of documentation +* Use Nextcloud +* Update isntaller background for OSX +* Fix ActivityWidget palette +* SettingsDialog: disable unnecessary wrapping for the about label +* Added default scheme when server returns just a host +* Removed explicit initialization; Fixed RAND_bytes not found +* Actually open the activity view on a click for more info +* Use a format that supports alpha channels for avatars +* L10n. Added space for correct grammar. + + +2.4 Series ChangeLog +==================== + +version 2.4.1 (2017-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 +* Notifications: Fix timer invocation on macOS +* Notifications: Immediately poll when account online +* Protocol: Remove entries for auto resolved conflicts (#6316) +* owncloudcmd: Set proxy before capabilities call (#6281) +* owncloudcmd: Do not do the capability call when --nonshib is passed +* Avatars: Use old location for servers <10 (#6279) +* Link shares: Change default share name (#6298) +* Nautilus integration: Work with python2 and python3 +* HTTP2: Only allow with Qt 5.9.4 (#6285) +* Crash fixes + +version 2.4.0 (2017-12-21) +* If you're using 2.4.0 alpha1, please upgrade as previous alphas/rcs had an issue with hidden files and renames! +* OAuth2 authentication support by opening external browser (#5668) +* Shibboleth: Change to use OAuth2 if supported (#6198) +* Sharing: Add support for multiple public link shares (#5655) +* Sharing: Add option to copy/email private links (#5023, #5627) +* Sharing: Add option "show file listing" (#5837) +* Sharing: Show warning that links are public (#5747) +* Sharing: Sharing dialog redesign: multiple share links support (#5695) +* Sharing: Make "can edit" partially checked sometimes (#5642) +* Sharing: Trigger a sync for folder affected by a change of sharing (#6098) +* Wizard: Never propose an existing folder for syncing (#5597) +* Wizard: Don't show last page anymore, go to settings directly (#5726) +* Wizard: Handle url-shortener redirects (#5954) +* Wizard: Resolve url/ redirects only if url/status.php not found (#5954) +* Wizard: Add explanation text when server error is shown (#6157) +* Wizard: Update the window size on high dpi screen (#6156) +* Wizard: Don't report confusing error message (#6116) +* Gui: Display the user server avatar (#5482) +* Gui: Use display name of user, not internal name +* Server URL: Update configuration in case of permanent redirection (#5972) +* Gui: Allow to add multiple sync folder connection of the same folder (#6032) +* Tray Menu: More detailed status messages +* Tray Menu: Shibboleth: raise the browser when clicking on the tray (#6105) +* Activity: Link errors from the account tab, allow filtering by account/folder (#5861) +* Activity: Present conflicts more prominently (#5894) +* Activity: Allow sorting the columns in issues and protocol tabs (#6093, #6086) +* Selective Sync: Open sub folder context menu (#5596) +* Selective Sync: Skip excluded folders when reading db (#5772) +* Selective Sync: Remove local files of unselected folder despite other modified files (#5783) +* Excludes: Remove .htaccess form list of excluded files (#5701) +* Excludes: Hardcode desktop.ini +* Excludes: Allow escaping "#" (#6012) +* Excludes: Use faster matching via QRegularExpression (#6063) +* Discovery: Increase the MAX_DEPTH and show deep folders as ignored (#1067) +* Discovery: General speed improvements +* Downloads: Remove empty temporary if disk space full (#5746) +* Downloads: Read Content-MD5 header for object store setups +* Checksums: Add global disable environment variable (#5017) +* Quota: PropagateUpload: Model of remote quota, avoid some uploads (#5537) +* Create favorite also in folder wizard (#455) +* Windows: Use the application icon for the Windows 8 sidebar favorite (#2446, #5690) +* macOS: Finder sidebar icon (#296) +* Overlay Icons: Consider also the "shared by me" as shared (#4788) +* Overlay Icons: Update right after sharing (#6115) +* Overlay Icons: Fix different case paths not matching (#5257) +* Overlay Icons: Detect changes in the shared flag (#6098) +* Windows Overlay Icons: Potential hang fixes +* Linux Overlay Icons: fix branded nemo and caja shell integration (#5966) +* Credentials: Fix behavior for bad password (#5989) +* Credentials: Don't create empty client cert keychain entries (#5752) +* Credentials: Namespace windows cred keys (#6125) +* Credentials: Use per-account keychain entries (#5830, #6126) +* AccountSettings: Triggering log in re-ask about previously rejected certificates (#5819) +* owncloudcmd: Added bandwidth limit parameter (#5707) +* owncloudcmd: Fix timestamps, Fix --logdebug +* AccountSettings: Sync with clean discovery on Ctrl-F6 (#5666) +* Sync: Dynamic sizing of chunks in chunked uploads for improved big file upload performance (#5852) +* Sync: Introduce overall errors that are not tied to a file (#5746) +* Sync: Better messaging for 507 Insufficient Storage (#5537) +* Sync: Create conflicts by comparing the hash of files with identical mtime/size (#5589) +* Sync: Avoid downloads by comparing the hash of files with identical mtime/size (#6153) +* Sync: Upload conflict files if OWNCLOUD_UPLOAD_CONFLICT_FILES environment variable is set (#6038) +* Sync: Blacklist: Don't let errors become warnings (#5516) +* Sync: Check etag again after active sync (#4116) +* Sync: Rename handling fixes: duplicate file ids (#6096, #6212) +* Sync: Rename handling fixes: File size must be equal +* Sync: Rename handling: Fix duplicate files on abort/resume sync (#5949) +* Sync: Add capability for invalid filename regexes (#6092) +* SyncJournalDB: Fall back to DELETE journal mode if WAL mode does not seem to work (#5723) +* SyncJournalDB: Don't crash if the db file is readonly (#6050) +* SyncJournalDB: DB close error is not fatal +* Fix at least one memory leak +* Documentation improvements +* Logging improvements (With Qt logging categories) (#5671) +* Logging filtering per account (#5672) +* Crash fixes +* Test improvements +* Small UI layout fixes +* Performance improvements +* Maintenance Mode: Detect maintenance mode (#4485) +* Maintenance Mode: Add a 1 to 5 min reconnection delay (#5872) +* HTTP: Send a unique X-Request-ID with each request (#5853) +* HTTP: Support HTTP2 when built and running with Qt 5.9.x (Official packages still on Qt 5.6.x) (#5659) +* owncloudcmd: Don't start if connection or auth fails (#5692) +* csync: Switch build from C to C++ (#6033) +* csync: Refactor a lot to use common data structures to save memory and memory copying +* csync: Switch some data structures to Qt data structures +* csync: Switch to using upper layer SyncJournalDB (#6087) +* Switch 3rdparty/json usage to Qt5's QJson (#5710) +* OpenSSL: Don't require directly, only via Qt (#5833) +* Remove iconv dependency, use Qt for file system locale encoding/decoding (emoji filename support on macOS) (#5875) +* Compilation: Remove Qt 4 code (#6025, #5702, #5505) +* Harmonize source code style with clang-format (#5732) +* Switch over to Qt 5 function pointer signal/slot syntax (#6041) +* Compile with stack-smashing protection +* Updater: Rudimentary support for beta channel (#6048) + + +2.3 Series ChangeLog +==================== + +version 2.3.4 (2017-11-02) +* Checksums: Use addData function to avoid endless loop CPU load issues with Office files +* Packaging: Require ZLIB + +version 2.3.3 (2017-08-29) +* Chunking NG: Don't use old chunking on new DAV endpoint (#5855) +* Selective Sync: Skip excluded folders when reading DB, don't let them show errors (#5772) +* Settings: Make window bigger so Qt version is always visible (#5760) +* Share links: Show warning that public link shares are public (#5786) +* Downloads: Re-trigger folder discovery on HTTP 404 (#5799) +* Overlay Icons: Fix potential hangs on Windows +* SyncJournalDB: Don't use ._ as filename pattern if that does not work because of SMB storage settings (#5844) +* SyncJournalDB: Log reason for sqlite3 opening errors +* Notifications: Proapgate "Dismiss" button action to server (#5922) +* Switch Linux build also to Qt 5.6.2 (#5470) +* Stopped maintaining Qt 4 buildability + +version 2.3.2 (2017-05-08) +* Fix more crashes (thanks to everyone submitting to our crash reporter!) +* Improve compatibility with server 10.0 (#5691, X-OC-Total-Size) +* Share dialog: UI improvements, Bring to front on tray click +* owncloudcmd: Align process return value with sync return value (#3936) +* Fix disk free check on Windows when opening the local DB + +version 2.3.1 (2017-03-21) +* Fix several crashes (thanks to everyone submitting to our crash reporter!) +* Improve HTTP redirect handling (#5555) +* Blacklist: Escalate repeated soft error to normal error (#5500) +* NTFS: Do not attempt to upload two existing files with similar casing (#5544) +* Fix URL for linking to application password generation for ownCloud 10.0 (#5605) + +version 2.3.0 (2017-03-03) +* Decreased memory usage during sync +* Overlay icons: Lower CPU usage +* Allow to not sync the server's external storages by default +* Switch Windows and OS X build to Qt 5.6.2 +* Switch to new ownCloud server WebDAV endpoint +* Chunking NG: New file upload chunking algorithmn for ownCloud server 9.2 +* Allow to sync a folder to multiple different servers (Filename change from .csync_journal.db to _sync_$HASH.db) +* Conflicts: Use the local mtime for the conflict file name (#5273) +* "Sync now" menu item +* SSL Client certificate support improved (Show UI, Store keys in keychain) +* Propagator: Upload more small files in parallel +* Sync Engine: Read data-fingerprint property to detect backups (#2325) +* GUI: Show link to ceate an app password/token for syncing +* Share dialog: Add 'Mail link' button +* Caja file manager plugin +* Make "backup detected" message to not trigger in wrong cases +* SyncEngine: Fix renaming of folder when file are changed (#5192) +* Fix reconnect bug if status.php intermittently returns wrong data (#5188) +* Improve sync scheduling (#5317) +* Overlay icons: Improvements in correctnes +* Tray menu: Only update on demand to fix Linux desktop integration glitches +* Progress: Better time/bandwidth estimations +* Network: Follow certain HTTP redirects (#2791) +* Network: Remove all cookies (including load balancers etc) when logging out +* Discovery thread: Low priority +* owncloudsync.log: Write during propagation +* Better error message for files with trailing spaces on Windows +* Excludes: Consider files in hidden folders excluded (#5163) +* Allow sync directory to be a symlinked directory +* Add manifest file on Windows to make the application UAC aware +* macOS: Improve monochrome tray icons +* Shibboleth bugfixes +* Fixes with regards to low disk space +* A ton of other bugfixes +* Refactorings +* Improved documentation +* Crash fixes + + +2.2 Series ChangeLog +==================== + +version 2.2.4 (release 2016-09-27) +* Dolphin Plugin: Use the Application name for the socket path (#5172) +* SyncEngine: Fix renaming of folder when file are changed (#5195) +* Selective Sync: Fix HTTP request loop and show error in view (#5154) +* ConnectionValidator: properly handle error in status.php request (#5188) +* Discovery: Set thread priority to low (#5017) +* ExcludeFiles: Fix when the folder casing is not the same in the settings and in the FS +* ShareLink: Ensure the password line edit is enabled (#5117) + +version 2.2.3 (release 2016-08-08) +* SyncEngine: Fix detection of backup (#5104) +* Fix bug with overriding URL in config (#5016) +* Sharing: Fix bug with file names containing percent encodes (#5042, #5043) +* Sharing: Permissions for federated shares on servers >=9.1 (#4996, #5001) +* Overlays: Fix issues with file name casing on OS X and Windows +* Windows: Skip symlinks and junctions again (#5019) +* Only accept notification API Capability if endpoint is OCS-enabled (#5034) +* Fix windows HiDPI (#4994) +* SocketAPI: Use different pipe name to avoid unusual delay (#4977) +* Tray: Add minimal mode as workaround and testing tool for Linux issues (#4985, #4990) +* owncloudcmd: Fix --exclude regression #4979 +* Small memleak: Use the full file stat destructors (#4992) +* Fix small QAction memleak (#5008) +* Fix crash on shutting down during propagation (#4979) +* Decrease memory usage during sync #4979 +* Setup csync logging earlier to get all log output (#4991) +* Enable Shibboleth debug view with OWNCLOUD_SHIBBOLETH_DEBUG env + +version 2.2.2 (release 2016-06-21) +* Excludes: Don't redundantly add the same exclude files (memleak) (#4967, #4988) +* Excludes: Only log if the pattern was really logged. (#4989) + +version 2.2.1 (release 2016-06-06) + * Fix out of memory error when too many uploads happen (#4611) + * Fix display errors in progress display (#4803 #4856) + * LockWatcher: Remember to upload files after they become unlocked (#4865) + * Fix overlay icons for files with umlauts (#4884) + * Certs: Re-ask for different cert after rejection (#4898, #4911) + * Progress: Don't count items without propagation jobs (#4856, #4910) + * Utility: Fix for the translation of minutes, second (#4855) + * SyncEngine: invalid the blacklist entry when the rename destination change + +version 2.2.0 (release 2016-05-12) + * Overlay icons: Refactoring - mainly for performance improvements + * Improved error handling with Sync Journal on USB storages (#4632) + * Sharing Completion: Improved UI of completion in sharing from desktop. (#3737) + * Show server notifications on the client (#3733) + * Improved Speed with small files by dynamic parallel request count (#4529) + * LockWatcher: Make sure to sync files after apps released exclusive locks on Windows. + * Improved handling of Win32 file locks and network files + * Workaround Ubuntu 16.04 tray icon bug (#4693) + * Removed the Alias field from the folder definition (#4695) + * Improved netrc parser (#4691) + * Improved user notifications about ignored files and conflicts (#4761, #3222) + * Add warnings for old server versions (#4523) + * Enable tranportation checksums if the server supports based on server capabilities (#3735) + + * Default Chunk-size changed to 10MB (#4354) + * Documentation Improvements, ie. about overlay icons + * Translation fixes + * Countless other bugfixes + * Update of QtKeyChain to support Windows credential store + * Packaging of dolphin overlay icon module for bleeding edge distros + + +2.1 Series ChangeLog +==================== + +version 2.1.1 (release 2016-02-10) + * UI improvements for HiDPI screens, error messages, RTL languages + * Fix occurences of "Connection Closed" when a new unauthenticated TCP socket is used + * Fix undeliberate WiFi scanning done by Qt Network classes + * Several fixes/improvements to the sharing dialog + * Several fixes/improvements to the server activity tab + * Create the directory when using --confdir and it does not exist + * Windows Overlay icons: Fix DLL and icon oddities + * Mac Overlay icons: Don't install legacy Finder plugin on >= 10.10 + * Linux Overlay icons: Nemo plugin + * Overlay icons: Fix several wrong icon state computations + * Allow changeable upload chunk size in owncloud.cfg + * Crash fixes on account deletion + * Forget password on explicit sign-out + * OS X: Fix the file system watcher ignoring unicode paths (#4424) + * Windows Installer: Update to NSIS 2.50, fixes possible DLL injection + * Sync Engine: .lnk files + * Sync Engine: symlinked syn directories + * Sync Engine: Windows: Fix deleting and replacing of read-only files (#4308, #4277) + * Sync Engine: Fixes for files becoming directories and vice versa (#4302) + * Misc other fixes/improvements + +version 2.1 (release 2015-12-03) + * GUI: Added a display of server activities + * GUI: Added a separate view for not synced items, ignores, errors + * GUI: Improved upload/download progress UI (#3403, #3569) + * Allowed sharing with ownCloud internal users and groups from Desktop + * Changed files starting in .* to be considered hidden on all platforms (#4023) + * Reflect read-only permissions in filesystem (#3244) + * Blacklist: Clear on successful chunk upload (#3934) + * Improved reconnecting after network change/disconnect (#4167 #3969 ...) + * Improved performance in Windows file system discovery + * Removed libneon-based propagator. As a consequence, The client can no +* longer provide bandwith limiting on Linux-distributions where it is +* using Qt < 5.4 + * Performance improvements in the logging functions + * Ensured that local disk space problems are handled gracefully (#2939) + * Improved handling of checksums: transport validation, db (#3735) + * For *eml-files don't reupload if size and checksum are unchanged (#3235) + * Ensured 403 reply code is handled properly (File Firewall) (#3490) + * Reduced number of PROPFIND requests to server(#3964) + * GUI: Added Account toolbox widget to keep account actions (#4139) + * Tray Menu: Added fixes for Recent Activity menu (#4093, #3969) + * FolderMan: Fixed infinite wait on pause (#4093) + * Renamed env variables to include unit (#2939) + * FolderStatusModel: Attempt to detect removed undecided files (#3612) + * SyncEngine: Don't whipe the white list if the sync was aborted (#4018) + * Quota: Handle special negative value for the quota (#3940) + * State app name in update notification (#4020) + * PropagateUpload: Fixed double-emission of finished (#3844) + * GUI: Ensured folder names which are excluded from sync can be clicked + * Shell Integration: Dolphin support, requires KF 5.16 and KDE Application 15.12 + * FolderStatusModel: Ensured reset also if a folder was renamed (#4011) + * GUI: Fixed accessiblity of remaing items in full settings toolbar (#3795) + * Introduced the term "folder sync connection" in more places (#3757) + * AccountSettings: Don't disable pause when offline (#4010) + * Fixed handling of hidden files (#3980) + * Handle download errors while resuming as soft errors (#4000) + * SocketAPI: Ensured that the command isn't trimmed (#3297) + * Shutdown socket API before removing the db (#3824) + * GUI: Made "Keep" default in the delete-all dialog (#3824) + * owncloudcmd: Introduced return code 0 for --version and --help + * owncloudcmd: Added --max-sync-retries (#4037) + * owncloudcmd: Don't do a check that file are older than 2s (#4160) + * Fixed getting size for selective sync (#3986) + * Re-added close button in the settings window (#3713) + * Added abililty to handle storage limitations gracefully (#3736) + * Organized patches to our base Qt version into admin/qt/patches + * Plus: A lot of unmentioned improvements and fixes + + +2.0 Series ChangeLog +==================== + +version 2.0.2 (release 2015-10-21) + * csync_file_stat_s: Save a bit of memory + * Shibboleth: Add our base user agent to WebKit + * SelectiveSync: Increase folder list timeout to 60 + * Propagation: Try another sync on 423 Locked (#3387) + * Propagation: Make 423 Locked a soft error (#3387) + * Propagation: Reset upload blacklist if a chunk succeeds + * Application: Fix crash on early shutdown (#3898) + * Linux: Don't show settings dialog always when launched twice (#3273, #3771, #3485) + * win32 vio: Add the OPEN_REPARSE_POINTS flag to the CreateFileW call. (#3813) + * AccountSettings: only expand root elements on single click. + * AccountSettings: Do not allow to expand the folder list when disconnected. + * Use application SHORT name for the name of the MacOSX pkg file (ownBrander). + * FolderMan: Fix for removing a syncing folder (#3843) + * ConnectionMethodDialog: Don't be insecure on close (#3863) + * Updater: Ensure folders are not removed (#3747) + * Folder settings: Ensure path is cleaned (#3811) + * Propagator: Simplify sub job finished counting (#3844) + * Share dialog: Hide settings dialog before showing (#3783) + * UI: Only expand 1 level in folder list (#3585) + * UI: Allow folder expanding from button click (#3585) + * UI: Expand folder treeview on single click (#3585) + * GUI: Change tray menu order (#3657) + * GUI: Replace term "sign in" with "Log in" and friends. + * SetupPage: Fix crash caused by uninitialized Account object. + * Use a themable WebDAV path all over. + * Units: Back to the "usual" mix units (JEDEC standard). + * csync io: Full UNC path support on Win (#3748) + * Tray: Don't use the tray workaround with the KDE theme (#3706, #3765) + * ShareDialog: Fix folder display (#3659) + * AccountSettings: Restore from legacy only once (#3565) + * SSL Certificate Error Dialog: show account name (#3729) + * Tray notification: Don't show a message about modified folder (#3613) + * PropagateLocalRemove: remove entries from the DB even if there was an error. + * Settings UI improvements (eg. #3713, #3721, #3619 and others) + * Folder: Do not create the sync folder if it does not exist (#3692) + * Shell integration: don't show share menu item for top level folders + * Tray: Hide while modifying menus (#3656, #3672) + * AddFolder: Improve remote path selection error handling (#3573) + * csync_update: Use excluded_traversal() to improve performance (#3638) + * csync_excluded: Add fast _traversal() function (#3638) + * csync_exclude: Speed up significantly (#3638) + * AccountSettings: Adjust quota info design (#3644, #3651) + * Adjust buttons on remove folder/account questions (#3654) + +version 2.0.1 (release 2015-09-01) + * AccountWizard: fix when the theme specify a override URL (#3699) + +version 2.0.0 (release 2015-08-25) + * Add support for multiple accounts (#3084) + * Do not sync down new big folders from server without users consent (#3148) + * Integrate Selective Sync into the default UI + * OS X: Support native finder integration for 10.10 Yosemite (#2340) + * Fix situation where client would not reconnect after timeout (#2321) + * Use SI units for the file sizes + * Improve progress reporting during sync (better estimations, show all files, show all bandwidth) + * Windows: Support paths >255 characters (#57) by using Windows API instead of POSIX API + * Windows, OS X: Allow to not sync hidden files (#2086) + * OS X: Show file name in UI if file has invalid UTF-8 in file name + * Sharing: Make use of Capability API (#3439) + * Sharing: Do not allow sharing the root folder (#3495) + * Sharing: Show thumbnail + * Client Updater: Check for updates periodically, not only once per run (#3044) + * Windows: Remove misleading option to remove sync data (#3461) + * Windows: Do not provoke AD account locking if password changes (#2186) + * Windows: Fix installer when installing unprivileged (#2616, #2568) + * Quota: Only refresh from server when UI is shown + * SSL Button: Show more information + * owncloudcmd: Fix --httpproxy (#3465) + * System proxy: Ask user for credentials if needed + * Several fixes and performance improvements in the sync engine + * Network: Try to use SSL session tickets/identifiers. Check the SSL button to see if they are used. + * Bandwidth Throttling: Provide automatic limit setting for downloads (#3084) + * Systray: Workaround for issue with Qt 5.5.0 #3656 + + +1.8 Series ChangeLog +==================== + +version 1.8.4 (release 2015-07-13) + * Release to ship a security release of openSSL. No source changes of the ownCloud Client code. + +version 1.8.3 (release 2015-06-23) + * Fix a bug in the Windows Installer that could crash explorer (#3320) + * Reduce 'Connection closed' errors (#3318, #3313, #3298) + * Ignores: Force a remote discovery after ignore list change (#3172) + * Shibboleth: Avoid crash by letting the webview use its own QNAM (#3359) + * System Ignores: Removed *.tmp from system ignore again. If a user +* wants to ignore *.tmp, it needs to be added to the user ignore list. + +version 1.8.2 (release 2015-06-08) + * Improve reporting of server error messages (#3220) + * Discovery: Ignore folders with any 503 (#3113) + * Wizard: Show server error message if possible (#3220) + * QNAM: Fix handling of mitm cert changes (#3283) + * Win32: Installer translations added (#3277) + * Win32: Allow concurrent OEM (un-)installers (#3272) + * Win32: Make Setup/Update Mutex theme-unique (#3272) + * HTTP: Add the branding name to the UserAgent string + * ConnectonValidator: Always run with new credentials (#3266) + * Recall Feature: Admins can trigger an upload of a file from +* client to server again (#3246) + * Propagator: Add 'Content-Length: 0' header to MKCOL request (#3256) + * Switch on checksum verification through branding or config + * Add ability for checksum verification of up and download + * Fix opening external links for some labels (#3135) + * AccountState: Run only a single validator, allow error message +* overriding (#3236, #3153) + * SyncJournalDB: Minor fixes and simplificatons + * SyncEngine: Force re-read of folder Etags for upgrades from +* 1.8.0 and 1.8.1 + * Propagator: Limit length of temporary file name (#2789) + * ShareDialog: Password ui fixes (#3189) + * Fix startup hang by removing QSettings lock file (#3175) + * Wizard: Allow SSL cert dialog to show twice (#3168) + * ProtocolWidget: Fix rename message (#3210) + * Discovery: Test better, treat invalid hrefs as error (#3176) + * Propagator: Overwrite local data only if unchanged (#3156) + * ShareDialog: Improve error reporting for share API fails + * OSX Updater: Only allow updates only if in /Applications (#2931) + * Wizard: Fix lock icon (#1447) + * Fix compilation with GCC 5 + * Treat any 503 error as temporary (#3113) + * Work around for the Qt PUT corruption bug (#2425) + * OSX Shell integration: Optimizations + * Windows Shell integration: Optimizations + .. more than 250 commits since 1.8.1 + +version 1.8.1 (release 2015-05-07) + * Make "operation canceled" error a soft error + * Do not throw an error for files that are scheduled to be removed, +* but can not be found on the server. #2919 + * Windows: Reset QNAM to proper function after hibernation. #2899 #2895 #2973 + * Fix argument verification of --confdir #2453 + * Fix a crash when accessing a dangling UploadDevice pointer #2984 + * Add-folder wizard: Make sure there is a scrollbar if folder names +* are too long #2962 + * Add-folder Wizard: Select the newly created folder + * Activity: Correctly restore column sizes #3005 + * SSL Button: do not crash on empty certificate chain + * SSL Button: Make menu creation lazy #3007 #2990 + * Lookup system proxy async to avoid hangs #2993 #2802 + * ShareDialog: Some GUI refinements + * ShareDialog: On creation of a share always retrieve the share +* This makes sure that if a default expiration date is set this is reflected +* in the dialog. #2889 + * ShareDialog: Only show share dialog if we are connected. + * HttpCreds: Fill pw dialog with previous password. #2848 #2879 + * HttpCreds: Delete password from old location. #2186 + * Do not store Session Cookies in the client cookie storage + * CookieJar: Don't accidentally overwrite cookies. #2808 + * ProtocolWidget: Always add seconds to the DateTime locale. #2535 + * Updater: Give context as to which app is about to be updated #3040 + * Windows: Add version information for owncloud.exe. This should help us know +* what version or build number a crash report was generated with. + * Fix a crash on shutdown in ~SocketApi #3057 + * SyncEngine: Show more timing measurements #3064 + * Discovery: Add warning if returned etag is 0 + * Fix a crash caused by an invalid DiscoveryDirectoryResult::iterator #3051 + * Sync: Fix sync of deletions during 503. #2894 + * Handle redirect of auth request. #3082 + * Discovery: Fix parsing of broken XML replies, which fixes local file disappearing #3102 + * Migration: Silently restore files that were deleted locally by bug #3102 + * Sort folder sizes SelectiveSyncTreeView numerically #3112 + * Sync: PropagateDownload: Read the mtime from the file system after writing it #3103 + * Sync: Propagate download: Fix restoring files for which the conflict file exists #3106 + * Use identical User Agents and version for csync and the Qt parts + * Prevent another crash in ~SocketApi #3118 + * Windows: Fix rename of finished file. #3073 + * AccountWizard: Fix auth error handling. #3155 + * Documentation fixes + * Infrastructure/build fixes + * Win32/OS X: Apply patch from OpenSSL to handle oudated intermediates gracefully #3087 + +version 1.8.0 (release 2015-03-17) + * Mac OS: HIDPI support + * Support Sharing from desktop: Added a share dialog that can be +* opened by context menu in the file managers (Win, Mac, Nautilus) +* Supports public links with password enforcement + * Enhanced usage of parallel HTTP requests for ownCloud 8 servers + * Renamed github repository from mirall to client. + * Mac OS: Use native notification support + * Selective Sync: allow to enforce selective sync in brandings. + * Added ability to build on Windows utilizing MingGW + * SQLite database fixes if running on FAT filesystems + * Improved detection of changing files to upload from local + * Preparations for the multi-account feature + * Fixed experience for Window manager without system tray + * Build with Qt 5.4 + * Dropped libneon dependency if Qt 5.4 is available + * Keep files open very short, that avoid lock problems on Windows +* especially with office software but also others. + * Merged some NetBSD patches + * Selective sync support for owncloudcmd + * Reorganize the source repository + * Prepared direct download + * Added Crashreporter feature to be switched on on demand + * A huge amount of bug fixes in all areas of the client. + * almost 700 commits since 1.7.1 + + +1.7 Series ChangeLog +==================== + +version 1.7.1 (release 2014-12-18) + * Documentation fixes and updates + * Nautilus Python plugin fixed for Python 3 + * GUI wording fixes plus improved log messages + * Fix hidning of the database files in the sync directories + * Compare http download size with the header value to avoid broken +* downloads, bug #2528 + * Avoid initial ETag fetch job at startup, which is not needed. + * Add chunk size http header to PUT requests + * Fixed deteteCookie method of our CookieJar, fix for Shibboleth + * Added fallback for distros where XDG_RUNTIME_DIR is undefined + * Fix the setup wizard, bug #1989, #2264 + * Fix scheduling of ETag check jobs, bug #2553 + * Fix to avoid syncing more than one folder at a time, bug #2407 + * Use fife minutes timeout for all network jobs + * Cleanup for Folderwizard wording + * Improve journal check: Remove corrupted journal files, bug #2547 + * Fix item count in progress dialog for deletes, bug #1132 + * Display correct file count on deletion (#1132) + * Fix reinitializing the folder using the wizard in certain cases (#2606) + * Mac OS: Fixed branding of the pkg file + * Mac OS: Fix display of overlay icons in certain situations (#1132) + * Mac OS: Use a bundled version of OpenSSL (#764, #2600, #2510) + * Win32: improved filesystem watcher + * Win32: Improve threading with shell integration + * Win32: Upgraded to OpenSSL 1.0.1j + * Win32: Improve reliability of Installer, fix removal of Shell Extensions + +version 1.7.0 (release 2014-11-07) + * oC7 Sharing: Handle new sharing options of ownCloud 7 correctly. + * Added Selective sync: Ability to unselect server folders which are +* excluded from syncing, plus GUI and setup GUI + * Added overlay icons for Windows Explorer, Mac OS Finder and GNOME Nautilus. +* Information is provided by the client via a local socket / named pipe API +* which provides information about the sync status of files. + * Improved local change detection: consider file size, detect files +* with ongoing changes and do not upload immediately + * Improved HTTP request timeout handler: all successful requests reset +* the timeout counter + * Improvements for syncing command line tool: netrc support, improved +* SSL support, non interactive mode + * Permission system: ownCloud 7 delivers file and folder permissions, +* added ability to deal with it for shared folders and more. + * Ignore handling: Do not recurse into ignored or excluded directories + * Major sync journal database improvements for more stability and performance + * New library interface to sqlite3 + * Improve "resync handling" if errors occur + * Blacklist improvements + * Improved logging: more useful meta info, removed noise + * Updated to latest Qt5 versions on Windows and OS X + * Fixed data loss when renaming a download temporary fails and there was +* a conflict at the same time. + * Fixed missing warnings about reusing a sync folder when the back button +* was used in the advanced folder setup wizard. + * The 'Retry Sync' button now also restarts all downloads. + * Clean up temporary downloads and some extra database files when wiping a +* folder. + * OS X: Sparkle update to provide pkg format properly + * OS X: Change distribution format from dmg to pkg with new installer. + * Windows: Fix handling of filenames with trailing dot or space + * Windows: Don't use the wrong way to get file mtimes in the legacy propagator. + + + +1.6 Series ChangeLog +==================== + +version 1.6.4 (release 2014-10-22) + * Fix startup logic, fixes bug #1989 + * Fix raise dialog on X11 + * Win32: fix overflow when computing the size of file > 4GiB + * Use a fixed function to get files modification time, the +* original one was broken for certain timezone issues, see +* core bug #9781 for details + * Added some missing copyright headers + * Avoid data corruption due to wrong error handling, bug #2280 + * Do improved request timeout handling to reduce the number of +* timed out jobs, bug #2155 +* version 1.6.3 (release 2014-09-03) + * Fixed updater on OS X + * Fixed memory leak in SSL button that could lead to quick memory draining + * Fixed upload problem with files >4 GB + * MacOSX, Linux: Bring Settings window to front properly + * Branded clients: If no configuration is detected, try to import the data +* from a previously configured community edition. + +version 1.6.2 (release 2014-07-28 ) + * Limit the HTTP buffer size when downloading to limit memory consumption. + * Another small mem leak fixed in HTTP Credentials. + * Fix local file name clash detection for MacOSX. + * Limit maximum wait time to ten seconds in network limiting. + * Fix data corruption while trying to resume and the server does +* not support it. + * HTTP Credentials: Read password from legacy place if not found. + * Shibboleth: Fix the waiting curser that would not disapear (#1915) + * Limit memory usage to avoid mem wasting and crashes + * Propagator: Fix crash when logging out during upload (#1957) + * Propagator_qnam: Fix signal slot connection (#1963) + * Use more elaborated way to detect that the server was reconfigured (#1948) + * Setup Wizard: Reconfigure Server also if local path was changed (#1948) + +version 1.6.1 (release 2014-06-26 ) + * Fix 'precondition failed' bug with broken upload + * Fix openSSL problems for windows deployment + * Fix syncing a folder with '#' in the name + * Fix #1845: do not update parent directory etag before sub +* directories are removed + * Fix reappearing directories if dirs are removed during its +* upload + * Fix app version in settings dialog, General tab + * Fix crash in FolderWizard when going offline + * Shibboleth fixes + * More specific error messages (file remove during upload, open +* local sync file) + * Use QSet rather than QHash in SyncEngine (save memory) + * Fix some memory leaks + * Fix some thread race problems, ie. wait for neon thread to finish +* before the propagator is shut down + * Fix a lot of issues and warnings found by Coverity + * Fix Mac some settings dialog problems + + +version 1.6.0 (release 2014-05-30 ) + * Minor GUI improvements + * Qt5 compile issues fixed + * Ignore sync log file in filewatcher + * Install libocsync to private library dir and use rpath to localize + * Fix reconnect after server disconnect + * Fix "unknown action" display in Activity window + * Fix memory leaks + * Respect XDG_CONFIG_HOME environment var + * Handle empty fileids in the journal correctly + * Add abilility to compile libowncloudsync without GUI dependendy + * Fix SSL error with previously-expired CAs on Windows + * Fix incorrect folder pause state after start + * Fix a couple of actual potential crashes + * Improve Cookie support (e.g. for cookie-based load-balancers) + * Introduce a general timeout of 300s for network operations + * Improve error handling, blacklisting + * Job-based change propagation, enables faster parallel up/downloads +* (right now only if no bandwidth limit is set and no proxy is used) + * Significantly reduced CPU load when checking for local and remote changes + * Speed up file stat code on Windows + * Enforce Qt5 for Windows and Mac OS X builds + * Improved owncloudcmd: SSL support, documentation + * Added advanced logging of operations (file .???.log in sync +* directory) + * Avoid creating a temporary copy of the sync database (.ctmp) + * Enable support for TLS 1.2 negotiation on platforms that use +* Qt 5.2 or later + * Forward server exception messages to client error messages + * Mac OS X: Support Notification Center in OS X 10.8+ + * Mac OS X: Use native settings dialog + * Mac OS X: Fix UI inconsistencies on Mavericks + * Shibboleth: Warn if authenticating with a different user + * Remove vio abstraction in csync + * Avoid data loss when a client file system is not case sensitive + + +1.5 Series ChangeLog +==================== + +version 1.5.3 (release 2014-03-10 ) + * Fix usage of proxies after first sync run (#1502, #1524, #1459, #1521) + * Do not wipe the credentials from config for reconnect (#1499, #1503) + * Do not erase the full account config if an old version of the client stored +* the password (related to above) + * Fix layout of the network tab (fixes #1491) + * Handle authentication requests by a Shibboleth IdP + * Shibboleth: If no connection is available, don't open the login window + * [Packaging] Debian/Ubuntu: ship sync-exclude.lst + * [Packaging] Fix issues with access to gnome keychain in Fedora and RHEL6 + * [Packaging] Ensure all sub packages get updated + * [Packaging] Fix incorrect path in desktop file (RHEL6/CentOS6) + +version 1.5.2 (release 2014-02-26 ) + * Fix behavior when attempting to rename Shared folder + * Fix potential endless sync loops on Mac OS (#1463) + * Fix potential crash when pausing during update phase (#1442) + * Fix handing of shared directories + * Fix online state handling (#1441, #1459) + * Fix potential crash in c_iconv on Mac OS + * Fix certificate chain display in SSLButton + * Fix sporadicly appearing multiple auth prompts on sign-in + * Show correct state icon in Account Settings right away + * Re-fetch content that gets deleted from read only shared directories + * Do not store the password in the config file, erase existing ones (#1469) + * Shibboleth: Close browser window after login + * Shibboleth: Proper invalidation if timeout during sync + * Shibboleth: Do not pop up IdP login immediately when modifying account + * Shibboleth: Avoid auth on restart by storing cookies in the wallet + * Fix license headers + +version 1.5.1 (release 2014-02-13 ) + * Added an auto updater that updates the client if a +* more recent version was found automatically (Windows, Mac OS X) + * Added a button to the account dialog that gives information +* about the encryption layer used for communication, plus a +* certificate information widget + * Preserve the permission settings of local files rather than +* setting them to a default (Bug #820) + * Handle windows lnk files correctly (Bug #1307) + * Detect removes and renames in read only shares and +* restore the gone away files. (Bug #1386) + * Fixes sign in/sign out and password dialog. (Bug #1353) + * Fixed error messages (Bug #1394) + * Lots of fixes for building with Qt5 + * Changes to network limits are now also applied during a +* sync run + * Fixed mem leak after via valgrind on Mac + * Imported the ocsync library into miralls repository. +* Adopted all build systems and packaging to that. + * Introduce a new linux packaging scheme following the +* debian upstream scheme + * Use a refactored Linux file system watcher based on +* inotify, incl. unit tests + * Wizard: Gracefully fall back to HTTP if HTTPS connection +* fails, issuing a warning + * Fixed translation misses in the propagator + * Fixes in proxy configuration + * Fixes in sync journal handling + * Fix the upload progress if the local source is still +* changing when the upload begins. + * Add proxy support to owncloud commandline client + * NSIS fixes + * A lot of other fixes and minor improvements + * Improve Qt5 compatability + +version 1.5.0 (release 2013-12-12 ), csync 0.91.4 required + * New owncloud propagator that skips the vio abstraction layer + * Add owncloudcmd to replace the ocsync command line tool + * Localize Windows installer + * Allow to sign in and out + * Ask for password if missing + * Introduce activity view + * Introduce black list for files which could not be synced + * Enabling accessbility by shipping accessibility enables on OS X (#736) + * Toggle Settings window when clicking on systray icon on Win and KDE (#896) + * FolderWizard: Sanitize error detection (#1201) + * Set proper enable state of blacklist button after the dialog was opened + * Set proper tooltips in blacklist + * Translatable error messages for file errors + * Add man page for owncloudcmd (#1234) + * Don't close setup wizard when the initial sync run is started + * Close the sync journal if a folder gets removed (#1252) + * Activity: Avoid horizontal scrollbar (#1213) + * Fix crash (#1229) + * Resize wizard appropriately (#1130) + * Fix account identity test (#1231) + * Maintain the file type correctly + * Display rename-target in sync protocol action column + * Let recursive removal also remove the top dir + * If item is a directory, remove its contents from the database as well (#1257) + * Install headers for owncloudsync library + * Fix opening the explorer with a selected file in Windows (#1249) + * Add build number into versioning scheme + * Windows: Fix rename of temporary files + * Windows: Fix move file operation + + +1.4 Series ChangeLog +==================== + +version 1.4.2 (release 2013-10-18 ), csync 0.90.4 required + * Do not show the warning icon in the tray (#944) + * Fix manual proxy support when switching (#1016) + * Add folder column to detailed sync protocol (#1037) + * Fix possible endless loop in inotify (#1041) + * Do not elide the progress text (#1049) + * Fix high CPU load (#1073) + * Reconnect if network is unavailable after startup (#1080) + * Ensure paused folder stays paused when syncing with more than one folder (#1083) + * Don't show desktop notification when the user doesn't want to (#1093) + * System tray: Avoid quick flickering up of the ok-icon for the sync prepare state + * Progress: Do not show progress if nothing is transmitted + * Progress: Show number of deletes. + +version 1.4.1 (release 2013-09-24 ), csync 0.90.1 required + * Translation and documentation fixes. + * Fixed error display in settings/status dialog, displays multi +* line error messages now correctly. + * Wait up to 30 secs before complaining about missing systray +* Fixes bug #949 + * Fixed utf8 issues with basic auth authentication, fixes bug #941 + * Fixed remote folder selector, avoid recursive syncing, fixes bug #962 + * Handle and display network problems at startup correctly. + * Enable and disable the folder watcher during syncs correctly. + * Fix setting of thread priority. + * Fixed file size display. + * Fixed various folder wizard issues, bug #992 + * Made "Sync started" message optional, fixes bug #934 + * Fixed shutdown, avoid crashed config on win32, fixes bug #945 + * Pop up config wizard if no server url is configured, fixes bug #1018 + * Settings: calculate sidebar width dynamically, fixes bug #1020 + * Fixed a crash if sync folders were removed, fixes bug #713 + * Do proper resync after network disconnect, fixes bug #1007 + * Various minor code fixes + +version 1.4.0 (release 2013-09-04 ), csync 0.90.0 required + * New Scheduler: Only sync when there are actual changes in the server + * Add a Settings Dialog, move Proxy Settings there + * Transform folder Status Dialog into Account Settings, provide feedback via context menu + * Add Bandwidth Control + * Add a visual storage/quota indicator (context menu and account settings) + * Add progress indication (context menu and account settings) + * Introduce a sync history, persisting results across syncs + * Move ability to switch to mono icons from a switch to a Settings option + * Add "Launch on System Startup" GUI option + * Add "Show Desktop Nofications"GUI option (enabled by default) +* top optionally disable sync notifications + * Add Help item, pointing to online reference + * Implement graphical selection of remote folders in FolderWizard + * Allow custom ignore patterns + * Add an editor for ingore patterns + * ALlow to flag certain ignore patterns as discardable + * Ensure to ship with all valid translations + * Progress Dialog now preserves the last syncned items across sync runs + * Split Setup Wizard into multiple pages again + * Implement "--logfile -" to log to stdout + * Add preliminary support for Shibboleth authentication + * Linux: Provide more icon sizes + * Linux: Do not trigger notifier on ignored files + * Windows: Reduce priority of CSync thread + * Documentation: Prem. updates to reflect UI changes + * Significant code refactorings + * Require Qt 4.7 + * Known issue: Under certain conditions, a file will only get uploaded after up to five minutes + + +1.3 Series ChangeLog +==================== + +version 1.3.0 (release 2013-06-25 ), csync 0.80.0 required + * Default proxy port to 8080 + * Don't lose proxy settings when changing passwords + * Support SOCKS5 proxy (useful in combination with ssh* *D) + * Propagate proxy changes to csync at runtime + * Improve proxy wizard + * Display proxy errors + * Solved problems with lock files + * Warn if for some reason all files are scheduled for removal on either side + * Avoid infinite loop if authentication fails in certain cases + * Fix reading the password from the config in certain cases + * Do not crash when configured sync target disappears + * Make --help work on windows + * Make sync feedback less ambiguous. + * Fix icon tray tooltip sometimes showing repeated content + * More use of native directory separators on Windows + * Remove journal when reusing a directory that used to have a journal before + * Visual clean up of status dialog items + * Wizard: When changing the URL or user name, allow the user to push his data +* to the new location or wipe the folder and start from scratch + * Wizard: Make setting a custom folder as a sync target work again + * Fix application icon + * User-Agent now contains "Mozilla/5.0" and the Platform name (for firewall/proxy compat) + * Server side directory moves will be detected + * New setup wizard, defaulting to root syncing (only for new setups) + * Improved thread stop/termination + + +1.2 Series ChangeLog +==================== + +version 1.2.5 (release 2013-04-23 ), csync 0.70.7 required + * [Fixes] NSIS installer fixes + * [Fixes] Fix crash race by making certificateChain() thread safe + * [Fixes] Build with older CMake versions (CentOS/RHEL 6) + * [Fixes] Wording in GUI + * [Fixes] Silently ignore "installed = true" status.php + * Set log verbosity before calling csync_init. + * GUI feedback for the statistics copy action + * Safer approach for detecting duplicate sync runs + +version 1.2.4 (release 2013-04-11 ), csync 0.70.6 required + * [Fixes] Clarify string in folder wizard + * [Fixes] Fixed some valgrind warnings + * [Fixes] Ensure that only one sync thread can ever run + * [Fixes] Fix default config storage path + * [Fixes] Skip folders with no absolute path + * [Fixes] Allow setting the configuration directory on command line + +version 1.2.3 (release 2013-04-02 ), csync 0.70.5 required + * [Fixes] Unbreak self-signed certificate handling + +version 1.2.2 (release 2013-04-02 ), csync 0.70.5 required + * [Fixes] Do not crash when local file tree contains symlinks + * [Fixes] Correctly handle locked files on Windows + * [Fixes] Display errors in all members of the SSL chain + * [Fixes] Enable Accessibility features on Windows + * [Fixes] Make setupFavLink work properly on Mac OS + * [Fixes] Ignore temporary files created by MS Office + * [Gui] Support Nautilus in setupFavLink + +version 1.2.1 (release 2013-02-26 ), csync 0.70.4 required + * [Fixes] Leave configured folders on configuration changes. + * [Fixes] Do not allow to finish the setup dialog if connection can't be established. + * [Fixes] Better handling of credentials in setup dialog. + * [Fixes] Do not leak fd's to /dev/null when using gnutls + * [Fixes] Stop sync scheduling when configuration wizard starts. + * [Fixes] Clear pending network requests when stepping back in config wizard. + * [Fixes] User password dialog asynchronous issues. + * [Fixes] Make folderman starting and stoping the scheduling. + * [Fixes] Various minor fixes and cleanups. + * [Fixes] Crash on pausing sync + * [Fixes] Stale lock file after pausing sync + * [App] Load translations from app dir or bundle as well. + * [Platform] Build fixes and simplifications, ie. build only one lib. + * [Platform] Added some getter/setters for configuration values. + * [Platform] Added man pages. + * [Platform] Simplified/fixed credential store usage and custom configs. + * [Platform] Added soname version to libowncloudsync. + * [Platform] Pull in Qt translations + * [Gui] Make sync result popups less annoyingq + * [Gui] Fix for result popup + +version 1.2.0 (release 2013-01-24 ), csync 0.70.2 required + * [GUI] New status dialog to show a detailed list of synced files. + * [GUI] New tray notifications about synced files. + * [GUI] New platform specific icon set. + * [App] Using cross platform QtKeychain library to store credentials crypted. + * [App] Use cross platform notification for changes in the local file system rather than regular poll. + * [Fixes] Improved SSL Certificate handling and SSL fixes troughout syncing. + * [Fixes] Fixed proxy authentication. + * [Fixes] Allow brackets in folder name alias. + * [Fixes] Lots of other minor fixes. + * [Platform] cmake fixes. + * [Platform] Improved, more detailed error reporting. + + +1.1 Series ChangeLog +==================== + +version 1.1.4 (release 2012-12-19 ), csync 0.60.4 required + * No changes to mirall, only csync fixes. + +version 1.1.3 (release 2012-11-30 ), csync 0.60.3 required + * No changes to mirall, only csync fixes. + +version 1.1.2 (release 2012-11-26 ), csync 0.60.2 required + * [Fixes] Allow to properly cancel the password dialog. + * [Fixes] Share folder name correctly percent encoded with old Qt +* * * * 4.6 builds ie. Debian. + * [Fixes] If local sync dir is not existing, create it. + * [Fixes] lots of other minor fixes. + * [GUI] Display error messages in status dialog. + * [GUI] GUI fixes for the connection wizard. + * [GUI] Show username for connection in statusdialog. + * [GUI] Show intro wizard on new connection setup. + * [APP] Use CredentialStore to better support various credential +* * * backends. + * [APP] Handle missing local folder more robust: Create it if +* * * missing instead of ignoring. + * [APP] Simplify treewalk code. + * [Platform] Fix Mac building + +version 1.1.1 (release 2012-10-18), csync 0.60.1 required + * [GUI]* Allow changing folder name in single folder mode + * [GUI]* Windows: Add license to installer + * [GUI]* owncloud --logwindow will bring up the log window +* * * * in an already running instance + * [Fixes] Make sure SSL errors are always handled + * [Fixes] Allow special characters in folder alias + * [Fixes] Proper workaround for Menu bug in Ubuntu + * [Fixes] csync: Fix improper memory cleanup which could +* * * * cause memory leaks and crashes + * [Fixes] csync: Fix memory leak + * [Fixes] csync: Allow single quote (') in file names + * [Fixes] csync: Remove stray temporary files + + * [GUI]* Reworked tray context menu. + * [GUI]* Users can now sync the server root folder. + * [Fixes] Proxy support: now supports Proxy Auto-Configuration (PAC) +* * * * on Windows, reliability fixes across all OSes. + * [Fixes] Url entry field in setup assistant handles http/https correctly. + * [Fixes] Button enable state in status dialog. + * [Fixes] Crash fixed on ending the client, tray icon related. + * [Fixes] Crash through wrong delete operator. + * [MacOS] behave correctly on retina displays. + * [MacOS] fix focus policy. + * [MacOS] Packaging improvements. + * [MacOS] Packaging improvements. + * [Platform] Windows: Setup closes client prior to uninstall. + * [Platform] Windows: ownCloud gets added to autorun by default. + * [Platform] insert correct version info from cmake. + * [Platform] csync conf file and database were moved to the users app data +* * * * * directory, away from the .csync dir. + ** * * Renamed exclude.lst to sync-exclude.lst and moved it to +* * * * /etc/appName()/ for more clean packaging. From the user path, +* * * * still exclude.lst is read if sync-exclude.lst is not existing. + ** * * Placed custom.ini with customization options to /etc/appName() + + +1.0 Series ChangeLog +==================== + +version 1.0.5 (release 2012-08-14), csync 0.50.8 required + * [Fixes] Fixed setup dialog: Really use https if checkbox is activated. + +version 1.0.4 (release 2012-08-10), csync 0.50.8 required + * [APP] ownCloud is now a single instance app, can not start twice any more. + * [APP] Proxy support + * [APP] Handle HTTP redirection correctly, note new url. + * [APP] More relaxed handling of read only directories in the sync paths. + * [APP] Started to split off a library with sync functionality, eg for KDE + * [APP] Make ownCloud Info class a singleton, more robust. + * [GUI] New, simplified connection wizard. + * [GUI] Added ability for customized theming. + * [GUI] Improved icon size handling. + * [GUI] Removed Log Window Button, log available through command line. + * [GUI] Proxy configuration dialog added. + * [GUI] Added Translations to languages Slovenian, Polish, Catalan, +* * * Portuguese (Brazil), German, Greek, Spanish, Czech, Italian, Slovak, +* * * French, Russian, Japanese, Swedish, Portuguese (Portugal) +* * * all with translation rate >90%. + * [Fixes] Loading of self signed certs into Networkmanager (#oc-843) + * [Fixes] Win32: Handle SSL dll loading correctly. + * [Fixes] Many other small fixes and improvements. + +version 1.0.3 (release 2012-06-19), csync 0.50.7 required + * [GUI] Added a log window which catches the logging if required and +* * * allows to save for information. + * [CMI] Added options --help, --logfile and --logflush + * [APP] Allow to specify sync frequency in the config file. + * [Fixes] Do not use csync database files from a sync before. + * [Fixes] In Connection wizard, write the final config onyl if +* * * * the user really accepted. Also remove the former database. + * [Fixes] More user expected behaviour deletion of sync folder local +* * * * and remote. + * [Fixes] Allow special characters in the sync directory names + * [Fixes] Win32: Fixed directory removal with special character dirs. + * [Fixes] MacOS: Do not flood the system log any more + * [Fixes] MacOS: Put app translations to correct places + * [Fixes] Win32: Fix loading of csync state db. + * [Fixes] Improved some english grammar. + * [Platform] Added krazy2 static code checks. + +version 1.0.2 (release 2012-05-18), csync 0.50.6 required + * [GUI] New icon set for ownCloud client + * [GUI] No splashscreen any more (oC Bug #498) + * [GUI] Russian translation added + * [GUI] Added 'open ownCloud' to traymenu + * [GUI] "Pause" and "Resume" instead of Enable/Disable + * [Fixes] Long running syncs can be interrupted now. + * [Fixes] Dialogs comes to front on click + * [Fixes] Open local sync folder from tray and status for win32 + * [Fixes] Load exclude.lst correctly on MacOSX +* + csync fixes. + +version 1.0.1 (release 2012-04-18), csync 0.50.5 required + * [Security] Support SSL Connections + * [Security] SSL Warning dialog + * [Security] Do not store password in clear text anymore + * [Security] Restrict credentials to the configured host + * [Security] Added ability to forbid local password storage. + * [Fixes] Various fixes of the startup behaviour. + * [Fixes] Various fixes in sync status display + * [GUI] Various error messages for user display improved. + * [GUI] fixed terms and Translations + * [GUI] fixed translation loading + * [Intern] Migrate old credentials to new format + * [Intern] Some code refactorings, got rid of rotten QWebDav lib + * [Intern] lots of cmake cleanups + * [Intern] Backport to Qt Version 4.6 for compat. with older distros. + * [Platform] MacOSX porting efforts + * [Platform] MacOSX Bundle creation added + * [Platform] Enabled ranslations on Windows. + diff --git a/NEXTCLOUD.cmake b/NEXTCLOUD.cmake new file mode 100644 index 000000000..e589a7799 --- /dev/null +++ b/NEXTCLOUD.cmake @@ -0,0 +1,91 @@ +# keep the application name and short name the same or different for dev and prod build +# or some migration logic will behave differently for each build +if(NEXTCLOUD_DEV) + set( APPLICATION_NAME "NextcloudDev" ) + set( APPLICATION_SHORTNAME "NextcloudDev" ) + set( APPLICATION_EXECUTABLE "nextclouddev" ) + set( APPLICATION_ICON_NAME "Nextcloud" ) +else() + set( APPLICATION_NAME "Nextcloud" ) + set( APPLICATION_SHORTNAME "Nextcloud" ) + set( APPLICATION_EXECUTABLE "nextcloud" ) + set( APPLICATION_ICON_NAME "${APPLICATION_SHORTNAME}" ) +endif() + +set( APPLICATION_CONFIG_NAME "${APPLICATION_EXECUTABLE}" ) +set( APPLICATION_DOMAIN "nextcloud.com" ) +set( APPLICATION_VENDOR "Nextcloud GmbH" ) +set( APPLICATION_UPDATE_URL "https://updates.nextcloud.org/client/" CACHE STRING "URL for updater" ) +set( APPLICATION_HELP_URL "" CACHE STRING "URL for the help menu" ) + +if(APPLE AND APPLICATION_NAME STREQUAL "Nextcloud" AND EXISTS "${CMAKE_SOURCE_DIR}/theme/colored/Nextcloud-macOS-icon.svg") + set( APPLICATION_ICON_NAME "Nextcloud-macOS" ) + message("Using macOS-specific application icon: ${APPLICATION_ICON_NAME}") +endif() + +set( APPLICATION_ICON_SET "SVG" ) +set( APPLICATION_SERVER_URL "" CACHE STRING "URL for the server to use. If entered, the UI field will be pre-filled with it" ) +set( APPLICATION_SERVER_URL_ENFORCE ON ) # If set and APPLICATION_SERVER_URL is defined, the server can only connect to the pre-defined URL +set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" ) +set( APPLICATION_VIRTUALFILE_SUFFIX "nextcloud" CACHE STRING "Virtual file suffix (not including the .)") +set( APPLICATION_OCSP_STAPLING_ENABLED OFF ) +set( APPLICATION_FORBID_BAD_SSL OFF ) + +set( LINUX_PACKAGE_SHORTNAME "nextcloud" ) +set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}") + +set( THEME_CLASS "NextcloudTheme" ) +set( WIN_SETUP_BITMAP_PATH "${CMAKE_SOURCE_DIR}/admin/win/nsi" ) + +set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-background.png" CACHE STRING "The MacOSX installer background image") + +# set( THEME_INCLUDE "${OEM_THEME_DIR}/mytheme.h" ) +# set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt ) + +option( WITH_CRASHREPORTER "Build crashreporter" OFF ) +#set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE STRING "URL for crash reporter" ) +#set( CRASHREPORTER_ICON ":/owncloud-icon.png" ) + +## Updater options +option( BUILD_UPDATER "Build updater" ON ) + +option( WITH_PROVIDERS "Build with providers list" ON ) + +option( ENFORCE_VIRTUAL_FILES_SYNC_FOLDER "Enforce use of virtual files sync folder when available" OFF ) +option( DISABLE_VIRTUAL_FILES_SYNC_FOLDER "Disable use of virtual files sync folder even when available" OFF ) + +option(ENFORCE_SINGLE_ACCOUNT "Enforce use of a single account in desktop client" OFF) + +option( DO_NOT_USE_PROXY "Do not use system wide proxy, instead always do a direct connection to server" OFF ) + +## Theming options +set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color") +set( APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR ${NEXTCLOUD_BACKGROUND_COLOR} CACHE STRING "Hex color of the wizard header background") +set( APPLICATION_WIZARD_HEADER_TITLE_COLOR "#ffffff" CACHE STRING "Hex color of the text in the wizard header") +option( APPLICATION_WIZARD_USE_CUSTOM_LOGO "Use the logo from ':/client/theme/colored/wizard_logo.(png|svg)' else the default application icon is used" ON ) + +# +## Windows Shell Extensions & MSI - IMPORTANT: Generate new GUIDs for custom builds with "guidgen" or "uuidgen" +# +if(WIN32) + # Context Menu + set( WIN_SHELLEXT_CONTEXT_MENU_GUID "{BC6988AB-ACE2-4B81-84DC-DC34F9B24401}" ) + + # Overlays + set( WIN_SHELLEXT_OVERLAY_GUID_ERROR "{E0342B74-7593-4C70-9D61-22F294AAFE05}" ) + set( WIN_SHELLEXT_OVERLAY_GUID_OK "{E1094E94-BE93-4EA2-9639-8475C68F3886}" ) + set( WIN_SHELLEXT_OVERLAY_GUID_OK_SHARED "{E243AD85-F71B-496B-B17E-B8091CBE93D2}" ) + set( WIN_SHELLEXT_OVERLAY_GUID_SYNC "{E3D6DB20-1D83-4829-B5C9-941B31C0C35A}" ) + set( WIN_SHELLEXT_OVERLAY_GUID_WARNING "{E4977F33-F93A-4A0A-9D3C-83DEA0EE8483}" ) + + # MSI Upgrade Code (without brackets) + set( WIN_MSI_UPGRADE_CODE "FD2FCCA9-BB8F-4485-8F70-A0621B84A7F4" ) + + # Windows build options + option( BUILD_WIN_MSI "Build MSI scripts and helper DLL" OFF ) + option( BUILD_WIN_TOOLS "Build Win32 migration tools" OFF ) +endif() + +if (APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 11.0) + option( BUILD_FILE_PROVIDER_MODULE "Build the macOS virtual files File Provider module" OFF ) +endif() diff --git a/NextcloudCPack.cmake b/NextcloudCPack.cmake new file mode 100644 index 000000000..0682090c0 --- /dev/null +++ b/NextcloudCPack.cmake @@ -0,0 +1,63 @@ +include( InstallRequiredSystemLibraries ) + +set( CPACK_PACKAGE_CONTACT "Dominik Schmidt " ) + +include("${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake") + +include( VERSION.cmake ) +set( CPACK_PACKAGE_VERSION_MAJOR ${MIRALL_VERSION_MAJOR} ) +set( CPACK_PACKAGE_VERSION_MINOR ${MIRALL_VERSION_MINOR} ) +set( CPACK_PACKAGE_VERSION_PATCH ${MIRALL_VERSION_PATCH} ) +set( CPACK_PACKAGE_VERSION_BUILD ${MIRALL_VERSION_BUILD} ) +set( CPACK_PACKAGE_VERSION ${MIRALL_VERSION_FULL}${MIRALL_VERSION_SUFFIX} ) + +if(APPLE) + set( CPACK_GENERATOR "DragNDrop" ) + set( CPACK_SOURCE_GENERATOR "") + set( CPACK_PACKAGE_FILE_NAME ${APPLICATION_SHORTNAME}-${CPACK_PACKAGE_VERSION} ) + set( CPACK_PACKAGE_ICON ${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns) + + set( CPACK_DMG_DS_STORE "${CMAKE_SOURCE_DIR}/admin/osx/DS_Store.in") +# set( CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/admin/osx/DMGBackground.png" ) + + set( CPACK_DMG_FORMAT "UDBZ" ) + set( CPACK_DMG_VOLUME_NAME "${APPLICATION_SHORTNAME}") + + # did not work with cmake 2.8.7, so we override MacOSXBundleInfo.plist.in + #set( CPACK_BUNDLE_PLIST ${CMAKE_SOURCE_DIR}/admin/osx/Info.plist ) + + # do we need these? + #set( CPACK_SYSTEM_NAME "OSX" ) + #set( CPACK_PACKAGE_NAME "FOO" ) + #set( CPACK_BUNDLE_NAME "BAR" ) +endif() + + + + +if(WIN32) + set( CPACK_PACKAGE_FILE_NAME ${APPLICATION_SHORTNAME}-${CPACK_PACKAGE_VERSION}-setup ) + # Package file name without extension. Also a directory of installer cmake-2.5.0-Linux-i686 + # CPACK_GENERATOR CPack generator to be used STGZ;TGZ;TZ + # CPACK_INCLUDE_TOPLEVEL_DIRECTORY Controls whether CPack adds a top-level directory, usually of the form ProjectName-Version-OS, to the top of package tree. 0 to disable, 1 to enable + # CPACK_INSTALL_CMAKE_PROJECTS List of four values: Build directory, Project Name, Project Component, Directory in the package /home/andy/vtk/CMake-bin;CMake;ALL;/ + set( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" ) # File used as a description of a project /path/to/project/ReadMe.txt + set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "${APPLICATION_NAME} Syncing Client" ) # Description summary of a project + # CPACK_PACKAGE_EXECUTABLES List of pairs of executables and labels. Used by the NSIS generator to create Start Menu shortcuts. ccmake;CMake + set( CPACK_PACKAGE_INSTALL_DIRECTORY ${APPLICATION_SHORTNAME} ) # Installation directory on the target system -> C:\Program Files\${APPLICATION_SHORTNAME} + set( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${APPLICATION_SHORTNAME} ) # Registry key used when installing this project CMake 2.5.0 + set( CPACK_PACKAGE_NAME ${APPLICATION_NAME} ) # Package name, defaults to the project name + set( CPACK_PACKAGE_VENDOR "http://${APPLICATION_DOMAIN}" ) # Package vendor name +endif() + +# set( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt" ) # License file for the project, used by the STGZ, NSIS, and PackageMaker generators. /home/andy/vtk/CMake/Copyright.txt + + +set( CPACK_TOPLEVEL_TAG "unused" ) # Directory for the installed files. - needed to provide anything to avoid an error# CPACK_INSTALL_COMMANDS Extra commands to install components. + + +# Set the options file that needs to be included inside CMakeCPackOptions.cmake +configure_file("${CMAKE_SOURCE_DIR}/CPackOptions.cmake.in" + "${CMAKE_BINARY_DIR}/CPackOptions.cmake" @ONLY) +set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_BINARY_DIR}/CPackOptions.cmake") # File included at cpack time, once per generator after setting CPACK_GENERATOR to the actual generator being used; allows per-generator setting of CPACK_* variables at cpack time. ${PROJECT_BINARY_DIR}/CPackOptions.cmake +include(CPack) diff --git a/README.md b/README.md new file mode 100644 index 000000000..65a8f1505 --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# Nextcloud Desktop Client + +The Nextcloud Desktop Client is a tool to synchronize files from Nextcloud Server with your computer. + +

+ Desktop Client on Windows +

+ +## :rocket: Releases +For the latest stable recommended version, please refer to the [download page https://nextcloud.com/install/#install-clients](https://nextcloud.com/install/#install-clients) + +## Contributing to the desktop client +:v: Please read the [Code of Conduct](https://nextcloud.com/community/code-of-conduct/). This document offers some guidance to ensure Nextcloud participants can cooperate effectively in a positive and inspiring atmosphere and to explain how together we can strengthen and support each other. + +### 👪 Join the team +There are many ways to contribute, of which development is only one! Find out [how to get involved](https://nextcloud.com/contribute/), including as a translator, designer, tester, helping others, and much more! 😍 + +### Help testing +Download and install the client:
+[🔽 All releases](https://github.com/nextcloud-releases/desktop/releases)
+[🔽 Daily master builds](https://download.nextcloud.com/desktop/daily) + +### Reporting issues +If you find any bugs or have any suggestion for improvement, please +[open an issue in this repository](https://github.com/nextcloud/desktop/issues). + +### Bug fixing and development +#### 1. 🚀 Set up your local development environment + +1.1 System requirements +- [Windows 10, Windows 11]((https://github.com/nextcloud/desktop-client-blueprints/)), Mac OS > 10.14 or Linux + +> [!NOTE] +> Find the system requirements and instructions on [how to work on Windows with KDE Craft](https://github.com/nextcloud/desktop-client-blueprints/) on our [desktop client blueprints repository](https://github.com/nextcloud/desktop-client-blueprints/). + +- [🔽 Inkscape (to generate icons)](https://inkscape.org/release/) +- Developer tools: cmake, clang/gcc/g++: +- Qt6 since 3.14, Qt5 for earlier versions +- OpenSSL +- [🔽 QtKeychain](https://github.com/frankosterfeld/qtkeychain) +- SQLite + +1.2 Optional +- [Qt Creator IDE](https://www.qt.io/product/development-tools) +- [delta: A viewer for git and diff output](https://github.com/dandavison/delta) + +> [!TIP] +> We highly recommend [Nextcloud development environment on Docker Compose](https://juliusknorr.github.io/nextcloud-docker-dev/) for testing/bug fixing/development.
+> ▶️ https://juliusknorr.github.io/nextcloud-docker-dev/ + +1.3 Step by step instructions on how to build the client to contribute +1. Clone the Github repository: +``` +git clone https://github.com/nextcloud/desktop.git +``` +2. Create : +``` +mkdir +``` +3. Compile: +``` +cd +cmake -S -B build -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=. -DNEXTCLOUD_DEV=ON +``` + +> [!TIP] +> The cmake variabel NEXTCLOUD_DEV allows you to run your own build of the client while developing in parallel with an installed version of the client. + +4. Build it: +- Windows: +``` +cmake --build . +``` +- Other platforms: +``` +make +``` + +> [!TIP] +> For building the client for mac OS we have a tool called mac-crafter. +> You will find instructions on how to use it at [admin/osx/mac-crafter](https://github.com/nextcloud/desktop/tree/32305e4c15ff95d00fae07e82e750fe9051b2250/admin/osx/mac-crafter). + +5. 🐛 [Pick a good first issue](https://github.com/nextcloud/desktop/labels/good%20first%20issue) +6. 👩‍🔧 Create a branch and make your changes. Remember to sign off your commits using `git commit -sm "Your commit message"` +7. ⬆ Create a [pull request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) and `@mention` the people from the issue to review +8. 👍 Fix things that come up during a review +9. 🎉 Wait for it to get merged! + +## Get in touch 💬 +* [📋 Forum](https://help.nextcloud.com) +* [👥 Facebook](https://www.facebook.com/nextclouders) +* [🐣 Twitter](https://twitter.com/Nextclouders) +* [🐘 Mastodon](https://mastodon.xyz/@nextcloud) + +You can also [get support for Nextcloud](https://nextcloud.com/support)! + +## :scroll: License + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. diff --git a/VERSION.cmake b/VERSION.cmake new file mode 100644 index 000000000..3fe5f7797 --- /dev/null +++ b/VERSION.cmake @@ -0,0 +1,66 @@ +# ------------------------------------ +# Version information +# ------------------------------------ +set(MIRALL_VERSION_MAJOR 3) +set(MIRALL_VERSION_MINOR 16) +set(MIRALL_VERSION_PATCH 2) +set(MIRALL_VERSION_YEAR 2025) +set(MIRALL_SOVERSION 0) +set(MIRALL_PREVERSION_HUMAN "3.16.2") # For preversions where PATCH>=50. Use version + alpha, rc1, rc2, etc. + +# ------------------------------------ +# Minimum supported server versions +# According to: https://docs.nextcloud.com/server/latest/admin_manual/release_schedule.html +# ------------------------------------ +set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MAJOR 18) +set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MINOR 0) +set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_PATCH 0) + +set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MAJOR 26) +set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR 0) +set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH 0) + +set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MAJOR 28) +set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR 0) +set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH 3) + +# ------------------------------------ +# Define default suffixes if not set +# ------------------------------------ +if(NOT DEFINED MIRALL_VERSION_SUFFIX) + set(MIRALL_VERSION_SUFFIX "daily") # e.g. beta1, rc1, etc. +endif() + +if(NOT DEFINED MIRALL_VERSION_BUILD) + set(MIRALL_VERSION_BUILD "0") # Integer ID generated by the build system +endif() + +# ------------------------------------ +# Composite version definitions +# ------------------------------------ +# Used for libraries: keep at x.y.z +set(MIRALL_VERSION "${MIRALL_VERSION_MAJOR}.${MIRALL_VERSION_MINOR}.${MIRALL_VERSION_PATCH}") + +# Full version (includes build number) +set(MIRALL_VERSION_FULL "${MIRALL_VERSION}.${MIRALL_VERSION_BUILD}") + +# Base version string (e.g. 3.16.50daily) +set(MIRALL_VERSION_STRING "${MIRALL_VERSION}${MIRALL_VERSION_SUFFIX}") + +# Decide human-readable version string +if(MIRALL_VERSION_PATCH VERSION_GREATER_EQUAL 50) + set(MIRALL_HUMAN_VERSION_STRING "${MIRALL_PREVERSION_HUMAN}") +else() + set(MIRALL_HUMAN_VERSION_STRING "${MIRALL_VERSION_STRING}") +endif() + +# Append build info if available +if(MIRALL_VERSION_BUILD) + set(MIRALL_VERSION_STRING "${MIRALL_VERSION_STRING} (build ${MIRALL_VERSION_BUILD})") +endif() + +# ------------------------------------ +# Misc +# ------------------------------------ +# Not used anymore. For brander, please maintain craftmaster.ini +set(QT_MAJOR_VERSION 6) diff --git a/admin/CMakeLists.txt b/admin/CMakeLists.txt new file mode 100644 index 000000000..b54e48ed1 --- /dev/null +++ b/admin/CMakeLists.txt @@ -0,0 +1,7 @@ +if(APPLE) + # traverse into osx subdirectory to install and patch the create-pack script + add_subdirectory(osx) +elseif(WIN32) + # MSI package scripts, helper DLL and migration tools + add_subdirectory(win) +endif() diff --git a/admin/linux/build-appimage.sh b/admin/linux/build-appimage.sh new file mode 100755 index 000000000..61b1b6f67 --- /dev/null +++ b/admin/linux/build-appimage.sh @@ -0,0 +1,127 @@ +#! /bin/bash + +set -xe + +export APPNAME=${APPNAME:-Nextcloud} +export EXECUTABLE_NAME=${EXECUTABLE_NAME:-nextcloud} +export BUILD_UPDATER=${BUILD_UPDATER:-OFF} +export BUILDNR=${BUILDNR:-0000} +export DESKTOP_CLIENT_ROOT=${DESKTOP_CLIENT_ROOT:-/home/user} +export QT_BASE_DIR=${QT_BASE_DIR:-/usr} +export OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR:-/usr/lib/x86_64-linux-gnu} +export VERSION_SUFFIX=${VERSION_SUFFIX:stable} + +# Set defaults +export SUFFIX=${PR_ID:=${DRONE_PULL_REQUEST:=master}} +if [ $SUFFIX != "master" ]; then + SUFFIX="PR-$SUFFIX" +fi +if [ "$BUILD_UPDATER" != "OFF" ]; then + BUILD_UPDATER=ON +fi + +# Ensure we use gcc-11 on RHEL-like systems +if [ -e "/opt/rh/gcc-toolset-11/enable" ]; then + source /opt/rh/gcc-toolset-11/enable +fi + +mkdir /app + +# Build client +mkdir build-client +cd build-client +cmake \ + -G Ninja \ + -DCMAKE_PREFIX_PATH=${QT_BASE_DIR} \ + -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBUILD_TESTING=OFF \ + -DBUILD_UPDATER=$BUILD_UPDATER \ + -DMIRALL_VERSION_BUILD=$BUILDNR \ + -DMIRALL_VERSION_SUFFIX="$VERSION_SUFFIX" \ + -DCMAKE_UNITY_BUILD=ON \ + ${DESKTOP_CLIENT_ROOT} +cmake --build . --target all +DESTDIR=/app cmake --install . + +# Move stuff around +cd /app + +[ -d usr/lib/x86_64-linux-gnu ] && mv usr/lib/x86_64-linux-gnu/* usr/lib/ + +mkdir usr/plugins +mv usr/lib64/*sync_vfs_suffix.so usr/plugins || mv usr/lib/*sync_vfs_suffix.so usr/plugins +mv usr/lib64/*sync_vfs_xattr.so usr/plugins || mv usr/lib/*sync_vfs_xattr.so usr/plugins + +rm -rf usr/lib/cmake +rm -rf usr/include +rm -rf usr/mkspecs +rm -rf usr/lib/x86_64-linux-gnu/ + +# Don't bundle the explorer extensions as we can't do anything with them in the AppImage +rm -rf usr/share/caja-python/ +rm -rf usr/share/nautilus-python/ +rm -rf usr/share/nemo-python/ + +# Move sync exclude to right location +mv /app/etc/*/sync-exclude.lst usr/bin/ +rm -rf etc + +# com.nextcloud.desktopclient.nextcloud.desktop +DESKTOP_FILE=$(ls /app/usr/share/applications/*.desktop) + +# Use linuxdeploy to deploy +export APPIMAGE_NAME=linuxdeploy-x86_64.AppImage +wget -O ${APPIMAGE_NAME} --ca-directory=/etc/ssl/certs -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" +chmod a+x ${APPIMAGE_NAME} +./${APPIMAGE_NAME} --appimage-extract +rm ./${APPIMAGE_NAME} +cp -r ./squashfs-root ./linuxdeploy-squashfs-root + +export LD_LIBRARY_PATH=/app/usr/lib64:/app/usr/lib:${QT_BASE_DIR}/lib:/usr/local/lib/x86_64-linux-gnu:/usr/local/lib:/usr/local/lib64 +./linuxdeploy-squashfs-root/AppRun --desktop-file=${DESKTOP_FILE} --icon-file=usr/share/icons/hicolor/512x512/apps/Nextcloud.png --executable=usr/bin/${EXECUTABLE_NAME} --appdir=AppDir + +# Use linuxdeploy-plugin-qt to deploy qt dependencies +export APPIMAGE_NAME=linuxdeploy-plugin-qt-x86_64.AppImage +wget -O ${APPIMAGE_NAME} --ca-directory=/etc/ssl/certs -c "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" +chmod a+x ${APPIMAGE_NAME} +./${APPIMAGE_NAME} --appimage-extract +rm ./${APPIMAGE_NAME} +cp -r ./squashfs-root ./linuxdeploy-plugin-qt-squashfs-root + +export PATH=${QT_BASE_DIR}/bin:${PATH} +export QML_SOURCES_PATHS=${DESKTOP_CLIENT_ROOT}/src/gui +./linuxdeploy-plugin-qt-squashfs-root/AppRun --appdir=AppDir + +./linuxdeploy-squashfs-root/AppRun --desktop-file=${DESKTOP_FILE} --icon-file=usr/share/icons/hicolor/512x512/apps/Nextcloud.png --executable=usr/bin/${EXECUTABLE_NAME} --appdir=AppDir --output appimage + +# Workaround issue #103 and #7231 +export APPIMAGETOOL=appimagetool-x86_64.AppImage +wget -O ${APPIMAGETOOL} --ca-directory=/etc/ssl/certs -c https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage +chmod a+x ${APPIMAGETOOL} +rm -rf ./squashfs-root +./${APPIMAGETOOL} --appimage-extract +rm ./${APPIMAGETOOL} +cp -r ./squashfs-root ./appimagetool-squashfs-root +rm -rf ./squashfs-root +APPIMAGE=$(ls *.AppImage) +./"${APPIMAGE}" --appimage-extract +rm ./"${APPIMAGE}" +rm ./squashfs-root/usr/lib/libglib-2.0.so.0 +LD_LIBRARY_PATH="$PWD/appimagetool-squashfs-root/usr/lib":$LD_LIBRARY_PATH PATH="$PWD/appimagetool-squashfs-root/usr/bin":$PATH appimagetool -n ./squashfs-root "${APPIMAGE}" + +#move AppImage +export COMMIT=${GITHUB_SHA:=${DRONE_COMMIT}} +if [ ! -z "$COMMIT" ] +then + export APPIMAGE_NAME="${EXECUTABLE_NAME}-${SUFFIX}-${COMMIT}-x86_64.AppImage" +else + export APPIMAGE_NAME="${EXECUTABLE_NAME}-${SUFFIX}-x86_64.AppImage" +fi +mv *.AppImage ${DESKTOP_CLIENT_ROOT}/$APPIMAGE_NAME + +# tell GitHub Actions the name of our appimage +if [ ! -z "$GITHUB_OUTPUT" ]; then + echo "AppImage name: ${APPIMAGE_NAME}" + echo "APPIMAGE_NAME=${APPIMAGE_NAME}" >> "$GITHUB_OUTPUT" +fi diff --git a/admin/linux/clean_tarball.sh b/admin/linux/clean_tarball.sh new file mode 100755 index 000000000..51d0918a7 --- /dev/null +++ b/admin/linux/clean_tarball.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +rm -vrf admin/ +rm -vrf src/3rdparty/sqlite3 # FIXME: For CentOS6 we have to use our bundled sqlite +rm -vrf binary/ +rm -vrf src/3rdparty/libcrashreporter-qt +rm -vrf shell_integration/windows +rm -vrf shell_integration/MacOSX diff --git a/admin/linux/debian/drone-build.sh b/admin/linux/debian/drone-build.sh new file mode 100755 index 000000000..2729adb33 --- /dev/null +++ b/admin/linux/debian/drone-build.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +set -xe +shopt -s extglob + +env + +PPA=ppa:nextcloud-devs/client +PPA_ALPHA=ppa:nextcloud-devs/client-alpha +PPA_BETA=ppa:nextcloud-devs/client-beta + +OBS_PROJECT=home:ivaradi +OBS_PROJECT_ALPHA=home:ivaradi:alpha +OBS_PROJECT_BETA=home:ivaradi:beta +OBS_PACKAGE=nextcloud-desktop + +if test "${DRONE_TARGET_BRANCH}" = "stable-2.6"; then + UBUNTU_DISTRIBUTIONS="bionic focal jammy kinetic" + DEBIAN_DISTRIBUTIONS="buster stretch testing" +else + UBUNTU_DISTRIBUTIONS="jammy noble oracular plucky" + DEBIAN_DISTRIBUTIONS="bullseye bookworm testing" +fi + +declare -A DIST_TO_OBS=( + ["bullseye"]="Debian_11" + ["bookworm"]="Debian_12" + ["testing"]="Debian_Testing" +) + +pull_request=${DRONE_PULL_REQUEST:=master} + +if test -z "${DRONE_WORKSPACE}"; then + DRONE_WORKSPACE=`pwd` +fi + +if test -z "${DRONE_DIR}"; then + DRONE_DIR=`dirname ${DRONE_WORKSPACE}` +fi + +set +x +if test "$DEBIAN_SECRET_KEY" -a "$DEBIAN_SECRET_IV"; then + openssl aes-256-cbc -K $DEBIAN_SECRET_KEY -iv $DEBIAN_SECRET_IV -in admin/linux/debian/signing-key.txt.enc -d | gpg --import + + openssl aes-256-cbc -K $DEBIAN_SECRET_KEY -iv $DEBIAN_SECRET_IV -in admin/linux/debian/oscrc.enc -out ~/.oscrc -d + + touch ~/.has_ppa_keys +fi +set -x + +cd "${DRONE_WORKSPACE}" +git config --global user.email "drone@noemail.invalid" +git config --global user.name "Drone User" +git fetch --tags + +for distribution in ${UBUNTU_DISTRIBUTIONS} ${DEBIAN_DISTRIBUTIONS}; do + git fetch origin debian/dist/${distribution}/${DRONE_TARGET_BRANCH} + git checkout origin/debian/dist/${distribution}/${DRONE_TARGET_BRANCH} + + git merge ${DRONE_COMMIT} + + read basever revdate kind <<<$(admin/linux/debian/scripts/git2changelog.py /tmp/tmpchangelog stable "" "" ${DRONE_COMMIT}) + break +done + +cd "${DRONE_DIR}" + +echo "$kind" > kind + +if test "$kind" = "alpha"; then + repo=nextcloud-devs/client-alpha +elif test "$kind" = "beta"; then + repo=nextcloud-devs/client-beta +else + repo=nextcloud-devs/client +fi + +origsourceopt="" + +cp -a ${DRONE_WORKSPACE} nextcloud-desktop_${basever}-${revdate} +tar cjf nextcloud-desktop_${basever}-${revdate}.orig.tar.bz2 --exclude .git --exclude binary nextcloud-desktop_${basever}-${revdate} + +cd "${DRONE_WORKSPACE}" + +for distribution in ${UBUNTU_DISTRIBUTIONS} ${DEBIAN_DISTRIBUTIONS}; do + git checkout -- . + git clean -xdf + + git fetch origin debian/dist/${distribution}/${DRONE_TARGET_BRANCH} + git checkout origin/debian/dist/${distribution}/${DRONE_TARGET_BRANCH} + + git merge ${DRONE_COMMIT} + + admin/linux/debian/scripts/git2changelog.py /tmp/tmpchangelog ${distribution} ${revdate} ${basever} + cat /tmp/tmpchangelog debian/changelog > debian/changelog.new + mv debian/changelog.new debian/changelog + + fullver=`head -1 debian/changelog | sed "s:nextcloud-desktop (\([^)]*\)).*:\1:"` + + EDITOR=true dpkg-source --commit . local-changes + + dpkg-source --build . + dpkg-genchanges -S -sa > "../nextcloud-desktop_${fullver}_source.changes" + + if test -f ~/.has_ppa_keys; then + debsign -k2265D8767D14AA7B -S + fi +done +cd .. +ls -al + +if test "${pull_request}" = "master"; then + if test "$kind" = "alpha"; then + PPA=$PPA_ALPHA + OBS_PROJECT=$OBS_PROJECT_ALPHA + elif test "$kind" = "beta"; then + PPA=$PPA_BETA + OBS_PROJECT=$OBS_PROJECT_BETA + fi + + if test -f ~/.has_ppa_keys; then + for distribution in ${UBUNTU_DISTRIBUTIONS}; do + changes=$(ls -1 nextcloud-desktop_*~${distribution}1_source.changes) + if test -f "${changes}"; then + dput $PPA "${changes}" > /dev/null + fi + done + + if test -n "${DEBIAN_DISTRIBUTIONS}"; then + package="nextcloud-desktop" + OBS_SUBDIR="${OBS_PROJECT}/${package}" + + mkdir -p osc + pushd osc + osc co "${OBS_PROJECT}" "${package}" + + if test "$(ls ${OBS_SUBDIR})"; then + osc delete ${OBS_SUBDIR}/* + fi + + ln ../nextcloud-desktop*.orig.tar.* ${OBS_SUBDIR}/ + + for distribution in ${DEBIAN_DISTRIBUTIONS}; do + pkgsuffix=".${distribution}" + pkgvertag="~${distribution}1" + obs_dist="${DIST_TO_OBS[${distribution}]}" + + ln ../nextcloud-desktop_*[0-9.][0-9]${pkgvertag}.dsc ${OBS_SUBDIR}/nextcloud-desktop-${obs_dist}.dsc + ln ../nextcloud-desktop_*[0-9.][0-9]${pkgvertag}.debian.tar* ${OBS_SUBDIR}/ + done + + osc add ${OBS_SUBDIR}/* + + cd ${OBS_SUBDIR} + osc commit -m "Drone update" + popd + fi + fi +fi diff --git a/admin/linux/debian/oscrc.enc b/admin/linux/debian/oscrc.enc new file mode 100644 index 0000000000000000000000000000000000000000..5eb93009e38c5d59fb4793e7fb3a76a92896a405 GIT binary patch literal 5472 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 WYg)=|NpY_s^8>_Hv3dk@7MyDIU5 %s" % (name, email, date), file=f) + print(file=f) + return (latestBaseVersion, latestRevDate, latestKind) + +if __name__ == "__main__": + scriptdir = os.path.dirname(__file__) + configPath = os.path.join(scriptdir, "git2changelog.cfg") + + baseCommit = "f9b1c724d6ab5431e0cd56b7cd834f2dd48cebb1" + baseVersion = "2.4.0" + + config = None + if os.path.exists(configPath): + config = ConfigParser.SafeConfigParser() + config.read(configPath) + + if config.has_section("base"): + if config.has_option("base", "commit") and \ + config.has_option("base", "version"): + baseCommit = config.get("base", "commit") + baseVersion = config.get("base", "version") + + distribution = sys.argv[2] + finalRevDate = sys.argv[3] if len(sys.argv)>3 and sys.argv[3] else None + finalBaseVersion = sys.argv[4] if len(sys.argv)>4 and sys.argv[4] else None + finalCommit = sys.argv[5] if len(sys.argv)>5 and sys.argv[5] else None + + entries = collectEntries(baseCommit, baseVersion, "alpha", + finalBaseVersion, finalRevDate, config, + finalCommit) + + with open(sys.argv[1], "wt") as f: + (baseVersion, revdate, kind) = genChangeLogEntries(f, entries, distribution) + print(baseVersion, revdate, kind) diff --git a/admin/linux/debian/signing-key.txt.enc b/admin/linux/debian/signing-key.txt.enc new file mode 100644 index 0000000000000000000000000000000000000000..cebc15b9eeb3d26b44a0e7aa4d74a04b13593635 GIT binary patch literal 6672 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 aBC%&9rBC)o?mT~aS8wl}q2(3O5WKv+mgunn literal 0 HcmV?d00001 diff --git a/admin/nix/flake.nix b/admin/nix/flake.nix new file mode 100644 index 000000000..c2bf70772 --- /dev/null +++ b/admin/nix/flake.nix @@ -0,0 +1,143 @@ +/* + * Copyright (C) by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +{ + description = "A flake for the Nextcloud desktop client"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + with flake-utils.lib; + eachSystem [ "aarch64-linux" "x86_64-linux" "aarch64-darwin" "x86_64-darwin" ] (system: + let + pkgs = import nixpkgs { + inherit system; + }; + + inherit (pkgs.lib.lists) optional optionals; + inherit (pkgs.lib.strings) hasPrefix optionalString; + isARM = hasPrefix "aarch64" system; + + buildMacOSSymlinks = pkgs.runCommand "nextcloud-build-symlinks" {} '' + mkdir -p $out/bin + ln -s /usr/bin/xcrun /usr/bin/xcodebuild /usr/bin/iconutil $out/bin + ''; + + nativeBuildInputs = with pkgs; [ + cmake + extra-cmake-modules + pkg-config + inkscape + qt5.wrapQtAppsHook + ] ++ optionals stdenv.isDarwin [ + buildMacOSSymlinks + ]; + + buildInputs = with pkgs; [ + sqlite + openssl + pcre + + qt5.qtbase + qt5.qtquickcontrols2 + qt5.qtsvg + qt5.qtgraphicaleffects + qt5.qtdeclarative + qt5.qttools + qt5.qtwebsockets + + libsForQt5.karchive + libsForQt5.qtkeychain + ] ++ optionals (!isARM) [ + # Qt WebEngine not available on ARM + qt5.qtwebengine + ] ++ optionals stdenv.isLinux [ + inotify-tools + libcloudproviders + libsecret + + libsForQt5.breeze-icons + libsForQt5.qqc2-desktop-style + libsForQt5.kio + ] ++ optionals stdenv.isDarwin [ + libsForQt5.qt5.qtmacextras + + darwin.apple_sdk.frameworks.UserNotifications + ]; + + packages.default = with pkgs; stdenv.mkDerivation rec { + inherit nativeBuildInputs buildInputs; + pname = "nextcloud-client"; + version = "dev"; + src = ../../.; + + dontStrip = true; + enableDebugging = true; + separateDebugInfo = false; + enableParallelBuilding = true; + + preConfigure = optionals stdenv.isLinux [ + '' + substituteInPlace shell_integration/libcloudproviders/CMakeLists.txt \ + --replace "PKGCONFIG_GETVAR(dbus-1 session_bus_services_dir _install_dir)" "set(_install_dir "\$\{CMAKE_INSTALL_DATADIR\}/dbus-1/service")" + '' + ] ++ optionals stdenv.isDarwin [ + '' + substituteInPlace shell_integration/MacOSX/CMakeLists.txt \ + --replace "-target FinderSyncExt -configuration Release" "-scheme FinderSyncExt -configuration Release -derivedDataPath $ENV{NIX_BUILD_TOP}/derivedData" + '' + ]; + + cmakeFlags = optionals stdenv.isLinux [ + "-DCMAKE_INSTALL_LIBDIR=lib" # expected to be prefix-relative by build code setting RPATH + "-DNO_SHIBBOLETH=1" # allows to compile without qtwebkit + ] ++ optionals stdenv.isDarwin [ + "-DQT_ENABLE_VERBOSE_DEPLOYMENT=TRUE" + "-DBUILD_OWNCLOUD_OSX_BUNDLE=OFF" + ]; + postPatch = optionalString stdenv.isLinux '' + for file in src/libsync/vfs/*/CMakeLists.txt; do + substituteInPlace $file \ + --replace "PLUGINDIR" "KDE_INSTALL_PLUGINDIR" + done + ''; + postFixup = optionalString stdenv.isLinux '' + wrapProgram "$out/bin/nextcloud" \ + --set LD_LIBRARY_PATH ${lib.makeLibraryPath [ libsecret ]} \ + --set PATH ${lib.makeBinPath [ xdg-utils ]} \ + --set QML_DISABLE_DISK_CACHE "1" + ''; + }; + + apps.default = mkApp { + name = "nextcloud"; + drv = packages.default; + }; + + in { + inherit packages apps; + devShell = pkgs.mkShell { + inherit buildInputs; + nativeBuildInputs = with pkgs; nativeBuildInputs ++ optionals (stdenv.isLinux) [ + gdb + qtcreator + ]; + name = "nextcloud-client-dev-shell"; + }; + } + ); +} diff --git a/admin/osx/CMakeLists.txt b/admin/osx/CMakeLists.txt new file mode 100644 index 000000000..98a2f4eee --- /dev/null +++ b/admin/osx/CMakeLists.txt @@ -0,0 +1,16 @@ + +# Check if variable MAC_INSTALLER_BACKGROUND_FILE is defined. +# Make sure that the MAC_INSTALLER_BACKGROUND_FILE contains the full path, ie. +# includes CMAKE_SOURCE_DIR or so. + +if (DEFINED MAC_INSTALLER_BACKGROUND_FILE ) + set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "1") +else() + set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0") +endif() + +find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} COMPONENTS Core REQUIRED) +configure_file(create_mac.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh) +configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj) +configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh) +configure_file(post_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/post_install.sh) diff --git a/admin/osx/DMGBackground.png b/admin/osx/DMGBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..873635e7f260f6d17e6ade6efe6ff40af827df93 GIT binary patch literal 18463 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 bOZWHTaH&#j3k7hL4@6!@NxDSRFzCMlII0Iz literal 0 HcmV?d00001 diff --git a/admin/osx/DS_Store.in b/admin/osx/DS_Store.in new file mode 100644 index 0000000000000000000000000000000000000000..66fae955203d0ef28a3e326f3d4dfd6e4814c2e6 GIT binary patch literal 15364 zcmeHM-)|H}9RE&xz|}k2Z3~JDxUobr{c(F&N_#B{?e#z!gC$-qB^1iu?)Gle>+X5C zrC_a|F(Li|LJZ--7b7uh`T&u{S07Ax(H9Ly;)_w<#8*Sq?{{bR?pkQ=lQCo_nfZQZ z=KG!Rd_TK0vvUUkEVW?90aO48V%hXl0-y|Gv!4*- zJ;1k7g&Y>L!liGDWAfVr6Q)dDF&H<;ewEZw4hvb~lA8nL=D>t!CT=Lq_l|a|uMTXO zOIb<=Bm)mKKzH{D^gtGLFjn2)&Fo^im@T+j)L6+D3wGJlwC`C%V`$6PZQ-V-aCG{l z?U?Rj%3W~G^65<8UCh{~mDNjUeC+AoLOG?E{GJoKm&YC-Pq=OY@wCuBX`5btM%lHr z6h9d6Qn6U>QkMn@_i260%T3{MQ!7h^cRt^9=-7n**7Do$RCpjvYzDBM*Q@1wh}Mb9 zHqMKv8pngEepXtlaXk@WPwd-nJH}JnMqTyV}-_^O|Lztu;+t zETZ|2T7&QF<&tGNr*kFS9G{&nTi#S1J~i$8@~rtWXV#rj+Q{E{(X(BrJZY86C{O97 zlJ4ZJ)WuapkIm~jYouW7Wq-I#Q8#QS*KznhXR)bc_(T=$=cwALKoxfIE`TZsD{R7X z9c#RmU7}7bakCB|*9~<%qfQ0-b@FznvvjNz8zNV`nrp%L6rEh1)+S-(YV7vP4}S*Q ze`5k@QiHmXk)E0#I`r!8F5OXnxdM!xdP>-^_B*0&VF3xW5`z7>5j=gHzbn z>AQ+?Pcd{9tMe0E;|AJ+#Q=8VT(?v79mB7Pu*2{Y9LC`%ArEiBCAbWq!7cb2zJp)k zKHJ9H*>1Lny}({%8cVVvmS)G0JlR8mWH z_i9)qd;8PfqlwWYM@J5hYW@9v!5rQt8yxBP!(3w3Pc%0g3tudsuSOyr=X`_OQJV31 zQcIc#2FwA?7|3e9daq{0vsum569){V&(Pwg89&%Rq={4oyq?g840paqFBS_HmEC3C zF|+Q4o|2`T-HRpLvjU6wkY@QtiJ*mQ*`%JB9f~c`n%v|MmXrIv5fN5R3 zf}6|WBPse?;2*N<>dw3Aw7K9JxQ%}NX@28z=UsEty2bp(x;fzVVdD*Sb*yj{_4i}G zUX9g-MdZXlmgsK^6E|L+SX*QFD%yOp8M{>+HUE@En<$R_NFQ|^t=ybM%?)*{9Q~{A zDvp}*)saauAQ_MhNCqSW8!$j0aF|s3UOlq@|Np*{EF=Sxfya{p7D{K*DU7Xl<5(Ri z-tIufd=4`u(yMUkn_xjI)Q*==zd|=r`tYVUjU*++!$MZL#1>5d`JVxf$$wi4?&LIU z!uv4OY}1%20(t)@7I>mZCGY>7i^t;rFP^Iuk^#wpWI!??8ITM}1|$QL0m*=5Kr$d1 RkPJu$Bm " && exit + +# the path of installation must be given as parameter +if [ -z "$1" ]; then + echo "ERROR: Provide the path to CMAKE_INSTALL_DIR to this script as first parameter." + exit 1 +fi + +if [ -z "$2" ]; then + echo "ERROR: Provide the path to build directory as second parameter." + exit 1 +fi + +install_path="$1" +build_path="$2" +identity="$3" +prjfile=$build_path/admin/osx/macosx.pkgproj + +# The name of the installer package +installer="@APPLICATION_SHORTNAME@-qt@Qt5Core_VERSION@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@" +installer_file="$installer.pkg" +installer_file_tar="$installer.pkg.tar" +installer_file_tar_bz2="$installer.pkg.tar.bz2" +installer_file_tbz="$installer.pkg.tbz" + +# set the installer name to the copied prj config file +/usr/local/bin/packagesutil --file $prjfile set project name "$installer" + +# The command line tool of the "Packages" tool, see link above. +pkgbuild=/usr/local/bin/packagesbuild + +$pkgbuild -F $install_path $prjfile +rc=$? + +if [ $rc == 0 ]; then + echo "Successfully created $installer_file" +else + echo "Failed to create $installer_file" + exit 3 +fi + +# Sign the finished package if desired. +if [ ! -z "$identity" ]; then + echo "Will try to sign the installer" + pushd $install_path + productsign --timestamp --sign "$identity" "$installer_file" "$installer_file.new" + mv "$installer_file".new "$installer_file" + popd +else + echo "No certificate given, will not sign the pkg" +fi + +# FIXME: OEMs? +# they will need to do their own signing.. + + +# Sparkle wants a tbz, it cannot install raw pkg +cd $install_path +tar cf "$installer_file_tar" "$installer_file" +bzip2 -9 "$installer_file_tar" +mv "$installer_file_tar_bz2" "$installer_file_tbz" +rc=$? +if [ $rc == 0 ]; then + echo "Successfully created $installer_file" +else + echo "Failed to create $installer_file" + exit 3 +fi diff --git a/admin/osx/deny_autoupdate_com.owncloud.desktopclient.plist b/admin/osx/deny_autoupdate_com.owncloud.desktopclient.plist new file mode 100644 index 0000000000000000000000000000000000000000..8339abffb0f93fd6e6b4ead616795ed778ace6b3 GIT binary patch literal 65 zcmYc)$jK}&F)+Bu$P_QYU!0v;5L%FuSd!|Tk(!*%$-ynl00xYV5SoD*O2a5Q01oO3 Al>h($ literal 0 HcmV?d00001 diff --git a/admin/osx/gen_sym_files.py b/admin/osx/gen_sym_files.py new file mode 100755 index 000000000..beaece4dc --- /dev/null +++ b/admin/osx/gen_sym_files.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +import logging, os, re, subprocess, sys +import os.path +import pdb, pprint + +if len(sys.argv) < 4: + print("Usage:") + print("\tgen_sym_files.py ") + print("") + print("Symbols will be created in './symbols'") + sys.exit(1) + +dump_symsPath = sys.argv[1] +bundlePath = sys.argv[2] +outPath = sys.argv[3] +macOsDir = os.path.join(bundlePath, 'Contents', 'MacOS') +pluginsDir = os.path.join(bundlePath, 'Contents', 'PlugIns') + +def resolvePath(input): + resolved = re.sub(r'@\w+', macOsDir, input) + return os.path.normpath(resolved) + +def extractDeps(macho): + deps = [macho] + otool = subprocess.Popen(['otool', '-L', macho], stdout=subprocess.PIPE) + for l in otool.communicate()[0].splitlines(): + if 'is not an object file' in l: + return [] + m = re.search(r'@[^\s]+', l) + if m: + path = resolvePath(m.group(0)) + if not os.path.exists(path): + logging.warning("Non-existent file found in dependencies, ignoring: [%s]", path) + continue + deps.append(path) + return deps + +def findDeps(): + deps = [] + for f in os.listdir(macOsDir): + path = os.path.join(macOsDir, f) + if not os.path.islink(path): + deps += extractDeps(path) + for root, dirs, files in os.walk(pluginsDir): + for f in files: + path = os.path.join(root, f) + deps += extractDeps(path) + return sorted(set(deps)) + +def dumpSyms(deps): + for dep in deps: + print("Generating symbols for [%s]" % dep) + with open('temp.sym', 'w') as temp: + subprocess.check_call([dump_symsPath, dep], stdout=temp) + with open('temp.sym', 'r') as temp: + header = temp.readline() + fields = header.split() + key, name = fields[3:5] + destDir = '%s/%s/%s/' % (outPath, name, key) + destPath = destDir + name + '.sym' + if os.path.exists(destPath): + logging.warning("Symbols already exist: [%s]", destPath) + continue + if not os.path.exists(destDir): + os.makedirs(destDir) + os.rename('temp.sym', destPath) + +def strip(deps): + for dep in deps: + print("Stripping symbols off [%s]" % dep) + subprocess.check_call(['strip', '-S', dep]) + +print('=== Generating symbols for [%s] in [%s]' % (bundlePath, outPath)) +deps = findDeps() +dumpSyms(deps) +strip(deps) diff --git a/admin/osx/installer-background.png b/admin/osx/installer-background.png new file mode 100644 index 0000000000000000000000000000000000000000..ca273880b37aa34ff8fca33a53677cc779b6fa37 GIT binary patch literal 4028 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 B2BiQ1 literal 0 HcmV?d00001 diff --git a/admin/osx/installer-background.svg b/admin/osx/installer-background.svg new file mode 100644 index 000000000..73af25b6d --- /dev/null +++ b/admin/osx/installer-background.svg @@ -0,0 +1,2 @@ + + diff --git a/admin/osx/installer-background_2x.png b/admin/osx/installer-background_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0117c4974989a1e4286f0490ce98e18e0f2d33b9 GIT binary patch literal 7190 zcmeI0_fr!N0z?s{1Q6*}X^IfKbcE1bD1jhVl->duq@xgu zG^x@NK?FhZ^3DAZ?yvVdvokw;X3xyoXJ+3y^CrMd^{Bz@U;qF>ZJ@7h0RRvo0RUh+ zIp`)sA;!xB0Du56W4O-E@!x;rzXblj5+GBhB>&GJcxGX02>=p-h)GDv$SJ^-RMa%I zbo93v7@3$^SlQS)IJqF)JiL6j`2_@ppu!@ecf`acB&DS9%E-#eD<~={tEj5oQ`gYc z($>+{(>E|QGBznub+Rw(`SJ} z!6Bi~Uxd93k3dF7MaRU(#lK2OOiE5kO-p~Bk%`L6&dJToFDNW3Ey?fu>(%RPE(b?7A(~IltANYVD{5Ui`GCDRsG5P89)HGpcc5eR5!s62M z%GcGk^^MJ~Z`(V&d;156N8gWsoSgnV`*nWt`||3~-|KzyFR}mt%bNo4c_GmV8x4v zpIm8<$Bk`Y+o)A)?cQ_f`38N(nSbhFY~_iQh7`_}7kmrb-c!(~>Bsm!@s-Mq_wmo^ zFIi@cAG+>5s4?6KRS@$jT1#-|Z8CfN=-NZ2M6W+_!kXJa%=dLo}vb&hpTgx44 zoAc?}FVC&%e3xy*)XH0$jxwcQ#ov->p>c~bk0=5E7_*Krt59Ul>7rkMT_Dm>VI4JV zrm5l|v4JFIKQ<>??;&HKhC4^7F`H)2bAa5Ms_$`82M;rJyLT8k2&@UVS8;huUe^#W z-ENh`h>`XHJ`S;w%zfhX_KniwKReZ2aPh{xTLp*uQyt#@_q}|LsJ&k7P-b1~p_xTQ z1G?Fxh@x{idcf^nr~@7$p@?~`J{s7;+>+7yWGa00pCL{+Ai$ub^y+?Nnu=mx{lj0u zoI$UhpVnfuZ0yJjhV06BvO^pCASW}1N>x*D8>0*1N#c9K0$x0=X{80s-DDdE2isZC z9t@W|$|+Xz+0CBwcH-rP22=vV7%rWL z@RBKo)A852K^$XzR>_rS%=c(Bhd@tvb7o2gI8R0bE(I?rE7OA?eAZG#kp2!3>xRqF zfQHV2s`nKWh74>jYaW2YRDBB>*D+> zCaf)c-@sH`1L828vMC>9cJy$}g#UuoF>}<_kJ9=~reDA{bzQFMCnUze^kDRGc+7|n zk|6&r_3?4Sen;m%4q7jky3xDL&mo{dK@+L>I^+43U-b(k1FmXb*@~m;TOtpI1FgXK zHq*Cx^6|b33Xo8aIh-|9~E8wzSr?}CQp%!6uVr1YMn#V@wdM7$gKUmUYU%V zJ;c6BE)Y>7MpRFZ^9XH(z!SZ@uciLzfY<{6XTp zi4UC96J|7NHowF^v-RPCPG3y}vgYM0#g_W+#?maFE?@#-_vu|#-WAh4;-V1XYj7|LjGBIq zqxPvRpH&H|C7U7q86*KJ?J7b)ttPyLdws$1O4?oVDY-6d9rBj1jZ=c286Vr~*Zd6u zay9gMwt%h`%&@Bwnr!zWkATxrOsWZc?;@)_9M!7l2@Z@Zu5-4xFi#JHb_Og zshzA}6+Qdw2M)gc=b7f`B=1t)zhu+9uL^kZcm3qKS}sCzg@eer(tjadVj2AZDk-6{ zT#q@sUrkVU-6CV?HarWW0ms`EKh3e|Zs?|?Q|(B$*<7I~-S|mk(fqTMZxuP6ZQkyP z?KusG70d_?NPb?dez;Ia?-#edE(@>a0nQK(?(S_yD1mj^w3-w3W{^)cNnK%e?GX4V zlOn;()0cJg@x844Y=A4CKL=L5Z%+MI!lHNe!Y{YKHBO{%7r5PAY>*YeUOJ-WTSfn% zIhq%O))b(OgzijrB#SWG(qtC4B^ef`fcG=BqFsWb1T(Aq ziy0iVpBrKO_vqlT1{L*Oogi|HeC^p@G;5# zm}yLM%^jQA)|5ObdPu1eHW3Y0hz55tk=~}JwOBdCA~k>=>c3smwM;ch?v!_JcS{li z!xN2?`swYM(V{3jfE0hGzqYI8$~y?_ev>qpC(2Z;)Cg5fEzH#E=O~58;2v)?TiSRq z(tO_x>(F%!9tMC66uMRz&w0jzOsl82`JW9{ByB>3Sb2;lagO6v@83!;>ufP*vnLF= zbtKg{RplX&W2%t&&#_a2{b46YZoYk`GmF|e)?A{jJkvCDr~jY_vb44c{q&}wn01)u z_UFJS@f4&(F7yhhR1LAtn4d4w`^E94$r#FRJ~p1OgQZ=%)}l_UG{y2zPhpxhkB+JF z3}671raoLs=Wj2?5}y~1OW>demzBPi$i6rm!djk_pv9P#Lw^3s&cxi(PtyP16lRK@ zl60tqeVwP@Qdrnee2JeoDdUfrKe|zep!-j^_;z?JknxOeX{!(*kn+}h`*1n~cp}B= zCLmyP-tPh_s~FQiXwXB7GppE1<4!Cado!W#dUkCo+s=j^>{r$8nf2MsH$>!h9q&oN zV8d_yN*2mu@AQYSl#RX=VdD{6{aW@^*o}V)+gTE|u;Gxg^E{d#L{%Ic(HDSMiESpYQlCjOprSuP2r%_i}WUSx6X`$5A71TqZR zOF524P09JS4soGwd5K@s=Y-E0knY@r^eSdL6-O=#n2#-A+&`qU;TL-#sV@Fw)vCeL zP*<#NMbpqa)*+?xzOE7JkQ!ihv=qhb*Si5iO%bWv0_!XY`qDUA`_GZu`E5k z02^+3t^%MbdNi=>SR^g+f)-FwOegsXH` z)p@x{U*;NQNtaVo`RPILNaw|ghHTgRaoXtT7+hf|U?31Du%J*glVtm6Qs3(f@mvdC zo!LAVgz25yrrg1k2tO*3O8f`DH=k$P07CuZR#Pw+iB?@aK4qi|?90xw>fdN|VbAXF zs0TM4XpKTy!513=Iel^)?r6d_1a33gj0%3|2&9SgzU5xr>TJ%`^AUtgiDr3K$R?#I^5V zT_)74bVg_7voox2H%`Bl8F&vP56zGAkrc!gAgVUpV|@8|@u!fjFfU_d9YSal!p>8p zxT)Pxo~u&A3-pPrTPX|gJLRo*rpN!3*3@9XvJQ1bIvvUL<30v>F>7)xJ{)aItDe$>GT*z)gY$0u zqD;V|#R9;ODXpckZ>$qiwQ;`C>ksK$$9f5pD*6=ZTJ8a=FF-bXJm zg7s%02+%{HyUiCgZ@Nu^)(fColF_$1T4AzR}CqMkd9=*;eo4umv_`R;@1kBK)RDEcH?x@Oq(+J( z>h-o1FK(sL3RR-S^ihlCYZ~f@tTFj9WWI*%j2*;8YB@xyORPZst0V1smXM}>Q8(k% z*H?gdDvh&L9xX#4e+di2D0*O%nAg^Dg^!iy0tHZv8wo4&bgcPB@G(;zI;lgWgyV=W z1ifTYmnP@x1Xh!rI#>~$_Rbj_wI2t+9bHB41{Fp6$3D{@6?Swj!=}uas{P1#@G_!KF)(MR5(l)*8+NH94&{)V?oMVB-H2@c_Bl-8l9_2KM_RA6wh#7>Wwca|E8q%wtTYQcw$DqYZbP zQ^5z6@?yB*#?d;NnGvIIY@_9No^(f2VwP;Ii3*2Xz4rhgjK27^SISkH>^=u|fvtKu zCPkS-FMx1+5j(<{%Yq1^y3>?ixp;y5!K+XaG>~IaYD7hqK7dHe+#&r^lA^$S>*_R+ z^-s7+*1|15*44sWBl8d<&oK2?@}vB_?jNWPTmzL$Pj?OGmQ;eiWe14JGe!Z6RgyF> z2bjJ8qF(3eP`YS?NfkI+VMDX9hwCrFp&Q{gI~wGq^OR!3TT1h#T1d@H!o1P`CV`&H zPYNl^*fdQhYFwIL=C)+8&#xtks|OULQM`?PZ#BSqq}rG%={#8yP$3XdBrMP^ct_Ic zr|ht#%{QMR5>^EW;6|qeNREPeF~sWt?SsnuQ{^O}Fs5EMGhqP=Kjp8?hSpII)TQ@* z;%t%a)ISPL8SgUr1e4*HVjN<_&5~*&zUZnLg_yjUbn6jmlZ zV(Kh#0y`g9J#tUb<6%LV8~r&9AF*a9n#u5Z1w*wgk0AkxPlCvZE)7;FbXm{9&c2OG}I` zvUL@vYdO0z>lgp30lNQ`v;T+Avr?ROI_0r9r^UN~5gRKGpVcBw$8LY<+^5*Mo0nkB z72dZ(4+_{NOSW~uk7Bi6WY^z?1OR<%(+1o)(2c)eORli$Z41SZSB!?S^RcX&iTORu z6!s2MpgNbt)Sa(O^09orpRK2L2UlC}AHo%l`en|V93+IdiyU~gew&=dJuB0@rpzo@9UQ)9wkz;_hRSru9(CQ{tiB=)}+@ z@PQlcDWTYm>248`kwa#wq0PaKf)A?^`d29$M!q2 zId8^1iI&R*NvenHq3~Hutc+>6gWGIR@|#Utitg0w$dR8KTU_rl^~C2NWX(I{cxCumVD6c&3A_j9R}!sr|D+l$IZiWkt;_^fmqk0$V{)cO@vb<$O}BF((Pl7 zN33<>B1M);&gx?N$3^E)Xo@VC=%>1@>Z_hd3MWV|TLYDJBDBTD=1?pdOyN_2libvLr%&$D?~2=?>YjkPnZUr%dwJW+W%l9OiUfgDLV zdOr8wSjpGb4my2NzYKT!jfS@AEJ60(x}Usc5e$I={i{;Kyj>KVp=vZDzw2|k(2YNZ z7I7vWIhG}VFqxKdg)=RrG=fb!laa%|;$vvtIgMt);D)NgrPj&QK9{4ia7?u)OZcDb zB#Bf50|U0d>q)-h3c)jJv4rpU6-qY-_MxSI0VU*ZX|5uNLcP5@4?2~5?l?DlK_VXT zF9|dS@388pO5*hL}b{3b3eOMdxu44(J%eHY}V^LRLc1z zM|7!`l>Xt`Y+?z2d({5t(yFN}A{O{Q8EO7WSnx+bJwv7Vip9|1EuX(ZgB8k`#V|6t z(8LGy#|bRD$1_F>r61j^?9!jDxK|bVX~xGnHf97%i}4|JsEnQNef6@@!nK6t;=|w8 ixKRMvyb<@z?}2y&u6u&J+co}U*&FDXYS(KbqW%ZzN7}pq literal 0 HcmV?d00001 diff --git a/admin/osx/mac-crafter/Package.swift b/admin/osx/mac-crafter/Package.swift new file mode 100644 index 000000000..de4b7465f --- /dev/null +++ b/admin/osx/mac-crafter/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "mac-crafter", + platforms: [ + .macOS(.v11), + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-argument-parser", from: "1.4.0") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .executableTarget( + name: "mac-crafter", + dependencies: [.product(name: "ArgumentParser", package: "swift-argument-parser")] + ), + ] +) diff --git a/admin/osx/mac-crafter/README.md b/admin/osx/mac-crafter/README.md new file mode 100644 index 000000000..db31b4bd2 --- /dev/null +++ b/admin/osx/mac-crafter/README.md @@ -0,0 +1,63 @@ +# mac-crafter + +A tool to easily build a fully-functional Nextcloud Desktop Client for macOS. + +It will create the application bundle with the option to sign it, which is required by Apple when running and debugging the file provider module. + +## System requirements + +- Mac OS > 11 +- XCode +- Python + +## Step by step usage + +1. Clone the desktop client in your mac OS +``` +https://github.com/nextcloud/desktop.git +``` + +2. Build the desktop client: +``` +cd admin/osx/mac-crafter +swift run mac-crafter +``` + +3. Sign the application bundle by adding the following parameter: +`-c ` +The whole command will look like this: +``` +swift run mac-crafter -c "Apple Development: " +``` + +> [!NOTE] +> The resulting app bundle will be placed under the `product` folder in the mac-crafter folder. + +> [!TIP] +> Check [Apple's oficial documentation about code signing](https://developer.apple.com/documentation/xcode/using-the-latest-code-signature-format). + +### Extra options + +- Build the file provider module with this option: +``` +--build-file-provider-module +``` + +- Disable the auto-updater: +``` +--disable-autoupdater +``` + +- Manually set the architecture you are building for: + +``` +--arch +``` + +### How to build the app bundle for arm and intel + +To achieve this we are using a Python script called `make_universal.py` which bundles together the arm64 and Intel builds into one universal app bundle. This script can be found under `admin/osx`. You can invoke it like so: + +``` +python admin/osx/make_universal.py +``` diff --git a/admin/osx/mac-crafter/Sources/Utils/Codesign.swift b/admin/osx/mac-crafter/Sources/Utils/Codesign.swift new file mode 100644 index 000000000..1f43d3e49 --- /dev/null +++ b/admin/osx/mac-crafter/Sources/Utils/Codesign.swift @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import Foundation + +fileprivate let defaultCodesignOptions = "--timestamp --force --preserve-metadata=entitlements --verbose=4 --options runtime" + +enum CodeSigningError: Error { + case failedToCodeSign(String) +} + +enum AppBundleSigningError: Error { + case doesNotExist(String) + case couldNotEnumerate(String) +} + +func isLibrary(_ path: String) -> Bool { + path.hasSuffix(".dylib") || path.hasSuffix(".framework") +} + +func isAppExtension(_ path: String) -> Bool { + path.hasSuffix(".appex") +} + +func isExecutable(_ path: String) throws -> Bool { + let outPipe = Pipe() + let errPipe = Pipe() + let task = Process() + task.standardOutput = outPipe + task.standardError = errPipe + + let command = "file \"\(path)\"" + guard run("/bin/zsh", ["-c", command], task: task) == 0 else { + throw CodeSigningError.failedToCodeSign("Failed to determine if \(path) is an executable.") + } + + let outputFileHandle = outPipe.fileHandleForReading + let outputData = outputFileHandle.readDataToEndOfFile() + try outputFileHandle.close() + let output = String(data: outputData, encoding: .utf8) ?? "" + return output.contains("Mach-O 64-bit executable") +} + +func codesign(identity: String, path: String, options: String = defaultCodesignOptions) throws { + print("Code-signing \(path)...") + let command = "codesign -s \"\(identity)\" \(options) \"\(path)\"" + guard shell(command) == 0 else { + throw CodeSigningError.failedToCodeSign("Failed to code-sign \(path).") + } +} + +func recursivelyCodesign( + path: String, + identity: String, + options: String = defaultCodesignOptions, + skip: [String] = [] +) throws { + let fm = FileManager.default + guard fm.fileExists(atPath: path) else { + throw AppBundleSigningError.doesNotExist("Item at \(path) does not exist.") + } + + guard let pathEnumerator = fm.enumerator(atPath: path) else { + throw AppBundleSigningError.couldNotEnumerate( + "Failed to enumerate directory at \(path)." + ) + } + + for case let enumeratedItem as String in pathEnumerator { + let enumeratedItemPath = "\(path)/\(enumeratedItem)" + guard !skip.contains(enumeratedItemPath) else { + print("Skipping \(enumeratedItemPath)...") + continue + } + let isExecutableFile = try isExecutable(enumeratedItemPath) + guard isLibrary(enumeratedItem) || isAppExtension(enumeratedItem) || isExecutableFile else { + continue + } + try codesign(identity: identity, path: enumeratedItemPath, options: options) + } +} + +func saveCodesignEntitlements(target: String, path: String) throws { + let command = "codesign -d --entitlements \"\(path)\" --xml \"\(target)\"" + guard shell(command) == 0 else { + throw CodeSigningError.failedToCodeSign("Failed to save entitlements for \(target).") + } +} + +func codesignClientAppBundle( + at clientAppDir: String, withCodeSignIdentity codeSignIdentity: String +) throws { + print("Code-signing Nextcloud Desktop Client libraries, frameworks and plugins...") + + let clientContentsDir = "\(clientAppDir)/Contents" + let frameworksPath = "\(clientContentsDir)/Frameworks" + let pluginsPath = "\(clientContentsDir)/PlugIns" + + try recursivelyCodesign(path: frameworksPath, identity: codeSignIdentity) + try recursivelyCodesign(path: pluginsPath, identity: codeSignIdentity) + try recursivelyCodesign(path: "\(clientContentsDir)/Resources", identity: codeSignIdentity) + + print("Code-signing QtWebEngineProcess...") + let qtWebEngineProcessPath = + "\(frameworksPath)/QtWebEngineCore.framework/Versions/A/Helpers/QtWebEngineProcess.app" + try codesign(identity: codeSignIdentity, + path: qtWebEngineProcessPath, + options: "--timestamp --force --verbose=4 --options runtime --deep --entitlements \"\(qtWebEngineProcessPath)/Contents/Resources/QtWebEngineProcess.entitlements\"") + + print("Code-signing QtWebEngine...") + try codesign(identity: codeSignIdentity, path: "\(frameworksPath)/QtWebEngineCore.framework") + + // Time to fix notarisation issues. + // Multiple components of the app will now have the get-task-allow entitlements. + // We need to strip these out manually. + + let sparkleFrameworkPath = "\(frameworksPath)/Sparkle.framework" + if FileManager.default.fileExists(atPath: sparkleFrameworkPath) { + print("Code-signing Sparkle...") + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/XPCServices/Installer.xpc", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/XPCServices/Downloader.xpc", + options: "-f -o runtime --preserve-metadata=entitlements" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/Autoupdate", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/Updater.app", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, path: sparkleFrameworkPath, options: "-f -o runtime" + ) + } else { + print("Build does not have Sparkle, skipping.") + } + + print("Code-signing app extensions (removing get-task-allow entitlements)...") + let fm = FileManager.default + let appExtensionPaths = + try fm.contentsOfDirectory(atPath: pluginsPath).filter(isAppExtension) + for appExtension in appExtensionPaths { + let appExtensionPath = "\(pluginsPath)/\(appExtension)" + let tmpEntitlementXmlPath = + fm.temporaryDirectory.appendingPathComponent(UUID().uuidString).path.appending(".xml") + try saveCodesignEntitlements(target: appExtensionPath, path: tmpEntitlementXmlPath) + // Strip the get-task-allow entitlement from the XML entitlements file + let xmlEntitlements = try String(contentsOfFile: tmpEntitlementXmlPath) + let entitlementKeyValuePair = "com.apple.security.get-task-allow" + let strippedEntitlements = + xmlEntitlements.replacingOccurrences(of: entitlementKeyValuePair, with: "") + try strippedEntitlements.write(toFile: tmpEntitlementXmlPath, + atomically: true, + encoding: .utf8) + try codesign(identity: codeSignIdentity, + path: appExtensionPath, + options: "--timestamp --force --verbose=4 --options runtime --deep --entitlements \"\(tmpEntitlementXmlPath)\"") + } + + // Now we do the final codesign bit + let binariesDir = "\(clientContentsDir)/MacOS" + print("Code-signing Nextcloud Desktop Client binaries...") + + guard let appName = clientAppDir.components(separatedBy: "/").last, clientAppDir.hasSuffix(".app") else { + throw AppBundleSigningError.couldNotEnumerate("Failed to determine main executable name.") + } + + // Sign the main executable last + let mainExecutableName = String(appName.dropLast(".app".count)) + let mainExecutablePath = "\(binariesDir)/\(mainExecutableName)" + try recursivelyCodesign(path: binariesDir, identity: codeSignIdentity, skip: [mainExecutablePath]) + try codesign(identity: codeSignIdentity, path: mainExecutablePath) +} diff --git a/admin/osx/mac-crafter/Sources/Utils/Craft.swift b/admin/osx/mac-crafter/Sources/Utils/Craft.swift new file mode 100644 index 000000000..738933f0e --- /dev/null +++ b/admin/osx/mac-crafter/Sources/Utils/Craft.swift @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +func archToCraftTarget(_ arch: String) -> String { + return arch == "arm64" ? "macos-clang-arm64" : "macos-64-clang" +} diff --git a/admin/osx/mac-crafter/Sources/Utils/Install.swift b/admin/osx/mac-crafter/Sources/Utils/Install.swift new file mode 100644 index 000000000..b83171744 --- /dev/null +++ b/admin/osx/mac-crafter/Sources/Utils/Install.swift @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import Foundation + +enum InstallError: Error { + case failedToInstall(String) +} + +func installIfMissing( + _ command: String, + _ installCommand: String, + installCommandEnv: [String: String]? = nil +) throws { + if commandExists(command) { + print("\(command) is installed.") + } else { + print("\(command) is missing. Installing...") + guard shell(installCommand, env: installCommandEnv) == 0 else { + throw InstallError.failedToInstall("Failed to install \(command).") + } + print("\(command) installed.") + } +} diff --git a/admin/osx/mac-crafter/Sources/Utils/Packaging.swift b/admin/osx/mac-crafter/Sources/Utils/Packaging.swift new file mode 100644 index 000000000..836f68a82 --- /dev/null +++ b/admin/osx/mac-crafter/Sources/Utils/Packaging.swift @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import Foundation + +enum PackagingError: Error { + case projectNameSettingError(String) + case packageBuildError(String) + case packageSigningError(String) + case packageNotarisationError(String) + case packageSparkleBuildError(String) + case packageSparkleSignError(String) +} + +/// NOTE: Requires Packages utility. http://s.sudre.free.fr/Software/Packages/about.html +fileprivate func buildPackage(appName: String, buildWorkPath: String, productPath: String) throws -> String { + let packageFile = "\(appName).pkg" + let pkgprojPath = "\(buildWorkPath)/admin/osx/macosx.pkgproj" + + guard shell("packagesutil --file \(pkgprojPath) set project name \(appName)") == 0 else { + throw PackagingError.projectNameSettingError("Could not set project name in pkgproj!") + } + guard shell("packagesbuild -v --build-folder \(productPath) -F \(productPath) \(pkgprojPath)") == 0 else { + throw PackagingError.packageBuildError("Error building pkg file!") + } + return "\(productPath)/\(packageFile)" +} + +fileprivate func signPackage(packagePath: String, packageSigningId: String) throws { + let packagePathNew = "\(packagePath).new" + guard shell("productsign --timestamp --sign '\(packageSigningId)' \(packagePath) \(packagePathNew)") == 0 else { + throw PackagingError.packageSigningError("Could not sign pkg file!") + } + let fm = FileManager.default + try fm.removeItem(atPath: packagePath) + try fm.moveItem(atPath: packagePathNew, toPath: packagePath) +} + +fileprivate func notarisePackage( + packagePath: String, appleId: String, applePassword: String, appleTeamId: String +) throws { + guard shell("xcrun notarytool submit \(packagePath) --apple-id \(appleId) --password \(applePassword) --team-id \(appleTeamId) --wait") == 0 else { + throw PackagingError.packageNotarisationError("Failure when notarising package!") + } + guard shell("xcrun stapler staple \(packagePath)") == 0 else { + throw PackagingError.packageNotarisationError("Could not staple notarisation on package!") + } +} + +fileprivate func buildSparklePackage(packagePath: String, buildPath: String) throws -> String { + let sparkleTbzPath = "\(packagePath).tbz" + guard shell("tar cf \(sparkleTbzPath) \(packagePath)") == 0 else { + throw PackagingError.packageSparkleBuildError("Could not create Sparkle package tbz!") + } + return sparkleTbzPath +} + +fileprivate func signSparklePackage(sparkleTbzPath: String, buildPath: String, signKey: String) throws { + guard shell("\(buildPath)/bin/sign_update -s \(signKey) \(sparkleTbzPath)") == 0 else { + throw PackagingError.packageSparkleSignError("Could not sign Sparkle package tbz!") + } +} + +func packageAppBundle( + productPath: String, + buildPath: String, + craftTarget: String, + craftBlueprintName: String, + appName: String, + packageSigningId: String?, + appleId: String?, + applePassword: String?, + appleTeamId: String?, + sparklePackageSignKey: String? +) throws { + print("Creating pkg file for client…") + let buildWorkPath = "\(buildPath)/\(craftTarget)/build/\(craftBlueprintName)/work/build" + let packagePath = try buildPackage( + appName: appName, + buildWorkPath: buildWorkPath, + productPath: productPath + ) + + if let packageSigningId { + print("Signing pkg with \(packageSigningId)…") + try signPackage(packagePath: packagePath, packageSigningId: packageSigningId) + + if let appleId, let applePassword, let appleTeamId { + print("Notarising pkg with Apple ID \(appleId)…") + try notarisePackage( + packagePath: packagePath, + appleId: appleId, + applePassword: applePassword, + appleTeamId: appleTeamId + ) + } + } + + print("Creating Sparkle TBZ file…") + let sparklePackagePath = + try buildSparklePackage(packagePath: packagePath, buildPath: buildPath) + + if let sparklePackageSignKey { + print("Signing Sparkle TBZ file…") + try signSparklePackage( + sparkleTbzPath: sparklePackagePath, + buildPath: buildPath, + signKey: sparklePackageSignKey + ) + } +} diff --git a/admin/osx/mac-crafter/Sources/Utils/Shell.swift b/admin/osx/mac-crafter/Sources/Utils/Shell.swift new file mode 100644 index 000000000..8c1570c5e --- /dev/null +++ b/admin/osx/mac-crafter/Sources/Utils/Shell.swift @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import Foundation + +weak var globalTaskRef: Process? + +@discardableResult +func run( + _ launchPath: String, + _ args: [String], + env: [String: String]? = nil, + quiet: Bool = false, + task: Process = Process() +) -> Int32 { + globalTaskRef = task + signal(SIGINT) { _ in + globalTaskRef?.terminate() // Send terminate signal to the task + exit(0) // Exit the script after cleanup + } + + task.launchPath = launchPath + task.arguments = args + + if let env, + let combinedEnv = task.environment?.merging(env, uniquingKeysWith: { (_, new) in new }) + { + task.environment = combinedEnv + } + + if quiet { + task.standardOutput = nil + task.standardError = nil + } + + task.launch() + task.waitUntilExit() + return task.terminationStatus +} + +func run( + _ launchPath: String, + _ args: String..., + env: [String: String]? = nil, + quiet: Bool = false +) -> Int32 { + return run(launchPath, args, env: env, quiet: quiet) +} + +@discardableResult +func shell(_ commands: String..., env: [String: String]? = nil, quiet: Bool = false) -> Int32 { + return run("/bin/zsh", ["-c"] + commands, env: env, quiet: quiet) +} + +func commandExists(_ command: String) -> Bool { + return run("/usr/bin/type", command, quiet: true) == 0 +} diff --git a/admin/osx/mac-crafter/Sources/main.swift b/admin/osx/mac-crafter/Sources/main.swift new file mode 100644 index 000000000..f7d723b80 --- /dev/null +++ b/admin/osx/mac-crafter/Sources/main.swift @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2024 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import ArgumentParser +import Foundation + +struct Build: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Client building script") + + enum MacCrafterError: Error { + case failedEnumeration(String) + case environmentError(String) + case gitError(String) + case craftError(String) + } + + @Argument(help: "Path to the root directory of the Nextcloud Desktop Client git repository.") + var repoRootDir = "\(FileManager.default.currentDirectoryPath)/../../.." + + @Option(name: [.short, .long], help: "Code signing identity for desktop client and libs.") + var codeSignIdentity: String? + + @Option(name: [.short, .long], help: "Path for build files to be written.") + var buildPath = "\(FileManager.default.currentDirectoryPath)/build" + + @Option(name: [.short, .long], help: "Path for the final product to be put.") + var productPath = "\(FileManager.default.currentDirectoryPath)/product" + + @Option(name: [.short, .long], help: "Architecture.") + var arch = "arm64" + + @Option(name: [.long], help: "Brew installation script URL.") + var brewInstallShUrl = "https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" + + @Option(name: [.long], help: "CraftMaster git url.") + var craftMasterGitUrl = "https://invent.kde.org/packaging/craftmaster.git" + + @Option(name: [.long], help: "Nextcloud Desktop Client craft blueprint git url.") + var clientBlueprintsGitUrl = "https://github.com/nextcloud/desktop-client-blueprints.git" + + @Option(name: [.long], help: "Nextcloud Desktop Client craft blueprint name.") + var craftBlueprintName = "nextcloud-client" + + @Option(name: [.long], help: "Build type (e.g. Release, RelWithDebInfo, MinSizeRel, Debug).") + var buildType = "RelWithDebInfo" + + @Option(name: [.long], help: "The application's branded name.") + var appName = "Nextcloud" + + @Option(name: [.long], help: "Sparkle download URL.") + var sparkleDownloadUrl = + "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" + + @Option(name: [.long], help: "Git clone command; include options such as depth.") + var gitCloneCommand = "git clone --depth=1" + + @Option(name: [.long], help: "Apple ID, used for notarisation.") + var appleId: String? + + @Option(name: [.long], help: "Apple ID password, used for notarisation.") + var applePassword: String? + + @Option(name: [.long], help: "Apple Team ID, used for notarisation.") + var appleTeamId: String? + + @Option(name: [.long], help: "Apple package signing ID.") + var packageSigningId: String? + + @Option(name: [.long], help: "Sparkle package signing key.") + var sparklePackageSignKey: String? + + @Option(name: [.long], help: "Override server url.") + var overrideServerUrl: String? + + @Flag(help: "Reconfigure KDE Craft.") + var reconfigureCraft = false + + @Flag(help: "Run build offline (i.e. do not update craft)") + var offline = false + + @Flag(help: "Build test suite.") + var buildTests = false + + @Flag(name: [.long], help: "Do not build App Bundle.") + var disableAppBundle = false + + @Flag(help: "Build File Provider Module.") + var buildFileProviderModule = false + + @Flag(help: "Build without Sparkle auto-updater.") + var disableAutoUpdater = false + + @Flag(help: "Run a full rebuild.") + var fullRebuild = false + + @Flag(help: "Force override server URL.") + var forceOverrideServerUrl = false + + @Flag(help: "Create an installer package.") + var package = false + + @Flag(help: "Build in developer mode.") + var dev = false + + mutating func run() throws { + print("Configuring build tooling.") + + if codeSignIdentity != nil { + guard commandExists("codesign") else { + throw MacCrafterError.environmentError("codesign not found, cannot proceed.") + } + } + + try installIfMissing("git", "xcode-select --install") + try installIfMissing( + "brew", + "curl -fsSL \(brewInstallShUrl) | /bin/bash", + installCommandEnv: ["NONINTERACTIVE": "1"] + ) + try installIfMissing("inkscape", "brew install inkscape") + try installIfMissing("python3", "brew install pyenv && pyenv install 3.12.4") + + print("Build tooling configured.") + + let fm = FileManager.default + let craftMasterDir = "\(buildPath)/craftmaster" + let craftMasterIni = "\(repoRootDir)/craftmaster.ini" + let craftMasterPy = "\(craftMasterDir)/CraftMaster.py" + let craftTarget = archToCraftTarget(arch) + let craftCommand = + "python3 \(craftMasterPy) --config \(craftMasterIni) --target \(craftTarget) -c" + + if !fm.fileExists(atPath: craftMasterDir) || reconfigureCraft { + print("Configuring KDE Craft.") + + if fm.fileExists(atPath: craftMasterDir) { + print("KDE Craft is already cloned.") + } else { + print("Cloning KDE Craft...") + guard shell("\(gitCloneCommand) \(craftMasterGitUrl) \(craftMasterDir)") == 0 else { + throw MacCrafterError.gitError("Error cloning craftmaster.") + } + } + + print("Configuring Nextcloud Desktop Client blueprints for KDE Craft...") + guard shell("\(craftCommand) --add-blueprint-repository \(clientBlueprintsGitUrl)") == 0 else { + throw MacCrafterError.craftError("Error adding blueprint repository.") + } + + print("Crafting KDE Craft...") + guard shell("\(craftCommand) craft") == 0 else { + throw MacCrafterError.craftError("Error crafting KDE Craft.") + } + + print("Crafting Nextcloud Desktop Client dependencies...") + guard shell("\(craftCommand) --install-deps \(craftBlueprintName)") == 0 else { + throw MacCrafterError.craftError("Error installing dependencies.") + } + } + + var craftOptions = [ + "\(craftBlueprintName).srcDir=\(repoRootDir)", + "\(craftBlueprintName).osxArchs=\(arch)", + "\(craftBlueprintName).buildTests=\(buildTests ? "True" : "False")", + "\(craftBlueprintName).buildMacOSBundle=\(disableAppBundle ? "False" : "True")", + "\(craftBlueprintName).buildFileProviderModule=\(buildFileProviderModule ? "True" : "False")" + ] + + if let overrideServerUrl { + craftOptions.append("\(craftBlueprintName).overrideServerUrl=\(overrideServerUrl)") + craftOptions.append("\(craftBlueprintName).forceOverrideServerUrl=\(forceOverrideServerUrl ? "True" : "False")") + } + + if dev { + appName += "Dev" + craftOptions.append("\(craftBlueprintName).devMode=True") + } + + if !disableAutoUpdater { + print("Configuring Sparkle auto-updater.") + + let fm = FileManager.default + guard fm.fileExists(atPath: "\(buildPath)/Sparkle.tar.xz") || + shell("wget \(sparkleDownloadUrl) -O \(buildPath)/Sparkle.tar.xz") == 0 + else { + throw MacCrafterError.environmentError("Error downloading sparkle.") + } + + guard fm.fileExists(atPath: "\(buildPath)/Sparkle.framework") || + shell("tar -xvf \(buildPath)/Sparkle.tar.xz -C \(buildPath)") == 0 + else { + throw MacCrafterError.environmentError("Error unpacking sparkle.") + } + + craftOptions.append( + "\(craftBlueprintName).sparkleLibPath=\(buildPath)/Sparkle.framework" + ) + } + + print("Crafting \(appName) Desktop Client...") + + let allOptionsString = craftOptions.map({ "--options \"\($0)\"" }).joined(separator: " ") + + let clientBuildDir = "\(buildPath)/\(craftTarget)/build/\(craftBlueprintName)" + if fullRebuild { + do { + try fm.removeItem(atPath: clientBuildDir) + } catch let error { + print("WARNING! Error removing build directory: \(error)") + } + } + + let buildMode = fullRebuild ? "-i" : disableAppBundle ? "compile" : "--compile --install" + let offlineMode = offline ? "--offline" : "" + guard shell( + "\(craftCommand) --buildtype \(buildType) \(buildMode) \(offlineMode) \(allOptionsString) \(craftBlueprintName)" + ) == 0 else { + throw MacCrafterError.craftError("Error crafting Nextcloud Desktop Client.") + } + + let clientAppDir = "\(clientBuildDir)/image-\(buildType)-master/\(appName).app" + if let codeSignIdentity { + print("Code-signing Nextcloud Desktop Client libraries and frameworks...") + try codesignClientAppBundle(at: clientAppDir, withCodeSignIdentity: codeSignIdentity) + } + + print("Placing Nextcloud Desktop Client in \(productPath)...") + if !fm.fileExists(atPath: productPath) { + try fm.createDirectory( + atPath: productPath, withIntermediateDirectories: true, attributes: nil + ) + } + if fm.fileExists(atPath: "\(productPath)/\(appName).app") { + try fm.removeItem(atPath: "\(productPath)/\(appName).app") + } + try fm.copyItem(atPath: clientAppDir, toPath: "\(productPath)/\(appName).app") + + if package { + try packageAppBundle( + productPath: productPath, + buildPath: buildPath, + craftTarget: craftTarget, + craftBlueprintName: craftBlueprintName, + appName: appName, + packageSigningId: packageSigningId, + appleId: appleId, + applePassword: applePassword, + appleTeamId: appleTeamId, + sparklePackageSignKey: sparklePackageSignKey + ) + } + + print("Done!") + } +} + +struct Codesign: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Codesigning script for the client.") + + @Argument(help: "Path to the Nextcloud Desktop Client app bundle.") + var appBundlePath = "\(FileManager.default.currentDirectoryPath)/product/Nextcloud.app" + + @Option(name: [.short, .long], help: "Code signing identity for desktop client and libs.") + var codeSignIdentity: String + + mutating func run() throws { + let absolutePath = appBundlePath.hasPrefix("/") + ? appBundlePath + : "\(FileManager.default.currentDirectoryPath)/\(appBundlePath)" + try codesignClientAppBundle(at: absolutePath, withCodeSignIdentity: codeSignIdentity) + } +} + +struct Package: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Packaging script for the client.") + + @Option(name: [.short, .long], help: "Architecture.") + var arch = "arm64" + + @Option(name: [.short, .long], help: "Path for build files to be written.") + var buildPath = "\(FileManager.default.currentDirectoryPath)/build" + + @Option(name: [.short, .long], help: "Path for the final product to be put.") + var productPath = "\(FileManager.default.currentDirectoryPath)/product" + + @Option(name: [.long], help: "Nextcloud Desktop Client craft blueprint name.") + var craftBlueprintName = "nextcloud-client" + + @Option(name: [.long], help: "The application's branded name.") + var appName = "Nextcloud" + + @Option(name: [.long], help: "Apple ID, used for notarisation.") + var appleId: String? + + @Option(name: [.long], help: "Apple ID password, used for notarisation.") + var applePassword: String? + + @Option(name: [.long], help: "Apple Team ID, used for notarisation.") + var appleTeamId: String? + + @Option(name: [.long], help: "Apple package signing ID.") + var packageSigningId: String? + + @Option(name: [.long], help: "Sparkle package signing key.") + var sparklePackageSignKey: String? + + mutating func run() throws { + try packageAppBundle( + productPath: productPath, + buildPath: buildPath, + craftTarget: archToCraftTarget(arch), + craftBlueprintName: craftBlueprintName, + appName: appName, + packageSigningId: packageSigningId, + appleId: appleId, + applePassword: applePassword, + appleTeamId: appleTeamId, + sparklePackageSignKey: sparklePackageSignKey + ) + } +} + +struct MacCrafter: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "A tool to easily build a fully-functional Nextcloud Desktop Client for macOS.", + subcommands: [Build.self, Codesign.self, Package.self], + defaultSubcommand: Build.self + ) +} + +MacCrafter.main() diff --git a/admin/osx/macosx.pkgproj.cmake b/admin/osx/macosx.pkgproj.cmake new file mode 100644 index 000000000..401326e39 --- /dev/null +++ b/admin/osx/macosx.pkgproj.cmake @@ -0,0 +1,892 @@ + + + + + PACKAGES + + + PACKAGE_FILES + + DEFAULT_INSTALL_LOCATION + / + HIERARCHY + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + @APPLICATION_NAME@.app + PATH_TYPE + 3 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Utilities + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Applications + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + Application Support + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Documentation + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Filesystems + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Frameworks + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Input Methods + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Internet Plug-Ins + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchAgents + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchDaemons + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PreferencePanes + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Preferences + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Printers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PrivilegedHelperTools + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickLook + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickTime + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Screen Savers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Scripts + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Services + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Widgets + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Extensions + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + System + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Shared + PATH_TYPE + 0 + PERMISSIONS + 1023 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Users + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + / + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + PAYLOAD_TYPE + 0 + VERSION + 2 + + PACKAGE_SCRIPTS + + POSTINSTALL_PATH + + PATH + @CMAKE_CURRENT_BINARY_DIR@/post_install.sh + PATH_TYPE + 0 + + PREINSTALL_PATH + + PATH + @CMAKE_CURRENT_BINARY_DIR@/pre_install.sh + PATH_TYPE + 0 + + RESOURCES + + + PACKAGE_SETTINGS + + AUTHENTICATION + 1 + CONCLUSION_ACTION + 0 + IDENTIFIER + @APPLICATION_REV_DOMAIN_INSTALLER@ + NAME + @APPLICATION_NAME_XML_ESCAPED@ + OVERWRITE_PERMISSIONS + + VERSION + @MIRALL_VERSION_FULL@ + + UUID + 7D7219B7-1897-48C3-8533-842BDEC46F71 + + + PROJECT + + PROJECT_COMMENTS + + NOTES + + PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M + IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv + c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l + cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7 + IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250 + ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp + dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u + dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD + b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEzNDMuMTQiPgo8c3R5bGUg + dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5 + Pgo8L2JvZHk+CjwvaHRtbD4K + + + PROJECT_PRESENTATION + + BACKGROUND + + ALIGNMENT + 6 + BACKGROUND_PATH + + PATH + @MAC_INSTALLER_BACKGROUND_FILE@ + PATH_TYPE + 0 + + CUSTOM + @MAC_INSTALLER_DO_CUSTOM_BACKGROUND@ + SCALING + 0 + + INSTALLATION TYPE + + HIERARCHIES + + INSTALLER + + LIST + + + DESCRIPTION + + OPTIONS + + HIDDEN + + STATE + 1 + + PACKAGE_UUID + 7D7219B7-1897-48C3-8533-842BDEC46F71 + TITLE + + TOOLTIP + + TYPE + 0 + UUID + 9647ADC0-BD53-4D7D-A561-73D383AACDE1 + + + REMOVED + + + + INSTALLATION TYPE + 1 + MODE + 1 + + INSTALLATION_STEPS + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewIntroductionController + INSTALLER_PLUGIN + Introduction + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewReadMeController + INSTALLER_PLUGIN + ReadMe + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewLicenseController + INSTALLER_PLUGIN + License + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewDestinationSelectController + INSTALLER_PLUGIN + TargetSelect + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationTypeController + INSTALLER_PLUGIN + PackageSelection + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationController + INSTALLER_PLUGIN + Install + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewSummaryController + INSTALLER_PLUGIN + Summary + LIST_TITLE_KEY + InstallerSectionTitle + + + INTRODUCTION + + LOCALIZATIONS + + + LICENSE + + KEYWORDS + + LOCALIZATIONS + + MODE + 0 + + README + + LOCALIZATIONS + + + SUMMARY + + LOCALIZATIONS + + + TITLE + + LOCALIZATIONS + + + LANGUAGE + English + VALUE + @APPLICATION_NAME_XML_ESCAPED@ Client + + + + + PROJECT_REQUIREMENTS + + LIST + + POSTINSTALL_PATH + + PREINSTALL_PATH + + RESOURCES + + ROOT_VOLUME_ONLY + + + PROJECT_SETTINGS + + ADVANCED_OPTIONS + + installer-script.options:hostArchitectures + + x86_64,arm64 + + + BUILD_FORMAT + 0 + BUILD_PATH + + PATH + @CMAKE_INSTALL_PREFIX@/. + PATH_TYPE + 3 + + EXCLUDED_FILES + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + .DS_Store + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove .DS_Store files + PROXY_TOOLTIP + Remove ".DS_Store" files created by the Finder. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + .pbdevelopment + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove .pbdevelopment files + PROXY_TOOLTIP + Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + CVS + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .cvsignore + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + .cvspass + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + .svn + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .git + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .gitignore + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove SCM metadata + PROXY_TOOLTIP + Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + classes.nib + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + designable.db + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + info.nib + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Optimize nib files + PROXY_TOOLTIP + Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + Resources Disabled + TYPE + 1 + + + PROTECTED + + PROXY_NAME + Remove Resources Disabled folders + PROXY_TOOLTIP + Remove "Resources Disabled" folders. + STATE + + + + SEPARATOR + + + + NAME + @APPLICATION_NAME_XML_ESCAPED@ Installer + REFERENCE_FOLDER_PATH + @CMAKE_INSTALL_DIR@ + + + TYPE + 0 + VERSION + 2 + + diff --git a/admin/osx/make_universal.py b/admin/osx/make_universal.py new file mode 100755 index 000000000..e5915e108 --- /dev/null +++ b/admin/osx/make_universal.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import sys +import os +import subprocess + + +# A general note: We first produce a x86_64 and a arm64 app package +# and then merge them together instead of compiling the desktop client +# with the CMake option CMAKE_OSX_ARCHITECTURES="x86_64;arm64" because +# macdeployqt can not handle universal binaries well. In the future +# with Qt6 this might change and this script will become obsolete. + + +def usage(program_name): + print("Creates a universal app package from a x86_64 and a arm64 app package.") + print("Usage: {} x86_64_app_file arm64_app_file output_directory".format(program_name)) + print("Example: {} some_dir/Nextcloud.app some_other_dir/Nextcloud.app output_dir".format(program_name)) + + +def execute(command): + return subprocess.check_output(command) + + +def path_relative_to_package(app_package_file_path, file_path): + if file_path.startswith(app_package_file_path): + relative_path = file_path[len(app_package_file_path):] + if relative_path.startswith("/"): + return relative_path[1:] + return relative_path + return file_path + + +def is_executable(file_path): + output = str(execute(["file", file_path])) + if (("Mach-O 64-bit dynamically linked shared library" in output) + or ("Mach-O 64-bit executable" in output) + or ("Mach-O 64-bit bundle" in output)): + return True + return False + + +if __name__ == "__main__": + if len(sys.argv) != 4: + usage(sys.argv[0]) + sys.exit(1) + + x86_64_app_file = sys.argv[1] + if not os.path.exists(x86_64_app_file): + print("Can't create universal: Path {} does not exist".format(x86_64_app_file)) + sys.exit(1) + arm64_app_file = sys.argv[2] + if not os.path.exists(arm64_app_file): + print("Can't create universal: Path {} does not exist".format(arm64_app_file)) + sys.exit(1) + output_dir = sys.argv[3] + + # Copy the Arm64 variant to the output location if possible + if not os.path.exists(output_dir): + os.makedirs(output_dir) + app_file_name = os.path.basename(arm64_app_file) + universal_app_file = os.path.join(output_dir, app_file_name) + if os.path.exists(universal_app_file): + print("Can't create universal: Path {} already exists".format(universal_app_file)) + sys.exit(1) + + execute(["cp", "-a", arm64_app_file, output_dir]) + + # Now walk through the copied arm64 version and replace the binaries + for root, dirs, files in os.walk(universal_app_file): + for f in files: + absolute_file_path = os.path.join(root, f) + root_relative = path_relative_to_package(universal_app_file, root) + x86_64_absolute_path = os.path.join(x86_64_app_file, root_relative, f) + arm64_absolute_path = os.path.join(arm64_app_file, root_relative, f) + if os.path.islink(absolute_file_path) or not is_executable(absolute_file_path): + continue + try: + print(f"Going to merge {arm64_absolute_path} with {x86_64_absolute_path} into {absolute_file_path}") + execute(["lipo", "-create", "-output", absolute_file_path, arm64_absolute_path, x86_64_absolute_path]) + print(execute(["lipo", "-info", absolute_file_path])) + except: + print(f"Could not merge {arm64_absolute_path} with {x86_64_absolute_path} into {absolute_file_path}!") + + print("Finished :)") diff --git a/admin/osx/post_install.sh.cmake b/admin/osx/post_install.sh.cmake new file mode 100644 index 000000000..583f5e9cb --- /dev/null +++ b/admin/osx/post_install.sh.cmake @@ -0,0 +1,13 @@ +#!/bin/sh + +# Always enable the new 10.10 finder plugin if available +if [ -x "$(command -v pluginkit)" ]; then + # add it to DB. This happens automatically too but we try to push it a bit harder for issue #3463 + pluginkit -a "/Applications/@APPLICATION_NAME@.app/Contents/PlugIns/FinderSyncExt.appex/" + # Since El Capitan we need to sleep #4650 + sleep 10s + # enable it + pluginkit -e use -i @APPLICATION_REV_DOMAIN@.FinderSyncExt +fi + +exit 0 diff --git a/admin/osx/pre_install.sh.cmake b/admin/osx/pre_install.sh.cmake new file mode 100644 index 000000000..dededc67d --- /dev/null +++ b/admin/osx/pre_install.sh.cmake @@ -0,0 +1,7 @@ +#!/bin/sh + +# kill the old version. see issue #2044 +killall @APPLICATION_EXECUTABLE@ +killall @APPLICATION_NAME@ + +exit 0 diff --git a/admin/osx/sign_app.sh b/admin/osx/sign_app.sh new file mode 100755 index 000000000..e495fe105 --- /dev/null +++ b/admin/osx/sign_app.sh @@ -0,0 +1,19 @@ +#!/bin/sh -xe + +[ "$#" -lt 2 ] && echo "Usage: sign_app.sh " && exit + +src_app="$1" +identity="$2" +team_identifier="$3" + +codesign -s "$identity" --force --preserve-metadata=entitlements --verbose=4 --deep "$src_app" + +# Verify the signature +codesign -dv $src_app +codesign --verify -v $src_app +spctl -a -t exec -vv $src_app + +# Validate that the key used for signing the binary matches the expected TeamIdentifier +# needed to pass the SocketApi through the sandbox +codesign -dv $src_app 2>&1 | grep "TeamIdentifier=$team_identifier" +exit $? \ No newline at end of file diff --git a/admin/osx/sign_dmg.sh b/admin/osx/sign_dmg.sh new file mode 100755 index 000000000..c1f4ba7d5 --- /dev/null +++ b/admin/osx/sign_dmg.sh @@ -0,0 +1,40 @@ +#!/bin/sh -x + +[ "$#" -lt 2 ] && echo "Usage: sign_dmg.sh " && 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" diff --git a/admin/osx/sparkle/dsa_pub.pem b/admin/osx/sparkle/dsa_pub.pem new file mode 100644 index 000000000..b7fc64d1a --- /dev/null +++ b/admin/osx/sparkle/dsa_pub.pem @@ -0,0 +1,36 @@ +-----BEGIN PUBLIC KEY----- +MIIGOzCCBC0GByqGSM44BAEwggQgAoICAQCwGHwZVKUPwJafICkknBmoIS7TGjfw +TnHpZdWJ/kVvMIhFiui3cJaB85e8R2yGRq7wr6ljYCR5EyjRXEJGEFW05PCUxLhh +LnUg7yWIL1EnRM61zSlnWer4f7IBO7Qf8hd35jL5VuQtqE+Shq1vtC21SFO6GMog +sfQdeyhTMIH67nw19fDxbyqPh+fPsBgitWmO07eF132Qxju0MwXvaju3YrXepuoR +ClonI8pfPCJAAyJd5sEAfJPiqObgW/ehNgU5mVXv2D6VNtvvyu0flnvj05TOtkz+ +6392xh0u/xtz1F1clPe31JW3C2zxkvS14M7eSn96hMlojLev75/V84pQNZ7qXQ/X +TxWaucnipJ94EqRLTg1hD3qwyC+5JKqOA6ELFmMARsP2MV4wmBIE+bz/bP2g7UCT +UIJVTZrZAemozMFR6zsQQMrdz9fEPXQhibcg3LppMnnTkAJUdMkKlGIpehGe1tVC +LaOgYh03zf/N7yFwH9eMIiAoXTlqR7iRO1HHsXn60OF8XYEt8Xga8cK7zMiPYOqm +o4rheeXw33pckX63glOjJ+ADH1jhU7vOjRsAySXMFjanD8A31Mh8NbhuvPJowJAx +ez8Hu4M6+fg644z7WHmsrbp0R3/Ow9FI/zmvYT6najOlEwnar8ix210ezjWmAOxN +BTuHN6Bj7ckgdQIVAKwAcb77T0Fyjus9ZImfCqlKdihZAoICABiPO4bywe636AlU +FRhMS/XFeGqRD7GbJSbGzIahooUPyVAeyRIU1HzmeVPx7jTqcoqcau0vXfv10EB+ +nJ3q6EzfCbitGIDJ1TjT2BhMtsnhzplhvVOAThuLnLpYwa3h8DIfgTqxh+DaCJHc +ccdl/sAgj/6m54FCRc5ukyQZZeOFgSO2L+JfGDYJpn1CFuRVrXr4DbvtUDItRTbQ +Gxlg5OEx2D1eO5DHtmuRPBZbumgACnFeD97tRQVjVKqQiMU3ZfNDp+mub0/MS/PY +djDZIZM4E3/Nx+IuSuRELGKgifM/ED0tyiq6FYy9kx1nVVoRhWt29ipkQSskvRL3 +Ba593/u7dMt2Pa/RVNha+9J1VIadblNu0OkieI8OrPJ8PEdrr3Igit1GuURxz/oR +c4T5nWCM+7e9yxs1resVDsU4D0aJVBMnE7IZwnN9/f4wduR0rxuBTLbMgtgBoIak +JhgplAQu7SdSxKSpY6keGZUpt8ATkixkScZmVhFKmuVYc1c0tLfUqQnlC4Ty44Wk +MEyub6749iRgNQp9vzvntS3EoLDho4CdEWlrp7YBtvTPiey46gcoLeLNZVyGuQ42 +CdFw09MIDPEhXBe6oWsOqW4OUla/UoVJyEjuPeiNIMruUJKIGkB1RL6OaiWxJkGM +2HXSebMEweWuScaJmNR5VX87n6KTA4ICBgACggIBAKIAUUc/MJYZYkZectbSabZy +TmlrPmi00q7wpsInTieeKVqOSypS+fuoiG2uuUX4+duqK8mLiA9WC0/y/cBJiWth +Bp28s1ADdC98wamERYpZOxWuHDS9MEsovQzm5RIxgVtZbK7vKk/f0WbGE6xwgERH +dt1zSZRh1ZWi/UWDVGHjlVMEhtNxoRD/Q5T4KUpLez0DNf2VpKk17KsqD2sS1zit +IwIMR++PEY9Rfw1FWIkE5GzJnjxR8sUr6hg5A4z779W7qW/KK5DGlOVYrHhdxUDA +b5q4wGBP3sDCPhhZ/g1V62tb1LAXnTMgAkdXGpRCxoe21TcB21PSQAbW1sOpFbSu +07kMLAZIh+L1eR5sY6z7S/pqE4W4ukYUEFJPUSCVUCXkN2ZbSfbQLLi2mVNNIp7u +/MJVxNQOtRqHM+2/nN+98Grivr1ct1G1NUHYgP/lr7Y2QNBiST0Lcnos8pjmI42v +0NxCt+BOx+cc0SNXxRJD2j73IgzD8YW3gvWfzSwUcIqgC27JEEMhscEVNI4vD/CR +mdDmYm0QJdBmEczPf5cA5gyAa1ATYS8ejrh6HpbC++FpSf4FN++5uu9cXtYJgI9B +G0ZEvlGwqzStV35LeqwF2KBSZIspquILBDJDaKHG7wPE5/MdSsFky1awX7jgyGZV +H5CvBpIDHOrQ0r1b40oB +-----END PUBLIC KEY----- diff --git a/admin/osx/sparkle/example_update_rss.rss b/admin/osx/sparkle/example_update_rss.rss new file mode 100644 index 000000000..e81c6351f --- /dev/null +++ b/admin/osx/sparkle/example_update_rss.rss @@ -0,0 +1,21 @@ + + + + oC + 127.0.0.1/test.rss + Most recent changes with links to updates. + en + + Version 1.5.1.2180-nightly20140202 + Wed, 09 Feb 2013 19:20:11 +0000 + + + + + diff --git a/admin/test/wait_for_server.sh b/admin/test/wait_for_server.sh new file mode 100755 index 000000000..a252f9d63 --- /dev/null +++ b/admin/test/wait_for_server.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2019-2020 Tobias Kaminsky +# SPDX-License-Identifier: AGPL-3.0-or-later + +counter=0 +status="" + +until [[ $status = "false" ]]; do + status=$(curl 2>/dev/null "http://$1/status.php" | jq .maintenance) + + echo "($counter) $status" + + if [[ "$status" =~ "false" || "$status" = "" ]]; then + let "counter += 1" + if [[ $counter -gt 90 ]]; then + echo "Failed to wait for server" + exit 1 + fi + fi + + sleep 10 +done + diff --git a/admin/win/CMakeLists.txt b/admin/win/CMakeLists.txt new file mode 100644 index 000000000..5395ad9e7 --- /dev/null +++ b/admin/win/CMakeLists.txt @@ -0,0 +1,8 @@ +# MSI package scripts, helper DLL and migration tools +if(BUILD_WIN_MSI) + add_subdirectory(msi) +endif() + +if(BUILD_WIN_MSI OR BUILD_WIN_TOOLS) + add_subdirectory(tools) +endif() diff --git a/admin/win/Toolchain-mingw32-openSUSE.cmake b/admin/win/Toolchain-mingw32-openSUSE.cmake new file mode 100644 index 000000000..ae1c5745f --- /dev/null +++ b/admin/win/Toolchain-mingw32-openSUSE.cmake @@ -0,0 +1,34 @@ +SET(MINGW_PREFIX "i686-w64-mingw32") + +# this one is important +SET(CMAKE_SYSTEM_NAME Windows) + + +# specify the cross compiler +SET(CMAKE_C_COMPILER ${MINGW_PREFIX}-gcc) +SET(CMAKE_CXX_COMPILER ${MINGW_PREFIX}-g++) +SET(CMAKE_RC_COMPILER ${MINGW_PREFIX}-windres) + +# where is the target environment containing libraries +SET(CMAKE_FIND_ROOT_PATH /usr/${MINGW_PREFIX}/sys-root/mingw) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + + +## configure qt variables +# generic +SET(QMAKESPEC win32-g++-cross) + +# dirs +SET(QT_LIBRARY_DIR /usr/${MINGW_PREFIX}/bin) +SET(QT_PLUGINS_DIR ${CMAKE_FIND_ROOT_PATH}/lib/qt5/plugins) +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) diff --git a/admin/win/create_stable_toolchain.sh b/admin/win/create_stable_toolchain.sh new file mode 100755 index 000000000..a158c3251 --- /dev/null +++ b/admin/win/create_stable_toolchain.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# +# This script creates a new windows toolchain repository in OBS. +# It only works for versions that do not yet exist. +# +# Make sure to adopt the variable stableversion. + +# Set the new stable version accordingly: +stableversion=2.1 +targetproject="isv:ownCloud:toolchains:mingw:win32:${stableversion}" + +# Create the new repo + +# get the xml build description of the stable repo +xml=`osc meta prj isv:ownCloud:toolchains:mingw:win32:stable` +stable_xml="${xml/stable/$stableversion}" + +echo $stable_xml + +echo $stable_xml | osc meta prj -F - ${targetproject} + + +# now copy all packages +packs=`osc ls isv:ownCloud:toolchains:mingw:win32:stable` + +for pack in $packs +do + osc copypac isv:ownCloud:toolchains:mingw:win32:stable $pack $targetproject +done diff --git a/admin/win/download_runtimes.sh b/admin/win/download_runtimes.sh new file mode 100755 index 000000000..350916f12 --- /dev/null +++ b/admin/win/download_runtimes.sh @@ -0,0 +1,19 @@ +#!/bin/sh -x + +#VS2013 +base_url=http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3 +tmp_path=${1:-/tmp/.vcredist} + +mkdir -p $tmp_path + +copy_cached_file() { + file=$1 + if [ ! -e $tmp_path/$file ]; then + wget -O $tmp_path/$file $base_url/$file + fi + cp -a $tmp_path/$file $PWD +} + +copy_cached_file "vcredist_x64.exe" +copy_cached_file "vcredist_x86.exe" + diff --git a/admin/win/msi/CMakeLists.txt b/admin/win/msi/CMakeLists.txt new file mode 100644 index 000000000..933037dac --- /dev/null +++ b/admin/win/msi/CMakeLists.txt @@ -0,0 +1,34 @@ +if(CMAKE_SIZEOF_VOID_P MATCHES 4) + set(MSI_BUILD_ARCH x86) +else() + set(MSI_BUILD_ARCH x64) +endif() + +string(SUBSTRING ${GIT_SHA1} 0 7 GIT_REVISION) + +set(VERSION "${MIRALL_VERSION_MAJOR}.${MIRALL_VERSION_MINOR}.${MIRALL_VERSION_PATCH}.${MIRALL_VERSION_BUILD}") + +if (NOT DEFINED MIRALL_VERSION_SUFFIX OR MIRALL_VERSION_SUFFIX MATCHES "git") + set(VERSION_SUFFIX "") +else() + set(VERSION_SUFFIX "-${MIRALL_VERSION_SUFFIX}") +endif() + +set(MSI_INSTALLER_FILENAME "${APPLICATION_SHORTNAME}-${VERSION}${VERSION_SUFFIX}-${MSI_BUILD_ARCH}.msi") + +configure_file(RegistryCleanup.vbs.in ${CMAKE_CURRENT_BINARY_DIR}/RegistryCleanup.vbs) +configure_file(OEM.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/OEM.wxi) +configure_file(collect-transform.xsl.in ${CMAKE_CURRENT_BINARY_DIR}/collect-transform.xsl) +configure_file(make-msi.bat.in ${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/OEM.wxi + ${CMAKE_CURRENT_BINARY_DIR}/collect-transform.xsl + ${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat + Platform.wxi + Nextcloud.wxs + ${CMAKE_CURRENT_BINARY_DIR}/RegistryCleanup.vbs + RegistryCleanupCustomAction.wxs + gui/banner.bmp + gui/dialog.bmp + DESTINATION msi/) diff --git a/admin/win/msi/Nextcloud.wxs b/admin/win/msi/Nextcloud.wxs new file mode 100644 index 000000000..c14cbe030 --- /dev/null +++ b/admin/win/msi/Nextcloud.wxs @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIS_UNINSTALLEXE AND NOT Installed + + + (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") + + + (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") + + + (SCHEDULE_REBOOT=1) OR NOT (UILevel=2) + + + + $(var.AppName) + $(var.AppIcon) + $(var.AppHelpLink) + $(var.AppInfoLink) + + + + + + + + + + + + + + + + + + + + + + + + 1 + + 1 + + + WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed + + Removing previous installation + Trying to terminate application process of previous installation + Removing sync folders from Explorer's Navigation Pane + + + + + + + NOT (LAUNCH=0) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (NO_SHELL_EXTENSIONS=1) + + + + + (NO_START_MENU_SHORTCUTS=1) + + + + + (NO_DESKTOP_SHORTCUT=1) + + + + diff --git a/admin/win/msi/OEM.wxi.in b/admin/win/msi/OEM.wxi.in new file mode 100644 index 000000000..e35451eef --- /dev/null +++ b/admin/win/msi/OEM.wxi.in @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/win/msi/Platform.wxi b/admin/win/msi/Platform.wxi new file mode 100644 index 000000000..c0efc3ad4 --- /dev/null +++ b/admin/win/msi/Platform.wxi @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/admin/win/msi/RegistryCleanup.vbs.in b/admin/win/msi/RegistryCleanup.vbs.in new file mode 100644 index 000000000..0eeb1a4ed --- /dev/null +++ b/admin/win/msi/RegistryCleanup.vbs.in @@ -0,0 +1,80 @@ +On Error goto 0 + +Const HKEY_LOCAL_MACHINE = &H80000002 +Const HKEY_CURRENT_USER = &H80000001 + +Const strObjRegistry = "winmgmts:\\.\root\default:StdRegProv" + +Function RegistryDeleteKeyRecursive(regRoot, strKeyPath) + Set objRegistry = GetObject(strObjRegistry) + objRegistry.EnumKey regRoot, strKeyPath, arrSubkeys + If IsArray(arrSubkeys) Then + For Each strSubkey In arrSubkeys + RegistryDeleteKeyRecursive regRoot, strKeyPath & "\" & strSubkey + Next + End If + objRegistry.DeleteKey regRoot, strKeyPath +End Function + +Function RegistryListSubkeys(regRoot, strKeyPath) + Set objRegistry = GetObject(strObjRegistry) + objRegistry.EnumKey regRoot, strKeyPath, arrSubkeys + RegistryListSubkeys = arrSubkeys +End Function + +Function GetUserSID() + Dim objWshNetwork, objUserAccount + + Set objWshNetwork = CreateObject("WScript.Network") + + Set objUserAccount = GetObject("winmgmts://" & objWshNetwork.UserDomain & "/root/cimv2").Get("Win32_UserAccount.Domain='" & objWshNetwork.ComputerName & "',Name='" & objWshNetwork.UserName & "'") + GetUserSID = objUserAccount.SID +End Function + +Function RegistryCleanupSyncRootManager() + strSyncRootManagerKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SyncRootManager" + + arrSubKeys = RegistryListSubkeys(HKEY_LOCAL_MACHINE, strSyncRootManagerKeyPath) + + If IsArray(arrSubkeys) Then + arrSubkeys=Filter(arrSubkeys, Session.Property("APPNAME")) + End If + If IsArray(arrSubkeys) Then + arrSubkeys=Filter(arrSubkeys, GetUserSID()) + End If + + If IsArray(arrSubkeys) Then + For Each strSubkey In arrSubkeys + RegistryDeleteKeyRecursive HKEY_LOCAL_MACHINE, strSyncRootManagerKeyPath & "\" & strSubkey + Next + End If +End Function + +Function RegistryCleanupCfApiShellExtensions() + Set objRegistry = GetObject(strObjRegistry) + + strShellExtAppId = "Software\Classes\AppID\@CFAPI_SHELLEXT_APPID_REG@" + + strShellExtThumbnailHandlerClsId = "Software\Classes\CLSID\@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG@" + strShellExtCustomStateHandlerClsId = "Software\Classes\CLSID\@CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID_REG@" + + rootKey = HKEY_CURRENT_USER + + If objRegistry.EnumKey(rootKey, strShellExtAppId, arrSubKeys) = 0 Then + RegistryDeleteKeyRecursive rootKey, strShellExtAppId + End If + + If objRegistry.EnumKey(rootKey, strShellExtThumbnailHandlerClsId, arrSubKeys) = 0 Then + RegistryDeleteKeyRecursive rootKey, strShellExtThumbnailHandlerClsId + End If + + If objRegistry.EnumKey(rootKey, strShellExtCustomStateHandlerClsId, arrSubKeys) = 0 Then + RegistryDeleteKeyRecursive rootKey, strShellExtCustomStateHandlerClsId + End If + +End Function + +Function RegistryCleanup() + RegistryCleanupSyncRootManager() + RegistryCleanupCfApiShellExtensions() +End Function diff --git a/admin/win/msi/RegistryCleanupCustomAction.wxs b/admin/win/msi/RegistryCleanupCustomAction.wxs new file mode 100644 index 000000000..a546930e6 --- /dev/null +++ b/admin/win/msi/RegistryCleanupCustomAction.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/admin/win/msi/collect-transform.xsl.in b/admin/win/msi/collect-transform.xsl.in new file mode 100644 index 000000000..63d335307 --- /dev/null +++ b/admin/win/msi/collect-transform.xsl.in @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + MainExecutable + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/admin/win/msi/gui/banner.bmp b/admin/win/msi/gui/banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7eba2ce1a7700f2010105784749f73ba19ef0247 GIT binary patch literal 85894 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 Apa1{> literal 0 HcmV?d00001 diff --git a/admin/win/msi/gui/banner.svg b/admin/win/msi/gui/banner.svg new file mode 100644 index 000000000..0739c16bf --- /dev/null +++ b/admin/win/msi/gui/banner.svg @@ -0,0 +1,72 @@ + +image/svg+xml diff --git a/admin/win/msi/gui/dialog.bmp b/admin/win/msi/gui/dialog.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f548941594d7772eb466a98a2a3b3e6e037548a0 GIT binary patch literal 464774 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 literal 0 HcmV?d00001 diff --git a/admin/win/msi/make-msi.bat.in b/admin/win/msi/make-msi.bat.in new file mode 100644 index 000000000..eb1473532 --- /dev/null +++ b/admin/win/msi/make-msi.bat.in @@ -0,0 +1,26 @@ +@echo off +set HarvestAppDir=%~1 +set BuildArch=@MSI_BUILD_ARCH@ + +if "%HarvestAppDir%" == "" ( + echo "Missing parameter: Please specify file collection source path (HarvestAppDir)." + exit 1 +) + +if "%WIX%" == "" ( + echo "WiX Toolset path not set (environment variable 'WIX'). Please install the WiX Toolset." + exit 1 +) + +Rem Generate collect.wxs +"%WIX%\bin\heat.exe" dir "%HarvestAppDir%" -dr INSTALLDIR -sreg -srd -sfrag -ag -cg ClientFiles -var var.HarvestAppDir -platform='%BuildArch%' -t collect-transform.xsl -out collect.wxs +if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% + +Rem Compile en-US (https://www.firegiant.com/wix/tutorial/transforms/morphing-installers/) +"%WIX%\bin\candle.exe" -dcodepage=1252 -dPlatform=%BuildArch% -arch %BuildArch% -dHarvestAppDir="%HarvestAppDir%" -ext WixUtilExtension NCMsiHelper.wxs WinShellExt.wxs collect.wxs Nextcloud.wxs RegistryCleanupCustomAction.wxs +if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% + +Rem Link MSI package +"%WIX%\bin\light.exe" -sw1076 -ext WixUIExtension -ext WixUtilExtension -cultures:en-us NCMsiHelper.wixobj WinShellExt.wixobj collect.wixobj Nextcloud.wixobj RegistryCleanupCustomAction.wixobj -out "@MSI_INSTALLER_FILENAME@" + +exit %ERRORLEVEL% diff --git a/admin/win/nsi/.directory b/admin/win/nsi/.directory new file mode 100644 index 000000000..be8d47225 --- /dev/null +++ b/admin/win/nsi/.directory @@ -0,0 +1,3 @@ +[Dolphin] +PreviewsShown=true +Timestamp=2012,4,1,13,48,38 diff --git a/admin/win/nsi/README.md b/admin/win/nsi/README.md new file mode 100644 index 000000000..ba2f5c166 --- /dev/null +++ b/admin/win/nsi/README.md @@ -0,0 +1,28 @@ +# Windows Installer Translations + +## Introduction + +Translations on transifex: http://www.transifex.com/projects/p/owncloud/resource/client-nsis/ + +Daily sync job: https://ci.owncloud.org/view/translation-sync/job/translation-sync-client-nsis/ + +## How to add a new translation string? + +0. Add the string to the pofiles/messages.pot manually. This step is necessary +for the upload of strings to be translated to transifex + +1. Run bin/l10n.sh to properly generate declarations.nsh and English.nsh + +2. If you want to test your installer right away you need to add the new string +at least to l10n/English.nsh + + +## How to add a new language? + +0. Add the new language to l10n/.tx/config which holds the explicit list of +languages to be downloaded from transifex on each translation sync run. + +1. Add the new language to l10n/languages.nsh + +2. In NSIS.template.in the language has to be added in the macro SETLANG. + diff --git a/admin/win/nsi/RELEASE_NOTES.txt b/admin/win/nsi/RELEASE_NOTES.txt new file mode 100644 index 000000000..e69de29bb diff --git a/admin/win/nsi/installer.ico b/admin/win/nsi/installer.ico new file mode 100644 index 0000000000000000000000000000000000000000..39b2b69160c205700ebc0dd62e67fc78112e4bb3 GIT binary patch literal 276766 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 literal 0 HcmV?d00001 diff --git a/admin/win/nsi/l10n/Basque.nsh b/admin/win/nsi/l10n/Basque.nsh new file mode 100644 index 000000000..683521eeb --- /dev/null +++ b/admin/win/nsi/l10n/Basque.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Erakutsi bertsio-berritze oharrak" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Gelditu beharreko ${APPLICATION_EXECUTABLE} prozesua(k) aurkitu dira.$\nNahi duzu instalatzaileak zure partetik hauek gelditzea?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "${APPLICATION_EXECUTABLE} prozesuak hiltzen." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "kill prozesua ez da aurkitu!" +StrCpy $PageReinstall_NEW_Field_1 "${APPLICATION_NAME}ren bertsio zaharrago bat instalatuta dago. Aholkatzen da hau desinstalatzea berria instalatu baino lehen. Hautatu nahi duzun aukera eta sakatu Hurrengoa jarraitzeko." +StrCpy $PageReinstall_NEW_Field_2 "Desinstalatu instalatu baino lehen" +StrCpy $PageReinstall_NEW_Field_3 "Ez desinstalatu" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Dagoeneko Instalatuta" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Hautatu nola nahi duzun ${APPLICATION_NAME} instalatzea." +StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME}ren bertsio berriago bat instalatuta dago! Ez da aholkatzen bertsio zaharrago bat instalatzea. Benetan bertsio zaharrago hau instalatu nahi baduzu, hobe da lehenengo bertsio berria desinstalatzea. Hautatu nahi duzun aukera eta sakatu Hurrengoa jarraitzeko." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} dagoeneko instalatuta dago.$\nHautatu zer operazio egin nahi duzu eta klikatu Hurrengoa jarraitzeko." +StrCpy $PageReinstall_SAME_Field_2 "Gehitu/Berrinstalatu osagaiak" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalatu ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalatu ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Hautatu zer mantenu aukera egin nahi duzun." +StrCpy $SEC_APPLICATION_DETAILS "${APPLICATION_NAME} ezinbestekoak instalatzen." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows Explorerekin Integrazioa" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows Explorerekin Integrazioa Instalatzen" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Hasierako Menuko Lasterbidea" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Hasierako Menuan ${APPLICATION_NAME}rako Abiarazle bizkorra sortzen." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Mahaigaineko Lasterbidea" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Mahaigaineko Lasterbideak Sortzen" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Abiarazle Bizkorreko Lasterbidea" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Abiarazle Bizkorreko Lasterbidea Sortzen" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} ezinbestekoak." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} lasterbidea." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "${APPLICATION_NAME}rako mahaigaineko lasterbidea." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "${APPLICATION_NAME}erako Abiarazle Bizkorreko Lasterbidea." +StrCpy $UNINSTALLER_FILE_Detail "Desinstalatzailea idazten" +StrCpy $UNINSTALLER_REGISTRY_Detail "Instalatzaileko Erregistroko Giltzak idazten" +StrCpy $UNINSTALLER_FINISHED_Detail "Bukatuta" +StrCpy $UNINSTALL_MESSAGEBOX "Ez dirudi ${APPLICATION_NAME} '$INSTDIR'.$ direktorioan instalatuta dagoenik.$\n$\nJarraitu hala ere (ez da aholkatzen)?" +StrCpy $UNINSTALL_ABORT "Desinstalazioak erabiltzaileak bertan behera utzi du" +StrCpy $INIT_NO_QUICK_LAUNCH "Abiarazle Bizkorreko Lasterbidea (E/E)" +StrCpy $INIT_NO_DESKTOP "Mahaigaineko Lasterbidea (dagoena berridazten du)" +StrCpy $UAC_ERROR_ELEVATE "Ezin izan da goratu, errorea:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Instalatzaileak administratzaile baimenak behar ditu, saiatu berriro" +StrCpy $INIT_INSTALLER_RUNNING "Instalatzailea dagoeneko martxan da." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Desinstalatzaile honek administratzaile baimenak behar ditu, saiatu berriro" +StrCpy $UAC_ERROR_LOGON_SERVICE "Saioa hasteko zerbitzua ez dago martxan, bertan behera uzten!" +StrCpy $INIT_UNINSTALLER_RUNNING "Desinstalatzailea dagoeneko martxan da." +StrCpy $SectionGroup_Shortcuts "Lasterbideak" diff --git a/admin/win/nsi/l10n/Catalan.nsh b/admin/win/nsi/l10n/Catalan.nsh new file mode 100644 index 000000000..4db71cc6e --- /dev/null +++ b/admin/win/nsi/l10n/Catalan.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar les notes de versió" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "S'ha trobat el(s) procés ${APPLICATION_EXECUTABLE} que s'ha d'aturar.$\nVoleu que l'instal·lador l'aturi?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "S'estan matant els processos ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Procés per matar no trobat!" +StrCpy $PageReinstall_NEW_Field_1 "Una versió anterior de ${APPLICATION_NAME} està instal·lada en el vostre sistema. Es recomana desinstal·lar la versió actual abans d'instal·lar. Seleccioneu l'operació que desitjeu realitzar i feu clic a Següent per continuar." +StrCpy $PageReinstall_NEW_Field_2 "Desinstal·lar abans d'instal·lar" +StrCpy $PageReinstall_NEW_Field_3 "No instal·lar" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ja instal·lat" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Trieu la manera com voleu instal·lar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Una versió més recent de ${APPLICATION_NAME} ja està instal.lada!! No es recomana instal.lar una versió més antiga. Si realment voleu instal.lar una versió més antiga, és millor primer desinstal.lar la versió actual. Seleccioni l'operació que desitjeu realitzar i feu clic a Següent per a continuar." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ja està instal·lat.$\n$\nSeleccioneu la operació que voleu fer i feu clic a Següent per continuar." +StrCpy $PageReinstall_SAME_Field_2 "Afegir/Reinstal.lar components" +StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolliu l'opció de manteniment per executar-ho." +StrCpy $SEC_APPLICATION_DETAILS "Instal·lant ${APPLICATION_NAME} essencial." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integració per Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instal·lant integració per Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Accés directe del programa al menú d'inici" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Afegint la drecera per ${APPLICATION_NAME} al menú d'inici." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Drecera a l'escriptori" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creant les dreceres a l'escriptori" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Drecera d'inici ràpid" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creant la drecera per l'inici ràpid" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essencial." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Drecera ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Drecera a l'escrptori per ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Drecera d'inici ràpid per ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Escrivint el desinstal·lador" +StrCpy $UNINSTALLER_REGISTRY_Detail "Escrivint les claus del registre de l'instal·lador" +StrCpy $UNINSTALLER_FINISHED_Detail "Acabat" +StrCpy $UNINSTALL_MESSAGEBOX "No sembla que ${APPLICATION_NAME} estigui instal·lat en la carpeta '$INSTDIR'.$\n$\nContinuo igualment (no recomanat)?" +StrCpy $UNINSTALL_ABORT "La desinstal·lació s'ha cancel·lat." +StrCpy $INIT_NO_QUICK_LAUNCH "Drecera d'inici ràpid (N/A)" +StrCpy $INIT_NO_DESKTOP "Drecera de l'escrpitori (sobreescriu l'existent)" +StrCpy $UAC_ERROR_ELEVATE "No es pot elevar, error:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Aquest instal·lador requereix accés d'administrador, intenteu-ho de nou" +StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou." +StrCpy $UAC_ERROR_LOGON_SERVICE "El servei de inici de sessió no s'està executant, s'està abortant!" +StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant." +StrCpy $SectionGroup_Shortcuts "Dreceres" diff --git a/admin/win/nsi/l10n/Czech.nsh b/admin/win/nsi/l10n/Czech.nsh new file mode 100644 index 000000000..8aa04a4e5 --- /dev/null +++ b/admin/win/nsi/l10n/Czech.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Zobrazit poznámky k vydání" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Nalezen proces(y) ${APPLICATION_EXECUTABLE}, které je nutné ukončit .$\nPřejete si, aby je instalátor za vás ukončil?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Ukončuji procesy ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Proces k ukončení nebyl nalezen! " +StrCpy $PageReinstall_NEW_Field_1 "Starší verze ${APPLICATION_NAME} je nainstalována na tomto systému. Doporučuje se předem tuto verzi odinstalovat. Zvolte operaci, kterou chcete uskutečnit, a klikněte na tlačítko Další pro pokračování." +StrCpy $PageReinstall_NEW_Field_2 "Odinstalovat před instalací" +StrCpy $PageReinstall_NEW_Field_3 "Neodinstalovávat" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Již nainstalováno" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Zvolte, jak chcete ${APPLICATION_NAME} nainstalovat." +StrCpy $PageReinstall_OLD_Field_1 "Novější verze aplikace ${APPLICATION_NAME} je již nainstalována. Instalace starší verze se nedoporučuje. Pokud opravdu chcete tuto starší verzi nainstalovat, je lepší nejprve odinstalovat současnou verzi. Zvolte požadovanou operaci a klikněte na Další pro pokračování." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} je již nainstalována.$\n$\nZvolte požadovanou operaci a klikněte na Další pro pokračování." +StrCpy $PageReinstall_SAME_Field_2 "Přidat či znovu instalovat komponenty" +StrCpy $PageReinstall_SAME_Field_3 "Odinstalovat ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstalovat ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnost údržby k provedení." +StrCpy $SEC_APPLICATION_DETAILS "Instalují se náležitosti ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integrace do průzkumníka Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalace integrace do průzkumníka Windows" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupce v Nabídce Start" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Přidávám zástupce pro ${APPLICATION_NAME} do Nabídky Start." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupce na ploše" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Vytvářím zástupce na ploše" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Zástupce v panelu rychlého spuštění" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Vytvářím zástupce v panelu rychlého spuštění" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Náležitosti ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Zástupce ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Zástupce na ploše pro ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Zástupce rychlého spuštění pro ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Zapisuji odinstalátor" +StrCpy $UNINSTALLER_REGISTRY_Detail "Zapisuji instalátor do registrů" +StrCpy $UNINSTALLER_FINISHED_Detail "Dokončeno" +StrCpy $UNINSTALL_MESSAGEBOX "Nezdá se, že ${APPLICATION_NAME} je nainstalována v adresáři '$INSTDIR'.$\n$\nChcete pokračovat (nedoporučuje se)?" +StrCpy $UNINSTALL_ABORT "Odinstalace zrušena uživatelem" +StrCpy $INIT_NO_QUICK_LAUNCH "Zástupce rychlého spuštění (není k dispozici)" +StrCpy $INIT_NO_DESKTOP "Zástupce na ploše (přepíše existující)" +StrCpy $UAC_ERROR_ELEVATE "Nelze zvýšit, chyba:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Tento instalátor vyžaduje správcovská oprávnění, opakujte znovu" +StrCpy $INIT_INSTALLER_RUNNING "Instalátor je již spuštěn." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tento odinstalátor vyžaduje správcovská oprávnění, opakujte znovu" +StrCpy $UAC_ERROR_LOGON_SERVICE "Služba přihlášení neběží, ukončuji!" +StrCpy $INIT_UNINSTALLER_RUNNING "Odinstalátor je již spuštěn." +StrCpy $SectionGroup_Shortcuts "Zástupci" diff --git a/admin/win/nsi/l10n/Dutch.nsh b/admin/win/nsi/l10n/Dutch.nsh new file mode 100644 index 000000000..e774aaef9 --- /dev/null +++ b/admin/win/nsi/l10n/Dutch.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze versie" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Gevonden ${APPLICATION_EXECUTABLE} proces(sen) moet worden gestopt.$\nWilt u dat het installatieprogramma dat voor u doet?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Stoppen ${APPLICATION_EXECUTABLE} processen." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Het te stoppen proces is niet gevonden!" +StrCpy $PageReinstall_NEW_Field_1 "Er is een oudere versie van ${APPLICATION_NAME} geïnstalleerd op uw systeem. geadviseerd wordt om de huidige versie te de-installeren voordat de nieuwe versie wordt geïnstalleerd. Selecteer de uit te voeren actie en klik op Verder om door te gaan." +StrCpy $PageReinstall_NEW_Field_2 "Verwijder oude versie" +StrCpy $PageReinstall_NEW_Field_3 "Behoud oude versie" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Al geïnstalleerd" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Kies hoe u ${APPLICATION_NAME} wilt installeren." +StrCpy $PageReinstall_OLD_Field_1 "Er is al een recentere versie van ${APPLICATION_NAME} geïnstalleerd! Installeren van een oudere versie wordt niet aangeraden. Als u echt de oudere versie wilt installeren, adviseren we de huidige versie eerst te verwijderen. Kies de actie die u wilt uitvoeren en druk op Verder om door te gaan." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is al geïnstalleerd.$\n$\nKies de actie die u uit wil voeren en druk op Verder om door te gaan." +StrCpy $PageReinstall_SAME_Field_2 "Toevoegen/herinstalleren componenten" +StrCpy $PageReinstall_SAME_Field_3 "De-installeer ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "De-installeer ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Kies de uit te voeren onderhoudsoptie." +StrCpy $SEC_APPLICATION_DETAILS "Installeren ${APPLICATION_NAME} basis." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integratie binnen Windows Verkenner" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installeren Integratie binnen Windows Verkenner" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Startmenu snelkoppeling" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Toevoegen snelkoppeling voor ${APPLICATION_NAME} aan het Startmenu." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Werkblad snelkoppeling" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Aanmaken werkblad snelkoppelingen" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Snelstart snelkoppeling" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Aanmaken snelstart snelkoppeling" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} basis." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} snelkoppeling." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Werkblad snelkoppeling voor ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Snelstart snelkoppeling voor ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Wegschrijven Uninstaller" +StrCpy $UNINSTALLER_REGISTRY_Detail "Wegschrijven installer Registersleutels" +StrCpy $UNINSTALLER_FINISHED_Detail "Klaar" +StrCpy $UNINSTALL_MESSAGEBOX "Het lijkt er niet op dat ${APPLICATION_NAME} is geïnstalleerd in de map '$INSTDIR'.$\n$\nToch doorgaan (niet aangeraden)?" +StrCpy $UNINSTALL_ABORT "De-installatie afgebroken door de gebruiker" +StrCpy $INIT_NO_QUICK_LAUNCH "Snelstart snelkoppeling (N/A)" +StrCpy $INIT_NO_DESKTOP "Bureaublad snelkoppeling (overschrijft huidige)" +StrCpy $UAC_ERROR_ELEVATE "Kan niet verhogen, fout:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dit installatieprogramma vereist beheerdersrechten. Probeer het opnieuw" +StrCpy $INIT_INSTALLER_RUNNING "De Installer is al gestart." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Deze uninstaller vereist Beheerderstoegang, probeer opnieuw" +StrCpy $UAC_ERROR_LOGON_SERVICE "De aanmeldprocedure is niet actief; er wordt afgebroken!" +StrCpy $INIT_UNINSTALLER_RUNNING "De uninstaller is al gestart." +StrCpy $SectionGroup_Shortcuts "Snelkoppelingen" diff --git a/admin/win/nsi/l10n/English.nsh b/admin/win/nsi/l10n/English.nsh new file mode 100644 index 000000000..41deff3ef --- /dev/null +++ b/admin/win/nsi/l10n/English.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Show release notes" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Found ${APPLICATION_EXECUTABLE} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Killing ${APPLICATION_EXECUTABLE} processes." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Process to kill not found!" +StrCpy $PageReinstall_NEW_Field_1 "An older version of ${APPLICATION_NAME} is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue." +StrCpy $PageReinstall_NEW_Field_2 "Uninstall before installing" +StrCpy $PageReinstall_NEW_Field_3 "Do not uninstall" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Already Installed" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choose how you want to install ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "A newer version of ${APPLICATION_NAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue." +StrCpy $PageReinstall_SAME_Field_2 "Add/Reinstall components" +StrCpy $PageReinstall_SAME_Field_3 "Uninstall ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Uninstall ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choose the maintenance option to perform." +StrCpy $SEC_APPLICATION_DETAILS "Installing ${APPLICATION_NAME} essentials." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration for Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing Integration for Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menu Program Shortcut" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adding shortcut for ${APPLICATION_NAME} to the Start Menu." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop Shortcut" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creating Desktop Shortcuts" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Quick Launch Shortcut" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creating Quick Launch Shortcut" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} essentials." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} shortcut." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Desktop shortcut for ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Quick Launch shortcut for ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Writing Uninstaller" +StrCpy $UNINSTALLER_REGISTRY_Detail "Writing Installer Registry Keys" +StrCpy $UNINSTALLER_FINISHED_Detail "Finished" +StrCpy $UNINSTALL_MESSAGEBOX "It does not appear that ${APPLICATION_NAME} is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?" +StrCpy $UNINSTALL_ABORT "Uninstall aborted by user" +StrCpy $INIT_NO_QUICK_LAUNCH "Quick Launch Shortcut (N/A)" +StrCpy $INIT_NO_DESKTOP "Desktop Shortcut (overwrites existing)" +StrCpy $UAC_ERROR_ELEVATE "Unable to elevate, error:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "This installer requires admin access, try again." +StrCpy $INIT_INSTALLER_RUNNING "The installer is already running." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "This uninstaller requires admin access, try again." +StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!" +StrCpy $INIT_UNINSTALLER_RUNNING "The uninstaller is already running." +StrCpy $SectionGroup_Shortcuts "Shortcuts" diff --git a/admin/win/nsi/l10n/Estonian.nsh b/admin/win/nsi/l10n/Estonian.nsh new file mode 100644 index 000000000..bf23a56ac --- /dev/null +++ b/admin/win/nsi/l10n/Estonian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Näita väljalaske märkmeid" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Leitud protsess(id) ${processName} mis tuleks peatada. $\nKas soovid, et installer seiskaks need?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "${APPLICATION_EXECUTABLE} protsessi lõpetamine." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Ei leitud protsessi, mida tappa!" +StrCpy $PageReinstall_NEW_Field_1 "Üks vanem versioon ${APPLICATION_NAME} on juba paigaldatud. On soovitav see eemaldada enne uue paigaldamist. Vali tehtav toiming ning kliki Jätka." +StrCpy $PageReinstall_NEW_Field_2 "Eemalda enne paigaldamist" +StrCpy $PageReinstall_NEW_Field_3 "Ära paigalda" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Juba paigaldatud" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Vali, kuidas sa soovid paigaldada ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Uuem versioon ${APPLICATION_NAME} on juba paigaldatud! Vanema versiooni paigaldus ei ole soovitatav. Kui tõesti tahad paigaldada vanemat versiooni, siis on parem esmalt eemaldada olemasolev. Vali tehtav toiming ning kliki Jätka." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on juba paigaldatud.$\n$\nVali toiming, mida sa tahad sooritada ning kliki jätkamiseks nuppu Next." +StrCpy $PageReinstall_SAME_Field_2 "Lisa/Taaspaigalda komponente" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalli ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalli ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vali hooldustegevus, mida sa soovid sooritada." +StrCpy $SEC_APPLICATION_DETAILS "Paigaldan ${APPLICATION_NAME} põhiosa." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integreerimine Windows Exploreriga" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Paigalda Windows Exploreriga integreerimine" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menüü programmide otsetee" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lisan ${APPLICATION_NAME} otsetee Start menüüsse." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Töölaua otsetee" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Töölaua otseteede loomine" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Kiirvaliku otsetee" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Kiirvaliku otsetee loomine" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} põhiosa." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} otsetee." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Töölaua otsetee rakendusele ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Kiirvaliku otsetee rakendusele ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Desinstallija kirjutamine" +StrCpy $UNINSTALLER_REGISTRY_Detail "Kirjutan paigaldaja registri võtmeid" +StrCpy $UNINSTALLER_FINISHED_Detail "Lõpetatud" +StrCpy $UNINSTALL_MESSAGEBOX "Ei leia, et ${APPLICATION_NAME} oleks paigaldatud kataloogi '$INSTDIR'.$\n$\nJätkata sellele vaatamata (pole soovitav)?" +StrCpy $UNINSTALL_ABORT "Desinstallimine on kasutaja poolt katkestatud" +StrCpy $INIT_NO_QUICK_LAUNCH "Kiirvaliku otsetee (N/A)" +StrCpy $INIT_NO_DESKTOP "Ikoon töölaual (kirjutab olemasoleva üle)" +StrCpy $UAC_ERROR_ELEVATE "Ei suuda ülendada õigusi, viga: " +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "See paigaldaja vajab admini ligipääsu, proovi uuesti" +StrCpy $INIT_INSTALLER_RUNNING "Paigaldaja on juba käimas." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "See desinstallija vajab admini ligipääsu, proovi uuesti" +StrCpy $UAC_ERROR_LOGON_SERVICE "Sisselogimisteenus ei tööta, katkestamine!" +StrCpy $INIT_UNINSTALLER_RUNNING "See desinstallija on juba käimas." +StrCpy $SectionGroup_Shortcuts "Otseteed" diff --git a/admin/win/nsi/l10n/Farsi.nsh b/admin/win/nsi/l10n/Farsi.nsh new file mode 100644 index 000000000..a0f78b1ba --- /dev/null +++ b/admin/win/nsi/l10n/Farsi.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "نمایش پادداشت های انتشار نسخه" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "${APPLICATION_EXECUTABLE} پردازش (ها) که باید متوقف شوند را پیدا کرد. $\nآیا میخواهیم برنامه نصاب این پردازشها را برای شما متوقف کند ؟" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "حذف پردازش‌های ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "پردازش برای از بین بردن یافت نشد!" +StrCpy $PageReinstall_NEW_Field_1 "نسخه‌ی قدیمی از برنامه ${APPLICATION_NAME} بر روی سیستم شما نصب شده است، پیشنهاد می‌شود نسخه‌ی فعلی را قبل از نصب حذف کنید. عملیات مورد نظر را انتخاب کنید و برای ادامه روی دکمه Next کلیک کنید." +StrCpy $PageReinstall_NEW_Field_2 "عمل حذف را قبل از نصب انجام دهید" +StrCpy $PageReinstall_NEW_Field_3 "حذف نکن" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "از قبل نصب شده است" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "نحوه‌ی نصب ${APPLICATION_NAME} را انتخاب کنید." +StrCpy $PageReinstall_OLD_Field_1 "نسخه جدیدتری از برنامه ${APPLICATION_NAME} بر روی سیستم شما نصب شده است، نصب نسخه‌ی قدیمی‌تر پیشنهاد نمی‌شود. درصورتیکه میخواهید نسخه‌ی قدیمی را نصب کنید، حذف نسخه‌ی کنونی قبل از اجرای نصب جدید پیشنهاد می‌شود. عملیات مورد نظر را انتخاب و بر روی دکمه‌ی Next کلیک کنید." +StrCpy $PageReinstall_SAME_Field_1 "نسخه ${VERSION} از ${APPLICATION_NAME} هم‌اکنون نصب شده است.$↩$\nعملیات مورد نظر را انتخاب و بر روی دکمه Next کلیک کنید." +StrCpy $PageReinstall_SAME_Field_2 "افزودن/نصب مجدد اجزا" +StrCpy $PageReinstall_SAME_Field_3 "حذف ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "حذف ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "گزینه نگهداری را به منظور اجرا انتخاب کنید." +StrCpy $SEC_APPLICATION_DETAILS "نصب ضروریات ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "یکپارچه‌سازی با Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "نصب یکپارچه‌ساز با Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "بازکردن میانبر منو برنامه" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "افزودن میانبر ${APPLICATION_NAME} به استارت منو ." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "میانبر دسکتاپ" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "ایجاد میانبر دسکتاپ" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "میانبر بازکردن سریع" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "ایجاد میانبر اجرای سریع" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "ملزومات ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "میانبر ${APPLICATION_NAME} " +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "میانبر دسکتاپ برای ${APPLICATION_NAME} ." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "میانبر اجرای سریع برای ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_FILE_Detail "نوشتن حذف کننده" +StrCpy $UNINSTALLER_REGISTRY_Detail "در حال نوشتن کلید های رجیستری نصاب" +StrCpy $UNINSTALLER_FINISHED_Detail "اتمام" +StrCpy $UNINSTALL_MESSAGEBOX "به نظر نمی رسد نرم افزار ${APPLICATION_NAME} در '$INSTDIR'.$\n$\nنصب شده باشد.$\nآیا می خواهید ادامه دهید ( توصیه نشده است ) ؟" +StrCpy $UNINSTALL_ABORT "عمل حذف توسط کاربر متوقف شد" +StrCpy $INIT_NO_QUICK_LAUNCH "میانبر بازکردن سریع ( N/A )" +StrCpy $INIT_NO_DESKTOP "میانبر دسکتاپ (رونویسی وجود دارد)" +StrCpy $UAC_ERROR_ELEVATE "مشکل در بالااوردن ، خطا : " +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "برای نصب، دسترسی مدیر سیستم نیاز است، مجددا تلاش کنید" +StrCpy $INIT_INSTALLER_RUNNING "نصاب از قبل در حال اجراست." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "حذف برنامه نیاز به دسترسی مدیر دارد ، لطفا دوباره سعی کنید" +StrCpy $UAC_ERROR_LOGON_SERVICE "سرویس ورود اجرا نیست، درحال لغو نصب!" +StrCpy $INIT_UNINSTALLER_RUNNING "حذف کننده از قبل در حال اجراست." +StrCpy $SectionGroup_Shortcuts "میانبرها" diff --git a/admin/win/nsi/l10n/Finnish.nsh b/admin/win/nsi/l10n/Finnish.nsh new file mode 100644 index 000000000..82d2ab5e4 --- /dev/null +++ b/admin/win/nsi/l10n/Finnish.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Näytä julkaisutiedot" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Havaittiin sovelluksen ${APPLICATION_EXECUTABLE} prosessi (tai prosesseja) jotka pitäisi pysäyttää.$\nHaluatko että asennusohjelma pysäyttää nämä puolestasi?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Pysäytetään sovelluksen ${APPLICATION_EXECUTABLE} prosessit." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Tapettavaa prosessia ei löytynyt!" +StrCpy $PageReinstall_NEW_Field_1 "Vanhempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu. On suositeltavaa että poistat vanhan asennuksen ensin. Valitse mikä toiminto suoritetaan ja napsauta Seuraava jatkaaksesi." +StrCpy $PageReinstall_NEW_Field_2 "Poista ennen asentamista" +StrCpy $PageReinstall_NEW_Field_3 "Älä poista" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Asennettu jo" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Valitse miten ${APPLICATION_NAME} asennetaan." +StrCpy $PageReinstall_OLD_Field_1 "Uudempi versio sovelluksesta ${APPLICATION_NAME} on jo asennettu! Vanhan version asennus ei ole suositeltavaa. Jos todella haluat asentaa vanhemman version, kannattaa poistaa nykyisen version asennus ensin. Valitse minkä toimenpiteen haluat suorittaa ja paina Seuraava jatkaaksesi." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on jo asennettu.$\n$\nValitse haluamasi toiminto ja napsauta Seuraava jatkaaksesi." +StrCpy $PageReinstall_SAME_Field_2 "Lisää/uudelleenasenna komponentteja" +StrCpy $PageReinstall_SAME_Field_3 "Poista ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Poista ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Valitse suoritettava huoltotoimenpide." +StrCpy $SEC_APPLICATION_DETAILS "Asennetaan sovelluksen ${APPLICATION_NAME} välttämättömyyksiä." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integraatio Windows Exploreriin" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Asennetaan integraatiota Windows Exploreriin" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Käynnistä-valikon pikakuvake" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lisätään ${APPLICATION_NAME}-pikakuvake Käynnistä-valikkoon." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Työpöydän pikakuvake" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Luodaan työpöydän pikakuvakkeet" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Pikakäynnistyksen pikakuvake" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Luodaan pikakuvaketta pikakäynnistykseen" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} välttämättömyydet." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}-pikakuvake." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Sovelluksen ${APPLICATION_NAME} työpyötäpikakuvake." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Pikakäynnistyksen pikakuvake sovellukselle ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Kirjoitetaan poisto-ohjelmaa" +StrCpy $UNINSTALLER_REGISTRY_Detail "Kirjoitetaan asennusohjelman rekisteriavaimia" +StrCpy $UNINSTALLER_FINISHED_Detail "Valmis" +StrCpy $UNINSTALL_MESSAGEBOX "Vaikuttaa siltä että sovellus ${APPLICATION_NAME} on asennettu kansioon '$INSTDIR'.$\n$\nHaluatko jatkaa tästä huolimatta (ei suositeltavaa)?" +StrCpy $UNINSTALL_ABORT "Poistaminen keskeytettiin käyttäjän toimesta" +StrCpy $INIT_NO_QUICK_LAUNCH "Pikakäynnistyksen pikakuvake (-)" +StrCpy $INIT_NO_DESKTOP "Työpöydän pikakuvake (korvaa nykyinen)" +StrCpy $UAC_ERROR_ELEVATE "Kohottaminen ei onnistu, virhe:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Tämä asennusohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen." +StrCpy $INIT_INSTALLER_RUNNING "Asennusohjelma on jo käynnissä." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tämä poisto-ohjelma vaatii ylläpitäjän oikeudet, yritä uudelleen." +StrCpy $UAC_ERROR_LOGON_SERVICE "Kirjautumispalvelu ei ole käynnissä, perutaan!" +StrCpy $INIT_UNINSTALLER_RUNNING "Poisto-ohjelma on jo käynnissä." +StrCpy $SectionGroup_Shortcuts "Pikakuvakkeet" diff --git a/admin/win/nsi/l10n/French.nsh b/admin/win/nsi/l10n/French.nsh new file mode 100644 index 000000000..365f86749 --- /dev/null +++ b/admin/win/nsi/l10n/French.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Afficher les notes de version" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Les processus ${APPLICATION_EXECUTABLE} en cours d’exécution doivent être stoppés avant de poursuivre.$\nVoulez-vous que le programme d’installation s’en charge pour vous ?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Fermeture des processus ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Le processus à stopper n'a pas été trouvé !" +StrCpy $PageReinstall_NEW_Field_1 "Une ancienne version de ${APPLICATION_NAME} est installée sur votre système. Il est recommandé de désinstaller cette version avant de continuer. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer." +StrCpy $PageReinstall_NEW_Field_2 "Désinstaller avant d'installer à nouveau" +StrCpy $PageReinstall_NEW_Field_3 "Ne pas désinstaller" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Déjà installé" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choisissez comment installer ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Une version plus récente de ${APPLICATION_NAME} est déjà installée ! Il n'est pas recommandé d'installer une version plus ancienne. Si vous voulez vraiment installer cette version plus ancienne, il est préférable de d'abord désinstaller la version courante. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} est déjà installé.$\n$\nSélectionnez l'opération que vous souhaitez effectuer et cliquez sur Suivant pour continuer." +StrCpy $PageReinstall_SAME_Field_2 "Ajouter/Réinstaller des composants" +StrCpy $PageReinstall_SAME_Field_3 "Désinstaller ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Désinstaller ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choisir l'opération de maintenance à effectuer." +StrCpy $SEC_APPLICATION_DETAILS "Installation des essentiels de ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Intégration à l'Explorateur Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installation de l'intégration à l'Explorateur Windows..." +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Raccourci programme du menu Démarrer" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Ajout d'un raccourci pour ${APPLICATION_NAME} au menu Démarrer." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Raccourci Bureau" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Création d'un raccourci sur le Bureau" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Raccourci de lancement rapide" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Création d'un raccourci de lancement rapide" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Essentiels de ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Raccourci de ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Raccourci de bureau pour ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Raccourci de lancement rapide de ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Écriture du désinstallateur" +StrCpy $UNINSTALLER_REGISTRY_Detail "Écriture des clefs de registre du désinstallateur" +StrCpy $UNINSTALLER_FINISHED_Detail "Terminé" +StrCpy $UNINSTALL_MESSAGEBOX "Il semble que ${APPLICATION_NAME} ne soit pas installé dans le dossier '$INSTDIR'.$\n$\nVoulez-vous poursuivre (non recommandé) ?" +StrCpy $UNINSTALL_ABORT "Désinstallation interrompue par l'utilisateur" +StrCpy $INIT_NO_QUICK_LAUNCH "Raccourci de lancement rapide (non disponible)" +StrCpy $INIT_NO_DESKTOP "Raccourci bureau (remplace l’existant)" +StrCpy $UAC_ERROR_ELEVATE "Échec d'élévation, erreur :" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Cet installateur requiert les droits administrateur, essayez à nouveau" +StrCpy $INIT_INSTALLER_RUNNING "Une installation est déjà en cours." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ce désinstallateur requiert les droits administrateur, essayez à nouveau" +StrCpy $UAC_ERROR_LOGON_SERVICE "Service de logon non lancé ! Abandon." +StrCpy $INIT_UNINSTALLER_RUNNING "Une désinstallation est déjà en cours." +StrCpy $SectionGroup_Shortcuts "Raccourcis" diff --git a/admin/win/nsi/l10n/Galician.nsh b/admin/win/nsi/l10n/Galician.nsh new file mode 100644 index 000000000..f22209da6 --- /dev/null +++ b/admin/win/nsi/l10n/Galician.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Amosar as notas de publicación" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Atopáronse procesos ${APPLICATION_EXECUTABLE} que teñen que ser detidos.$\nQuere que sexa o instalador quen o(s) deteña?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Matando os procesos ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Non se atopou o proceso para matalo!" +StrCpy $PageReinstall_NEW_Field_1 "No seu sistema hai instalada unha versión anterior de ${APPLICATION_NAME}. Recomendámoslle que desinstale a versión actual antes de instalar. Seleccione a operación que quere realizar e prema en Seguinte para continuar." +StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar" +StrCpy $PageReinstall_NEW_Field_3 "Non desinstalar" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Xa instalado" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolla como quere instalar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Ten instalada unha versión actualizada do ${APPLICATION_NAME}! recomendámoslle que non instale unha versión anterior. Se realmente quere instalar esta versión máis antiga, é preferíbel que desinstale a versión actual antes de instalar. Seleccione a operación que quere realizar e prema en Seguinte para continuar." +StrCpy $PageReinstall_SAME_Field_2 "Engadir/reinstalar compoñentes" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolla a opción de mantemento a realizar." +StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciais." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración con Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando a integración con Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo ao programa no menú de inicio" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Engadindo o acceso directo a ${APPLICATION_NAME} no menú de inicio" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo no escritorio" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando os accesos directos no escritorio" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Acceso de inicio rápido" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando o acceso de inicio rápido" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esenciais." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso directo ao ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Acceso directo no escritorio para " +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Acceso de inicio rápido para ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Escribindo o desinstalador" +StrCpy $UNINSTALLER_REGISTRY_Detail "Escribindo o instalador nas chaves do rexistro" +StrCpy $UNINSTALLER_FINISHED_Detail "Rematado" +StrCpy $UNINSTALL_MESSAGEBOX "Semella que ${APPLICATION_NAME} non está instalado no directorio «$INSTDIR».$\n$\nContinuar aínda así (non recomendado)?" +StrCpy $UNINSTALL_ABORT "A desinstalación foi interrompida polo usuario." +StrCpy $INIT_NO_QUICK_LAUNCH "Acceso de inicio rápido (n/d)" +StrCpy $INIT_NO_DESKTOP "Atallo no escritorio (sobrescribe o existente)" +StrCpy $UAC_ERROR_ELEVATE "Non foi posíbel elevalo, erro:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este instalador require acceso de administrador, ténteo de novo" +StrCpy $INIT_INSTALLER_RUNNING "O instalador xa está en execución." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador require acceso de administrador, ténteo de novo" +StrCpy $UAC_ERROR_LOGON_SERVICE "O servizo de acceso non está en execución, cancelando!" +StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador xa está en execución." +StrCpy $SectionGroup_Shortcuts "Atallos" +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue." diff --git a/admin/win/nsi/l10n/German.nsh b/admin/win/nsi/l10n/German.nsh new file mode 100644 index 000000000..8730acf4d --- /dev/null +++ b/admin/win/nsi/l10n/German.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Release-Informationen anzeigen" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "${APPLICATION_EXECUTABLE} Prozess(e) gefunden, die gestoppt werden müssen.$\nWollen Sie, dass der Installer diese nun für Sie stoppt?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Stoppe ${APPLICATION_EXECUTABLE} Prozess(e)." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Prozess zum Beenden nicht gefunden!" +StrCpy $PageReinstall_NEW_Field_1 "Eine ältere Version von ${APPLICATION_NAME} ist auf Ihrem System installiert. Es wird empfohlen, diese Version zunächst zu entfernen. Wählen Sie unter folgenden Vorgehenweisen und wählen Sie $\"Weiter$\"." +StrCpy $PageReinstall_NEW_Field_2 "Vor der Installation entfernen" +StrCpy $PageReinstall_NEW_Field_3 "Nicht entfernen" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Bereits installiert" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Wählen Sie die Methode, mit der sie ${APPLICATION_NAME} installieren wollen." +StrCpy $PageReinstall_OLD_Field_1 "Eine neuere Version von ${APPLICATION_NAME} ist bereits installiert! Es wird nicht empfohlen, eine ältere Version zu installieren. Wollen Sie dies trotzdem tun, so sollten Sie die aktuelle Version zunächst entfernen. Wählen Sie eine Vorgehensweise und wählen dann $\"Weiter$\"." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ist bereits installiert. $\nWählen Sie eine Vorgehensweise und klicken Sie auf $\"Weiter$\"." +StrCpy $PageReinstall_SAME_Field_2 "Komponenten hinzufügen" +StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} entfernen" +StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} entfernen" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wählen Sie zur Ausführung die Wartungsoption." +StrCpy $SEC_APPLICATION_DETAILS "Installiere ${APPLICATION_NAME} Basis." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration in den Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installiere Integration in den Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Installiere Verknüpfung im Programmmenü" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Füge Verknüpfung für ${APPLICATION_NAME} dem Startmenü hinzu." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop-Verknüpfung" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Erstellt Desktop-Verknüpfung" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Schnellstart-Verknüpfung" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Erstelle Schnellstart-Verknüpfung" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} Basis." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} Verknüfung." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Desktop-Verknüpfung für ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Schnellstart-Verknüpfung für ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Schreibe Uninstaller" +StrCpy $UNINSTALLER_REGISTRY_Detail "Schreibe Registrierungseinträge" +StrCpy $UNINSTALLER_FINISHED_Detail "Abgeschlossen" +StrCpy $UNINSTALL_MESSAGEBOX "Es scheint, als ob ${APPLICATION_NAME} nicht im Verzeichnis '$INSTDIR' installiert ist.$\n$\nTrotzdem fortfahren (nicht empfohlen)?" +StrCpy $UNINSTALL_ABORT "Deinstallation vom Benutzer abgebrochen" +StrCpy $INIT_NO_QUICK_LAUNCH "Schnellstart-Verknüpfung (Nicht verfügbar)" +StrCpy $INIT_NO_DESKTOP "Desktop-Verknüpfung (überschreibt vorhandene)" +StrCpy $UAC_ERROR_ELEVATE "Rechte können nicht erhöht werden, Fehler:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dieses Installationsprogramm erfordert Administrator-Rechte, bitte erneut versuchen" +StrCpy $INIT_INSTALLER_RUNNING "Das Installationsprogramm wird bereits ausgeführt." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Das Deinstallationsprogramm erfordert Administrator-Rechte. Bitte erneut versuchen." +StrCpy $UAC_ERROR_LOGON_SERVICE "Anmeldedienst läuft nicht, abbruch!" +StrCpy $INIT_UNINSTALLER_RUNNING "Das Deinstallationsprogramm wird bereits ausgeführt." +StrCpy $SectionGroup_Shortcuts "Verknüpfungen" diff --git a/admin/win/nsi/l10n/Greek.nsh b/admin/win/nsi/l10n/Greek.nsh new file mode 100644 index 000000000..8b3c893bb --- /dev/null +++ b/admin/win/nsi/l10n/Greek.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Εμφάνιση σημειώσεων έκδοσης" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Βρέθηκε η(οι) διεργασία(ες) ${APPLICATION_EXECUTABLE} η(οι) οποία(ες) θα πρέπει να τερματιστεί(ούν).$\nΘα θέλατε να την(τις) τερματίσει ο βοηθός εγκατάστασης για εσάς;" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Τερματισμός διεργασιών ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Δεν βρέθηκε διεργασία για βίαιο τερματισμό!" +StrCpy $PageReinstall_NEW_Field_1 "Μια παλαιότερη έκδοση της ${APPLICATION_NAME} είναι εγκατεστημένη στο σύστημά σας. Είναι προτεινόμενο να απεγκαταστήσετε την τρέχουσα έκδοση πριν την εγκατάσταση. Επιλέξτε τη διαδικασία που επιθυμείτε να εκτελέσετε και πατήστε Επόμενο για να συνεχίσετε." +StrCpy $PageReinstall_NEW_Field_2 "Απεγκατάσταση πριν την εγκατάσταση" +StrCpy $PageReinstall_NEW_Field_3 "Να μην απεγκατασταθεί" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ήδη εγκατεστημένη" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Επιλέξτε πώς θέλετε να εγκαταστήσετε την ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Μια νεώτερη έκδοση της ${APPLICATION_NAME} είναι ήδη εγκατεστημένη! Δεν συνίσταται να εγκαταστείσετε μια παλαιότερη έκδοση. Εάν θέλετε πραγματικά να εγκαταστήσετε αυτήν την παλαιότερη έκδοση, είναι καλύτερο να απεγκαταστήσετε την τρέχουσα έκδοση πρώτα. Επιλέξτε τη διαδικασία που επιθυμείτε να εκτελέσετε και επιλέξτε Επόμενο για να συνεχίσετε." +StrCpy $PageReinstall_SAME_Field_1 "Η ${APPLICATION_NAME} ${VERSION} είναι ήδη εγκατεστημένη.$\n$\nΕπιλέξτε τη λειτουργία που επιθυμείτε να εκτελέσετε και επιλέξτε Επόμενο για να συνεχίσετε." +StrCpy $PageReinstall_SAME_Field_2 "Προσθήκη/ Επανεγκατάσταση συνιστωσών" +StrCpy $PageReinstall_SAME_Field_3 "Απεγκατάσταση ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Απεγκατάσταση ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Επιλέξτε την επιλογή συντήρησης που θα πραγματοποιηθεί." +StrCpy $SEC_APPLICATION_DETAILS "Εγκατάσταση βάσης ${APPLICATION_NAME} σε εξέλιξη." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Ενσωμάτωση στην Εξερεύνηση των Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Εγκατάσταση ενσωμάτωσης στην Εξερεύνηση των Windows" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Συντόμευση στο Αρχικό Μενού" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Προσθήκη συντόμευσης για την ${APPLICATION_NAME} στο Αρχικό Μενού." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Συντόμευση επιφάνειας εργασίας" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Δημιουργία Συντομεύσεων στην Επιφάνεια Εργασίας" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Συντόμευση Ταχείας Εκκίνησης" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Δημιουργία Συντόμευσης Ταχείας Εκκίνησης" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Βάση ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Συντόμευση ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Συντόμευση επιφάνειας εργασίας της ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Συντόμευση Ταχείας Εκκίνησης της ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Εγγραφή Εφαρμογής Απεγκατάστασης" +StrCpy $UNINSTALLER_REGISTRY_Detail "Εγγραφή Κλειδιών μητρώου (Registry) της Εφαρμογής Εγκατάστασης" +StrCpy $UNINSTALLER_FINISHED_Detail "Ολοκληρώθηκε" +StrCpy $UNINSTALL_MESSAGEBOX "Δεν φαίνεται να είναι εγκατεστημένηη η ${APPLICATION_NAME} στον κατάλογο '$INSTDIR'.$\n$\nΣυνέχιση παρ' όλα αυτά (δεν συνίσταται);" +StrCpy $UNINSTALL_ABORT "Η απεγκατάσταση ματαιώθηκε από το χρήστη" +StrCpy $INIT_NO_QUICK_LAUNCH "Συντόμευση Ταχείας Εκκίνησης (Μ/Δ)" +StrCpy $INIT_NO_DESKTOP "Συντόμευση Επιφάνειας Εργασίας (αντικαθιστά υπάρχουσα)" +StrCpy $UAC_ERROR_ELEVATE "Αδυναμία ανύψωσης, σφάλμα:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Αυτή η εφαρμογή εγκατάστασης απαιτεί πρόσβαση διαχειριστή, δοκιμάστε ξανά" +StrCpy $INIT_INSTALLER_RUNNING "Η εφαρμογή εγκατάστασης λειτουργεί ήδη." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Αυτή η εφαρμογή απεγκατάστασης απαιτεί πρόσβαση διαχειριστή, δοκιμάστε ξανά" +StrCpy $UAC_ERROR_LOGON_SERVICE "Η υπηρεσία σύνδεσης δεν εκτελείται, ακύρωση!" +StrCpy $INIT_UNINSTALLER_RUNNING "Η εφαρμογή απεγκατάστασης λειτουργεί ήδη." +StrCpy $SectionGroup_Shortcuts "Συντομεύσεις" diff --git a/admin/win/nsi/l10n/Hungarian.nsh b/admin/win/nsi/l10n/Hungarian.nsh new file mode 100644 index 000000000..9f2492693 --- /dev/null +++ b/admin/win/nsi/l10n/Hungarian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Kiadási jegyzetek megtekintése" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "A következő folyamatot(okat) meg kell állítani ${APPLICATION_EXECUTABLE}.$\nSzeretné ha a telepítő program megállítani ezeket a folyamatokat?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "${APPLICATION_EXECUTABLE} folyamat kilövése." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "A kilövésre szánt folyamat nem található!" +StrCpy $PageReinstall_NEW_Field_1 "Az ${APPLICATION_NAME} alkalmazás egy régebbi verziója telepítve van a rendszeren. Ajánlott a régi alkalmazás eltávolítása mielőtt a legfrissebb verziót telepítené. Válassza ki milyen műveletet szeretne végrehajtani, és nyomja meg a $\"Következő$\" gombot a folytatáshoz." +StrCpy $PageReinstall_NEW_Field_2 "Eltávolítás telepítés előtt" +StrCpy $PageReinstall_NEW_Field_3 "Ne távolítsa el" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Már telepítve" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Válassza ki, hogy szeretné telepíteni a következő alkalmazást: ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Az ${APPLICATION_NAME} alkalmazás egy újabb verziója már megtalálható a rendszeren. Nem ajánlott egy régebbi verzió telepítése. Ha valóban szeretné a régebbi verziót telepíteni, akkor ajánlott a jelenleg telepített verzió eltávolítása. Válassza ki milyen műveletet szeretne végrehajtani, és nyomja meg a $\"Következő$\" gombot a folytatáshoz." +StrCpy $PageReinstall_SAME_Field_1 "Az ${APPLICATION_NAME} alkalmazás ${VERSION} verziója már telepítve van.$↩$\nKérjük válaszd ki milyen műveletet szeretnél végrehajtani, és nyomd meg a „Következő” gombot." +StrCpy $PageReinstall_SAME_Field_2 "Komponens hozzáadása/újratelepítése" +StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} eltávolítása" +StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} eltávolítása" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Válassza ki milyen karbantartási műveletet szeretne elvégezni." +StrCpy $SEC_APPLICATION_DETAILS "Az ${APPLICATION_NAME} alkalmazás lényeges komponenseinek telepítése." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows Explorer integráció" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows Explorer integráció telepítése" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menü parancsikonok" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "A ${APPLICATION_NAME} parancsikon hozzáadása a Start Menühöz" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Asztali parancsikon" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Asztali parancsikon létrehozása" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Gyorsindító eszköztár parancsikon" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Gyorsindító eszköztár parancsikon létrehozása" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} lényeges komponensek." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} parancsikon" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Asztali parancsikon a ${APPLICATION_NAME} alkalmazásnak." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Gyorsindítás eszköztár parancsikon a ${APPLICATION_NAME} alkalmazásnak." +StrCpy $UNINSTALLER_FILE_Detail "Elltávolító írása" +StrCpy $UNINSTALLER_REGISTRY_Detail "Telepítési registry kulcsok írása" +StrCpy $UNINSTALLER_FINISHED_Detail "Befejezve!" +StrCpy $UNINSTALL_MESSAGEBOX "Nem sikerült az ${APPLICATION_NAME} alkalmazás telepítése a '$INSTDIR' könyvtárba.$\n$\nSzeretné mindenképpen folytatni (nem ajánlott)?" +StrCpy $UNINSTALL_ABORT "Az eltávolítást a felhasználó megszakította" +StrCpy $INIT_NO_QUICK_LAUNCH "Gyorsindító hivatkozás (N/A)" +StrCpy $INIT_NO_DESKTOP "Asztali hivatkozás (felülírja a meglévőt)" +StrCpy $UAC_ERROR_ELEVATE "Nem sikerült felemelni, hiba:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "A telepítő futtatásához adminisztrátori hozzáférés szükséges, próbálja újra." +StrCpy $INIT_INSTALLER_RUNNING "A telepítő már fut." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Az eltávolító futtatásához adminisztrátori hozzáférés szükséges, próbálja újra." +StrCpy $UAC_ERROR_LOGON_SERVICE "A bejelentkező szolgáltatás nem fut, megszakítás!" +StrCpy $INIT_UNINSTALLER_RUNNING "Az eltávolító már fut." +StrCpy $SectionGroup_Shortcuts "Parancsikonok" diff --git a/admin/win/nsi/l10n/Italian.nsh b/admin/win/nsi/l10n/Italian.nsh new file mode 100644 index 000000000..d80d1b194 --- /dev/null +++ b/admin/win/nsi/l10n/Italian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostra le note di rilascio" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Trovati ${APPLICATION_EXECUTABLE} processi che dovrebbero essere fermati.$\nVuoi che il programma di installazione li fermi al posto tuo?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Sto terminando ${APPLICATION_EXECUTABLE} processi." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Il processo da terminare non è stato trovato!" +StrCpy $PageReinstall_NEW_Field_1 "Una versione più datata di ${APPLICATION_NAME} è installata sul tuo sistema. Si consiglia di disinstallare la versione attuale prima di installare. Seleziona l'operazione da eseguire e fai clic su Avanti per continuare." +StrCpy $PageReinstall_NEW_Field_2 "Disinstalla prima di installare" +StrCpy $PageReinstall_NEW_Field_3 "Non disinstallare" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Già installato" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Scegli come desideri installare ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Una versione più recente di ${APPLICATION_NAME} è già installata! Non è consigliabile installare una versione più vecchia. Se vuoi davvero installare una versione più vecchia, ti consigliamo di rimuovere prima la versione attuale. Scegli l'operazione da eseguire e fai clic su Avanti per continuare." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} è già installato.$\n$\nSeleziona l'operazione che desideri eseguire e fai clic su Avanti per continuare.." +StrCpy $PageReinstall_SAME_Field_2 "Aggiungi/Reinstalla i componenti" +StrCpy $PageReinstall_SAME_Field_3 "Disinstalla ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Disinstalla ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Scegli l'opzione di manutenzione da eseguire." +StrCpy $SEC_APPLICATION_DETAILS "Installazione degli elementi fondamentali di ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integrazione con Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installazione dell'integrazione con Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Scorciatoia di programma menu Start" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Aggiunta della scorciatoia per ${APPLICATION_NAME} al menu Start." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Scorciatoia del desktop" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creazione delle scorciatoie del desktop" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Scorciatoia dell'avvio veloce" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creazione della scorciatoia dell'avvio veloce" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Oggetti fondamentali di ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Scorciatoia di ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Scorciatoia del desktop per ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Scorciatoia per ${APPLICATION_NAME} dell'avvio veloce." +StrCpy $UNINSTALLER_FILE_Detail "Creazione del programma di disinstallazione" +StrCpy $UNINSTALLER_REGISTRY_Detail "Scrittura delle chiavi di registro del programma di installazione" +StrCpy $UNINSTALLER_FINISHED_Detail "Completato" +StrCpy $UNINSTALL_MESSAGEBOX "Non sembra che ${APPLICATION_NAME} sia installato nella cartella '$INSTDIR'.$$\nVuoi continuare comunque (non consigliato)?" +StrCpy $UNINSTALL_ABORT "Disinstallazione interrotta dall'utente" +StrCpy $INIT_NO_QUICK_LAUNCH "Scorciatoia dell'avvio veloce (N/D)" +StrCpy $INIT_NO_DESKTOP "Scorciatoia del desktop (sovrascrivi se esistente)" +StrCpy $UAC_ERROR_ELEVATE "Impossibile elevare, errore:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Il programma di installazione necessita delle credenziali di amministrazione, riprova" +StrCpy $INIT_INSTALLER_RUNNING "Il programma di installazione è già in esecuzione." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Il programma di disinstallazione necessita delle credenziali di amministrazione, riprova" +StrCpy $UAC_ERROR_LOGON_SERVICE "Il servizio di accesso non è in esecuzione, interruzione in corso!" +StrCpy $INIT_UNINSTALLER_RUNNING "Il programma di disinstallazione è già in esecuzione." +StrCpy $SectionGroup_Shortcuts "Scorciatoie" diff --git a/admin/win/nsi/l10n/Japanese.nsh b/admin/win/nsi/l10n/Japanese.nsh new file mode 100644 index 000000000..303a953cb --- /dev/null +++ b/admin/win/nsi/l10n/Japanese.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "リリースノートを表示" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "${APPLICATION_EXECUTABLE} のプロセスを終了する必要があります。$\nインストーラーがそのプロセスを停止してもよろしいですか?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "${APPLICATION_EXECUTABLE} プロセスを停止しています。" +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "終了するプロセスがありません" +StrCpy $PageReinstall_NEW_Field_1 "システムに ${APPLICATION_NAME} の旧バージョンがインストールされています。$\n旧バージョンをアンインストールし、最新バージョンをインストールするのをお勧めします。$\nオペレーションを選択し、次へをクリックする。" +StrCpy $PageReinstall_NEW_Field_2 "インストール前にアンインストールする" +StrCpy $PageReinstall_NEW_Field_3 "アンインストールしない" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "インストール済" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "${APPLICATION_NAME} のインストール方法を選択する" +StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME} の最新バージョンがすでにインストールされています。$\n旧バージョンのインストールはお勧めしません。旧バージョンのインストールが本当に必要な場合は、まず最新バージョンをアンインストールしてから、旧バージョンをインストールしてください。$\nオペレーションを選択し、次へをクリックする。" +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} は、${VERSION} がすでにインストールされています。$\n$\n実行したい操作を選択して、次へをクリックしてください。" +StrCpy $PageReinstall_SAME_Field_2 "追加/再インストールコンポーネント" +StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} をアンインストール" +StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} をアンインストール" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "実行するには、メンテナンスオプションを選択してください。" +StrCpy $SEC_APPLICATION_DETAILS "${APPLICATION_NAME} の重要なパッケージをインストール中" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows エクスプローラーへの統合" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows エクスプローラーへの統合をインストールしています。" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "スタートメニューショートカット" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "スタートメニューに${APPLICATION_NAME} のショートカットの追加" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "デスクトップショートカット" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "デスクトップショートカット作成" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "クイック起動ショートカット" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "クイック起動ショートカットを作成" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} の重要なパッケージ" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} のショートカット" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "${APPLICATION_NAME} のデスクトップショートカット" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "${APPLICATION_NAME} のクイック起動ショートカット" +StrCpy $UNINSTALLER_FILE_Detail "アンインストーラーを書き込み" +StrCpy $UNINSTALLER_REGISTRY_Detail "インストーラーのレジストリキーの書き込み" +StrCpy $UNINSTALLER_FINISHED_Detail "終了" +StrCpy $UNINSTALL_MESSAGEBOX "${APPLICATION_NAME} は'$INSTDIR'.$$  ディレクトリにインストールされていません。エラーを無視し、進みますか (非推奨)?" +StrCpy $UNINSTALL_ABORT "アンインストールは、ユーザーによって中止されました。" +StrCpy $INIT_NO_QUICK_LAUNCH "クイック起動ショートカット(N/A)" +StrCpy $INIT_NO_DESKTOP "デスクトップにショートカットを作成(すでにある場合は上書き)" +StrCpy $UAC_ERROR_ELEVATE "エスカレーション不可です、エラー:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "このインストーラーは、管理者権限が必要です。インストールを再試行してください。" +StrCpy $INIT_INSTALLER_RUNNING "インストーラーは、すでに起動しています。" +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "このアンインストーラーは、管理者権限が必要です。アンインストールを再試行してください。" +StrCpy $UAC_ERROR_LOGON_SERVICE "ログオンサービスが動いていません。中止します。" +StrCpy $INIT_UNINSTALLER_RUNNING "アンインストーラーは、すでに起動しています。" +StrCpy $SectionGroup_Shortcuts "ショートカット" diff --git a/admin/win/nsi/l10n/Norwegian.nsh b/admin/win/nsi/l10n/Norwegian.nsh new file mode 100644 index 000000000..dc2a9f069 --- /dev/null +++ b/admin/win/nsi/l10n/Norwegian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Vis versjonsmerknader" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Fant ${APPLICATION_EXECUTABLE}-prosess(er) som må stoppes.$\nVil du at installasjonsprogrammet skal stoppe dem for deg?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Terminerer ${APPLICATION_EXECUTABLE}-prosesser." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Fant ikke prosess som skulle termineres!" +StrCpy $PageReinstall_NEW_Field_1 "En eldre versjon av ${APPLICATION_NAME} er installert på systemet ditt. Det anbefales at du avinstallerer den versjonen før installering av ny versjon. Velg hva du vil gjøre og klikk Neste for å fortsette." +StrCpy $PageReinstall_NEW_Field_2 "Avinstaller før installering" +StrCpy $PageReinstall_NEW_Field_3 "Ikke avinstaller" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Allerede installert" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Velg hvordan du vil installere ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "En nyere versjon av ${APPLICATION_NAME} er allerede installert! Det anbefales ikke at du installerer en eldre versjon. Hvis du virkelig ønsker å installere denne eldre versjonen, er det bedre å avinstallere gjeldende versjon først. Velg hva du vil gjøre og klikk Neste for å fortsette." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} er installert allerede.$\n$\nVelg hva du ønsker å gjøre og klikk Neste for å fortsette." +StrCpy $PageReinstall_SAME_Field_2 "Legg til/installer komponenter på nytt" +StrCpy $PageReinstall_SAME_Field_3 "Avinstaller ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstaller ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Velg hva slags vedlikehold som skal utføres." +StrCpy $SEC_APPLICATION_DETAILS "Installerer ${APPLICATION_NAME} grunnleggende." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integrering med Windows Utforsker" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installerer integrering med Windows Utforsker" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Snarvei i Start-menyen" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Legger til snarvei for ${APPLICATION_NAME} i Start-menyen." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Snarvei på skrivebordet" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Oppretter snarveier på skrivebordet" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Snarvei i Hurtigstart" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Oppretter snarvei i Hurtigstart" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} grunnleggende." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}-snarvei." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Skrivebordssnarvei for ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Hurtigstart-snarvei for ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Skriver Avinstallasjonsprogram." +StrCpy $UNINSTALLER_REGISTRY_Detail "Skriver registernøkler for installasjonsprogrammet" +StrCpy $UNINSTALLER_FINISHED_Detail "Ferdig" +StrCpy $UNINSTALL_MESSAGEBOX "Det ser ikke ut som ${APPLICATION_NAME} er installert i mappe '$INSTDIR'.$\n$\nFortsett likevel (ikke anbefalt)?" +StrCpy $UNINSTALL_ABORT "Avinstallering avbrutt av bruker" +StrCpy $INIT_NO_QUICK_LAUNCH "Hurtigstart-snarvei (I/T)" +StrCpy $INIT_NO_DESKTOP "Snarvei på skrivebordet (skriver over eksisterende)" +StrCpy $UAC_ERROR_ELEVATE "Klarte ikke å heve tilgangsnivå. Feil: " +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dette installasjonsprogrammet krever administrasjonstilgang. Prøv igjen" +StrCpy $INIT_INSTALLER_RUNNING "Installasjonsprogrammet kjører allerede." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Avinstallasjonsprogrammet krever administrasjonstilgang. Prøv igjen" +StrCpy $UAC_ERROR_LOGON_SERVICE "Påloggingstjenesten kjører ikke, avbryter!" +StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallasjonsprogrammet kjører allerede." +StrCpy $SectionGroup_Shortcuts "Snarveier" diff --git a/admin/win/nsi/l10n/Polish.nsh b/admin/win/nsi/l10n/Polish.nsh new file mode 100644 index 000000000..85e9e6e82 --- /dev/null +++ b/admin/win/nsi/l10n/Polish.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Pokaż informacje o wydaniu" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Znaleziono proces(y) ${APPLICATION_EXECUTABLE}, które muszą być zatrzymane $\nCzy chcesz, aby instalator zatrzymał je za Ciebie?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Zamykam proces ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Nie znaleziono procesu do zatrzymania!" +StrCpy $PageReinstall_NEW_Field_1 "W Twoim systemie jest zainstalowana starsza wersja ${APPLICATION_NAME}. Zaleca się odinstalowanie aktualnej wersji przed instalacją. Wybierz operację, którą chcesz wykonać i kliknij 'Dalej', aby kontynuować." +StrCpy $PageReinstall_NEW_Field_2 "Odinstaluj przed instalacją" +StrCpy $PageReinstall_NEW_Field_3 "Nie odinstalowuj" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Już zainstalowane" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Wybierz, jak chcesz zainstalować ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Nowsza wersja ${APPLICATION_NAME} jest już zainstalowana! Nie zaleca się instalowania starszej wersji. Jeśli koniecznie chcesz zainstalować starszą wersję, najpierw odinstaluj bieżącą wersję. Wybierz operację, którą chcesz wykonać i kliknij 'Dalej', aby kontynuować." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} jest już zainstalowany.$\nWybierz operację, którą chcesz wykonać i kliknij 'Dalej', aby kontynuować." +StrCpy $PageReinstall_SAME_Field_2 "Dodaj/zainstaluj ponownie komponenty" +StrCpy $PageReinstall_SAME_Field_3 "Odinstaluj ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstaluj ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wybierz opcję konserwacji do wykonania." +StrCpy $SEC_APPLICATION_DETAILS "Instalowanie niezbędnych plików ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integracja z Eksploratorem Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalowanie integracji dla Eksploratora Windows" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Skrót w Menu Start" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Dodaję skrót do ${APPLICATION_NAME} w Menu Start." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrót na Pulpicie" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Tworzenie skrótów na Pulpicie" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Skrót na Pasku Zadań" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Tworzenie skrótu na Pasku Zadań" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Niezbędne pliki ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Skrót do ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Skrót na Pulpicie do ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Skrót na Pasku Zadań do ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Tworzenie deinstalatora" +StrCpy $UNINSTALLER_REGISTRY_Detail "Tworzenie wpisów w rejestrze" +StrCpy $UNINSTALLER_FINISHED_Detail "Skończone" +StrCpy $UNINSTALL_MESSAGEBOX "Nie wygląda na to, że ${APPLICATION_NAME} jest zainstalowany w katalogu '$INSTDIR'.$$ Kontynuować mimo tego (niezalecane)?" +StrCpy $UNINSTALL_ABORT "Odinstalowywanie przerwane przez użytkownika" +StrCpy $INIT_NO_QUICK_LAUNCH "Skrót na Pasku Zadań (NIE DOTYCZY)" +StrCpy $INIT_NO_DESKTOP "Skrót na Pulpicie (nadpisuje istniejące)" +StrCpy $UAC_ERROR_ELEVATE "Nie można podwyższyć, błąd:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Ten instalator wymaga dostępu administratora, spróbuj ponownie." +StrCpy $INIT_INSTALLER_RUNNING "Instalator jest już uruchomiony." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ten deinstalator wymaga dostępu administratora, spróbuj ponownie." +StrCpy $UAC_ERROR_LOGON_SERVICE "Proces logowania nie jest uruchomiony, przerywam!" +StrCpy $INIT_UNINSTALLER_RUNNING "Deinstalator jest już uruchomiony." +StrCpy $SectionGroup_Shortcuts "Skróty" diff --git a/admin/win/nsi/l10n/Portuguese.nsh b/admin/win/nsi/l10n/Portuguese.nsh new file mode 100644 index 000000000..48aa5af5e --- /dev/null +++ b/admin/win/nsi/l10n/Portuguese.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Encontrados ${APPLICATION_EXECUTABLE} processo(s) em execução que precisa(m) de ser interrompido(s).$\nDeseja que o instalador o(s) termine por si?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar os processos de ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado o processo para terminar!" +StrCpy $PageReinstall_NEW_Field_1 "Está instalada no sistema uma versão antiga de ${APPLICATION_NAME}. É recomendado que desinstale a versão atual antes de instalar a mais recente. Selecione a operação que deseja executar e clique em $\"Seguinte$\" para continuar." +StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar" +StrCpy $PageReinstall_NEW_Field_3 "Não desinstale" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já instalado" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como pretende instalar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Já está instalada uma versão mais recente de ${APPLICATION_NAME}! Não é recomendada a instalação de uma versão mais antiga. Se realmente desejar instalar esta versão antiga, aconselha-se que desinstale primeiro a versão atual. Selecione a operação que deseja executar e clique em $\"Seguinte$\" para continuar." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalada.$\nSelecione a operação que deseja realizar e clique em 'Seguinte' para continuar." +StrCpy $PageReinstall_SAME_Field_2 "Adicionar/Reinstalar Componentes" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de manutenção a realizar." +StrCpy $SEC_APPLICATION_DETAILS "A instalar o essencial de ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integração para Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "A instalar integração para Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Atalho do progama no Menu Iniciar" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "A adicionar o atalho de ${APPLICATION_NAME} no Menu Iniciar." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Atalho da área de trabalho" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "A criar atalhos na área de trabalho" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atalho de início rápido" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "A criar atalho de início rápido" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "O essencial de ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Atalho de ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Atalho do ambiente de trabalho para ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Atalho de início rápido de ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "A escrever o Desinstalador" +StrCpy $UNINSTALLER_REGISTRY_Detail "A escrever chaves de registo do instalador" +StrCpy $UNINSTALLER_FINISHED_Detail "Terminado" +StrCpy $UNINSTALL_MESSAGEBOX "Não parece que a aplicação ${APPLICATION_NAME} esteja instalada no diretório '$INSTDIR'.$\n$\nContinuar na mesma (não recomendado)?" +StrCpy $UNINSTALL_ABORT "Desinstalação cancelada pelo utilizador" +StrCpy $INIT_NO_QUICK_LAUNCH "Atalho de Início Rápido (N/A)" +StrCpy $INIT_NO_DESKTOP "Atalho do Ambiente de Trabalho (sobrepõe o existente)" +StrCpy $UAC_ERROR_ELEVATE "Incapaz de elevar, erro:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este instalador precisa de permissões de administrador, tente novamente" +StrCpy $INIT_INSTALLER_RUNNING "O instalador já está em execução." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador requer permissões de administrador, tente novamente" +StrCpy $UAC_ERROR_LOGON_SERVICE "O serviço do início de sessão não está em execução, a abortar!" +StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador já está em execução." +StrCpy $SectionGroup_Shortcuts "Atalhos" diff --git a/admin/win/nsi/l10n/PortugueseBR.nsh b/admin/win/nsi/l10n/PortugueseBR.nsh new file mode 100644 index 000000000..74cc9590a --- /dev/null +++ b/admin/win/nsi/l10n/PortugueseBR.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Encontrados ${APPLICATION_EXECUTABLE} processo(s) que precisam ser interrompidos.$\nVocê quer que o instalador pare esses processos para você?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Desativando ${APPLICATION_EXECUTABLE} processos." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Processo para eliminar não encontrado!" +StrCpy $PageReinstall_NEW_Field_1 "Uma versão mais antiga de ${APPLICATION_NAME} está instalado em seu sistema. É recomendado que você desinstale a versão atual antes de instalar. Selecione a operação que deseja executar e clique em Avançar para continuar." +StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar" +StrCpy $PageReinstall_NEW_Field_3 "Não desinstale" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já Instalado" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como você deseja instalar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "A versão mais recente do ${APPLICATION_NAME} já está instalado! Não é recomendado que você instale uma versão mais antiga. Se você realmente deseja instalar esta versão mais antiga, é melhor desinstalar a versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalado.$\n$\nSelecione a operação que você quer realizar e clique Próximo para continuar." +StrCpy $PageReinstall_SAME_Field_2 "Adicionar/reinstalar componentes" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de realizar manutenção." +StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} fundamentos." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integração para Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalação de Integração para Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Menu Iniciar Programa Atalho" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Adicionando atalho para ${APPLICATION_NAME} ao Menu Iniciar." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Atalho Desktop" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Criando Atalhos de Desktop" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atalho Rápido" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Criando Atalho Rápido" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esseciais." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} atalho." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Atalho Desktop para ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Atalho Rápido para ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Gravando Desinstalador" +StrCpy $UNINSTALLER_REGISTRY_Detail "Gravando Chaves de Registro do Inslalador" +StrCpy $UNINSTALLER_FINISHED_Detail "Finalizado" +StrCpy $UNINSTALL_MESSAGEBOX "Não parece que ${APPLICATION_NAME} está instalado no diretório '$INSTDIR'.$\n$\nContinuar assim mesmo (não recomendado)?" +StrCpy $UNINSTALL_ABORT "Desinstalação abortada pelo usuário" +StrCpy $INIT_NO_QUICK_LAUNCH "Atalho de Inicialização Rápida (N/A)" +StrCpy $INIT_NO_DESKTOP "Atalho Desktop (substitui os existente)" +StrCpy $UAC_ERROR_ELEVATE "Incapaz de elevar, erro:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este programa de instalação requer acesso de administrador, tente novamente" +StrCpy $INIT_INSTALLER_RUNNING "O instalador já está em execução." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador requer acesso de administrador, tente novamente" +StrCpy $UAC_ERROR_LOGON_SERVICE "O serviço de logon não está sendo executado, abortando!" +StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador já está em execução." +StrCpy $SectionGroup_Shortcuts "Atalhos" diff --git a/admin/win/nsi/l10n/Russian.nsh b/admin/win/nsi/l10n/Russian.nsh new file mode 100644 index 000000000..5e228e6bf --- /dev/null +++ b/admin/win/nsi/l10n/Russian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Показать примечания к выпуску" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Обнаружен процесс ${APPLICATION_EXECUTABLE}, который требуется остановить.$\nВы хотите чтобы программа установки сделала это самостоятельно?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Завершение процессов ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Процессы для завершения не найдены!" +StrCpy $PageReinstall_NEW_Field_1 "Обнаружена более старая версия ${APPLICATION_NAME}. Рекомендуется удалить её перед установкой. Выберите желаемое действие и нажмите Далее для продолжения." +StrCpy $PageReinstall_NEW_Field_2 "Удалить перед установкой" +StrCpy $PageReinstall_NEW_Field_3 "Не устанавливать" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Уже установлено" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Выберите, как вы хотите установить ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Новая версия ${APPLICATION_NAME} уже установлена​​! Не рекомендуется устанавливать старую версию. Если вы действительно хотите установить эту старую версию, то сначала лучше удалить текущую версию. Выберите желаемое действие и нажмите Далее для продолжения." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} уже установлен.$\n$\nУкажите действие и нажмите Далее для продолжения." +StrCpy $PageReinstall_SAME_Field_2 "Добавить/Переустановить компоненты" +StrCpy $PageReinstall_SAME_Field_3 "Удалить ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Удалить ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Выберите опцию обслуживания для исполнения." +StrCpy $SEC_APPLICATION_DETAILS "Установка базовых компонентов ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Интеграция для проводника Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Установка интеграции с проводником Windows" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлык в меню Пуск" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Добавление ярлыка ${APPLICATION_NAME} в меню Пуск" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлык на рабочем столе" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Создание ярлыков на рабочем столе" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Ярлык в меню быстрого запуска" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Создание ярлыка в меню быстрого запуска" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Базовые компоненты ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Ярлык приложения ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Ярлык на рабочем столе для ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Ярлык в меню быстрого запуска для ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Сохранение деинсталлятора" +StrCpy $UNINSTALLER_REGISTRY_Detail "Запись ключей реестра установщика" +StrCpy $UNINSTALLER_FINISHED_Detail "Завершено" +StrCpy $UNINSTALL_MESSAGEBOX "Похоже, что приложение ${APPLICATION_NAME} не установлено в каталог '$INSTDIR'.$\nВсе равно продолжить (не рекомендуется)?" +StrCpy $UNINSTALL_ABORT "Удаление отменено пользователем" +StrCpy $INIT_NO_QUICK_LAUNCH "Ярлык быстрого запуска (не доступен)" +StrCpy $INIT_NO_DESKTOP "Ярлык на рабочем столе (перезапись существующего)" +StrCpy $UAC_ERROR_ELEVATE "Невозможно повысить привилегии, ошибка:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Этому установщику требуются права администратора, попробуйте ещё раз" +StrCpy $INIT_INSTALLER_RUNNING "Установщик уже запущен." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Этому деинсталлятору требуются права администратора, попробуйте ещё раз" +StrCpy $UAC_ERROR_LOGON_SERVICE "Служба входа в систему не запущена, прерывание!" +StrCpy $INIT_UNINSTALLER_RUNNING "Программа удаления уже выполняется." +StrCpy $SectionGroup_Shortcuts "Ярлыки" diff --git a/admin/win/nsi/l10n/SimpChinese.nsh b/admin/win/nsi/l10n/SimpChinese.nsh new file mode 100644 index 000000000..76ce525b8 --- /dev/null +++ b/admin/win/nsi/l10n/SimpChinese.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "查看版本日志" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "有 ${APPLICATION_EXECUTABLE} 项进程需要关闭。$\n您想让安装程序关闭这些进程吗?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "停止${APPLICATION_EXECUTABLE}进程。" +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "未找到要停止的进程!" +StrCpy $PageReinstall_NEW_Field_1 "您的系统已经安装${APPLICATION_NAME}较老版本。建议安装前卸载当前版本。选择将要执行的操作,点击下一步继续。" +StrCpy $PageReinstall_NEW_Field_2 "在安装前先卸载" +StrCpy $PageReinstall_NEW_Field_3 "不要卸载" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "已经安装" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "选择如何安装${APPLICATION_NAME}。" +StrCpy $PageReinstall_OLD_Field_1 "较新版本的 ${APPLICATION_NAME} 已经安装!安装较旧版本的程序是不推荐的。如果您希望继续安装较旧版本,建议先卸载较新版本。选择您想要执行的操作并点击下一步以继续。" +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} 已经安装。$\n$\n请选择想要执行的操作并点击下一步。" +StrCpy $PageReinstall_SAME_Field_2 "增加/重装组件" +StrCpy $PageReinstall_SAME_Field_3 "卸载${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "卸载${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "选择需要执行的维护选项。" +StrCpy $SEC_APPLICATION_DETAILS "安装${APPLICATION_NAME}基本组件。" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "整合到 Windows 资源管理器" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "正在整合到 Windows 资源管理器" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "开始菜单程序快捷方式" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "添加 ${APPLICATION_NAME} 快捷方式到开始菜单。" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "桌面快捷方式" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "创建桌面快捷方式" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "快速启动栏快捷方式" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "创建快速启动栏快捷方式" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME}基本组件。" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME}快捷方式。" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "${APPLICATION_NAME}桌面快捷方式。" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "${APPLICATION_NAME}快速启动栏快捷方式。" +StrCpy $UNINSTALLER_FILE_Detail "覆盖卸载器" +StrCpy $UNINSTALLER_REGISTRY_Detail "正在写入注册表" +StrCpy $UNINSTALLER_FINISHED_Detail "完成" +StrCpy $UNINSTALL_MESSAGEBOX "${APPLICATION_NAME} 可能并没有安装在 $INSTDIR。$\n$\n仍然继续吗?(不推荐)" +StrCpy $UNINSTALL_ABORT "用户取消了卸载" +StrCpy $INIT_NO_QUICK_LAUNCH "快速启动栏快捷方式(N/A)" +StrCpy $INIT_NO_DESKTOP "桌面快捷方式(覆盖)" +StrCpy $UAC_ERROR_ELEVATE "无法获得权限,错误:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "安装程序需要管理员权限,请重试" +StrCpy $INIT_INSTALLER_RUNNING "安装程序已经运行。" +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试" +StrCpy $UAC_ERROR_LOGON_SERVICE "登录服务器未运行!" +StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。" +StrCpy $SectionGroup_Shortcuts "快捷方式" diff --git a/admin/win/nsi/l10n/Slovak.nsh b/admin/win/nsi/l10n/Slovak.nsh new file mode 100644 index 000000000..1c47c7791 --- /dev/null +++ b/admin/win/nsi/l10n/Slovak.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Zobraziť zoznam zmien" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Našli sa ${APPLICATION_EXECUTABLE} proces (y), ktoré je potrebné zastaviť.$\nChcete, aby ich inštalátor zastavil?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Ukončujem ${APPLICATION_EXECUTABLE} procesy." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Proces ukončenia nebol nájdený!" +StrCpy $PageReinstall_NEW_Field_1 "Staršia verzia ${APPLICATION_NAME} je nainštalovaná vo vašom počítači. Odporúčam vám odinštalovať aktuálnu verziu pred inštaláciou. Vyberte operáciu, ktorú chcete vykonať, a kliknite na tlačidlo Ďalej pre pokračovanie." +StrCpy $PageReinstall_NEW_Field_2 "Odinštalovať pred inštaláciou" +StrCpy $PageReinstall_NEW_Field_3 "Neodinštalovať" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Už je nainštalovaný" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Vyberte si, ako chcete nainštalovať ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Novšia verzia ${APPLICATION_NAME} je už nainštalovaná! Neodporúčam vám nainštalovať staršiu verziu. Ak naozaj chcete nainštalovať túto staršiu verziu, je lepšie najprv odinštalovať aktuálnu verziu. Vyberte operáciu, ktorú chcete vykonať, a kliknite na tlačidlo Ďalej pre pokračovanie." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} je už nainštalovaná.$\n$\nVyberte operáciu, ktorú chcete vykonať, a kliknite na tlačidlo Ďalej pre pokračovanie." +StrCpy $PageReinstall_SAME_Field_2 "Pridať/Preinštalovať komponenty" +StrCpy $PageReinstall_SAME_Field_3 "Odinštalovať ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Odinštalovať ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnosť vykonať údržbu." +StrCpy $SEC_APPLICATION_DETAILS "Inštalujú sa náležitosti ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integrácia do Windows Explorera" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Inštalaácia integrácie do Windows Explorera" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupca programu v menu Štart" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Pridať zástupcu pre ${APPLICATION_NAME} do menu Štart." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupca na ploche" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Vytvorenie zástupcu na ploche" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Zástupca na paneli úloh" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Vytvorenie zástupcu na paneli úloh" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Náležitosti ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} zástupca." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Zástupca na ploche pre ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Zástupca na paneli úloh pre ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Zapisujem odinštalátor" +StrCpy $UNINSTALLER_REGISTRY_Detail "Zapisujem inštalačné kľúče do registra" +StrCpy $UNINSTALLER_FINISHED_Detail "Dokončené" +StrCpy $UNINSTALL_MESSAGEBOX "Nezdá sa, že ${APPLICATION_NAME} je nainštalovaný v priečinku '$INSTDIR'.$\n$\nNapriek tomu pokračovať (neodporúča sa)?" +StrCpy $UNINSTALL_ABORT "Odinštalácia prerušená používateľom" +StrCpy $INIT_NO_QUICK_LAUNCH "Zástupca na paneli úloh (N/A)" +StrCpy $INIT_NO_DESKTOP "Zástupca na ploche (prepíše existujúci)" +StrCpy $UAC_ERROR_ELEVATE "Nemožno povýšiť, chyba:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Tento inštalátor vyžaduje admin prístup, skúste to znova" +StrCpy $INIT_INSTALLER_RUNNING "Inštalátor je už spustený." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Tento odinštalátor vyžaduje admin prístup, skúste to znova" +StrCpy $UAC_ERROR_LOGON_SERVICE "Prihlasovacia služba nebeží! Prerušuje sa." +StrCpy $INIT_UNINSTALLER_RUNNING "Odinštalátor je už spustený." +StrCpy $SectionGroup_Shortcuts "Zástupcovia" diff --git a/admin/win/nsi/l10n/Slovenian.nsh b/admin/win/nsi/l10n/Slovenian.nsh new file mode 100644 index 000000000..8f5b4737e --- /dev/null +++ b/admin/win/nsi/l10n/Slovenian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Pokaži opombe k objavi" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Zaznana so dejavna opravila programa ${APPLICATION_EXECUTABLE}, ki pa morajo biti pred nadaljevanjem zaustavljena.$\nAli želite izvajanje teh dejanj končati?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Poteka zaustavljanje opravil programa ${APPLICATION_EXECUTABLE}" +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Opravila, določenega za uničenje, ni mogoče najti!" +StrCpy $PageReinstall_NEW_Field_1 "Nameščena je starejša različica ${APPLICATION_NAME}. Priporočljivo je najprej odstraniti obstoječo namestitev in šele nato namestiti novo. Izberite ustrezno možnost in kliknite za nadaljevanje." +StrCpy $PageReinstall_NEW_Field_2 "Pred namestitvijo je treba obstoječo različico odstraniti" +StrCpy $PageReinstall_NEW_Field_3 "Ne odstrani namestitve" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Program je že nameščen" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Izberite način namestitve programa ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Novejša različica programa ${APPLICATION_NAME} je že nameščena! Ni priporočljivo namestiti starejše. V kolikor želite vseeno nadaljevati z namestitvijo, prej odstranite obstoječo različico. Izberite opravilo in pritisnite gumb za nadaljevanje." +StrCpy $PageReinstall_SAME_Field_1 "Program ${APPLICATION_NAME} ${VERSION} je že nameščen.$\n$\nIzberite opravilo, ki ga želite izvesti in kliknite za nadaljevanje." +StrCpy $PageReinstall_SAME_Field_2 "Dodaj/Ponovno namesti programe" +StrCpy $PageReinstall_SAME_Field_3 "Odstrani ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Odstrani ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Izberite možnost vzdrževanja za izvedbo." +StrCpy $SEC_APPLICATION_DETAILS "Poteka nameščanje ključnih paketov programa ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Podpora programa Windows raziskovalca" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Nameščanje podpore za program Windows Raziskovalec" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Bližnjica programa v programskem meniju" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Poteka dodajanje bližnjice programa ${APPLICATION_NAME} v programski meni." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Bližnica namizja" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Poteka ustvarjanje bližnjice na namizju" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Bližnjica na hitri dostop" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Poteka ustvarjanje bližnjice za hitri dostop" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Knjižnice programa ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Bližnjica programa ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Bližnjica namizja za program ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Bližnjica za hiter dostop za program ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Zapisovanje programa za odstranjevanje namestitve" +StrCpy $UNINSTALLER_REGISTRY_Detail "Poteka zapisovanje namestilnika v register" +StrCpy $UNINSTALLER_FINISHED_Detail "Končano" +StrCpy $UNINSTALL_MESSAGEBOX "Ni videti, da bi bil program ${APPLICATION_NAME} nameščen v mapi '$INSTDIR'.$\n$\nAli želite vseeno nadaljevati (ni priporočeno)?" +StrCpy $UNINSTALL_ABORT "Odstranjevanje namestitve je bilo prekinjeno s strani uporabnika" +StrCpy $INIT_NO_QUICK_LAUNCH "Bližnjica za hiter dostop (N/A)" +StrCpy $INIT_NO_DESKTOP "Bližnjica namizja (obstajajo predmeti za prepis)" +StrCpy $UAC_ERROR_ELEVATE "Ni mogoče dvigniti; napaka:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Namestilnik zahteva skrbniška dovoljenja." +StrCpy $INIT_INSTALLER_RUNNING "Namestilnik je že zagnan." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Program za odstranjevanje namestitve zahteva skrbniška dovoljenja." +StrCpy $UAC_ERROR_LOGON_SERVICE "Storitev za prijavo ni zagnana. Opravilo je ustavljeno!" +StrCpy $INIT_UNINSTALLER_RUNNING "Program za odstranjevanje namestitve je že zagnan." +StrCpy $SectionGroup_Shortcuts "Bližnjice" diff --git a/admin/win/nsi/l10n/Spanish.nsh b/admin/win/nsi/l10n/Spanish.nsh new file mode 100644 index 000000000..7212baded --- /dev/null +++ b/admin/win/nsi/l10n/Spanish.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar las notas de la versión" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso(s) ${APPLICATION_EXECUTABLE} debe(n) ser detenido(s).$\n¿Quiere que el instalador lo haga por usted?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso(s) ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso a finalizar no encontrado!" +StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda desinstalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar." +StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar" +StrCpy $PageReinstall_NEW_Field_3 "No desinstalar" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ya está instalado" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Elija cómo quiere instalar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Una nueva versión de ${APPLICATION_NAME} ya está instalada. No es recomendable instalar una versión anterior. Si realmente quiere instalar esta versión anterior, es mejor que desinstale la versión actual primero. Seleccione la operación que desea realizar y pulse Siguiente para continuar." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ya está instalado.$\n$\nSeleccione la operación que desea realizar y haga click en Siguiente para continuar." +StrCpy $PageReinstall_SAME_Field_2 "Añadir/Reinstalar componentes" +StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Elija la opcion de mantenimiento a realizar." +StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciales." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración para Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando la integración para Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa en Menú de Inicio" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando accesos directos de escritorio" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atajo de acceso rápido" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando un Acceso Directo al Lanzador Rápido" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esenciales." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso Directo de ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Acceso Directo de Escritorio para ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Lanzador Rápido de Accesos Director para ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Escribiendo desinstalador" +StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo claves en el registro del instalador" +StrCpy $UNINSTALLER_FINISHED_Detail "Terminado" +StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No recomendado)" +StrCpy $UNINSTALL_ABORT "Desinstalación cancelada por el usuario" +StrCpy $INIT_NO_QUICK_LAUNCH "Atajo de inicio rápido (N/A)" +StrCpy $INIT_NO_DESKTOP "Atajo de escritorio (sobreescribe el existente)" +StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, error:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "El instalador requiere acceso administrativo, inténtelo de nuevo" +StrCpy $INIT_INSTALLER_RUNNING "El instalador ya se encuentra en ejecución" +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "El desinstalador requiere acceso administrativo, inténtelo de nuevo" +StrCpy $UAC_ERROR_LOGON_SERVICE "Servicio Inicio de sesión no se está ejecutando, abortando!" +StrCpy $INIT_UNINSTALLER_RUNNING "El desinstalador ya se encuentra en ejecución." +StrCpy $SectionGroup_Shortcuts "Accesos directos" diff --git a/admin/win/nsi/l10n/SpanishInternational.nsh b/admin/win/nsi/l10n/SpanishInternational.nsh new file mode 100644 index 000000000..1a14f3148 --- /dev/null +++ b/admin/win/nsi/l10n/SpanishInternational.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de la versión" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Se encontrarion ${APPLICATION_EXECUTABLE} proceso(s) que debe/n ser detenidos.$\"$\n$\"¿Quiere que el instalador lo haga por usted?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Parando el proceso ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Proceso a detener no encontrado!" +StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} esta instalada en el sistema. Es recomendado que quite esta versión antes de instalar. Elija la operación a realizar y seleccione Siguiente para continuar." +StrCpy $PageReinstall_NEW_Field_2 "Des-instale antes de Instalar." +StrCpy $PageReinstall_NEW_Field_3 "No des-instalar." +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Actualmente Instalado." +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Elija como desea instalar ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Una versión mas reciente de ${APPLICATION_NAME} esta actualmente instalada! No es recomendado que instale una versión antigua. Si realmente desea instalar esta versión obsoleta, es mejor que des-instale la versión actual primero. Seleccione la operación que desea realizar y presione en Siguiente para continuar. " +StrCpy $PageReinstall_SAME_Field_1 "La ${APPLICATION_NAME} ${VERSION} ya está instalado.$\n$\nSeleccione la operación que desea realizar y haga click en Siguiente para continuar." +StrCpy $PageReinstall_SAME_Field_2 "Agregar/Re-Instalar componentes" +StrCpy $PageReinstall_SAME_Field_3 "Des-instalar ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Des-instalar ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Elija la opción de mantenimiento a realizar." +StrCpy $SEC_APPLICATION_DETAILS "Instalar esenciales ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración para Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando la integración para Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso Directo en Menú de Programas" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Agregando el Acceso Directo al Menú de Inicio para ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo en Escritorio" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando Accesos Directos en Escritorio" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atajo de Acceso Rápido" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando Atajo de Acceso Rápido" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esencial." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso directo de ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Acceso Directo al Escritorio para ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Atajo de Acceso Rápido para ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Escribiendo Des-Instalador." +StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo claves de Registro del Instalador" +StrCpy $UNINSTALLER_FINISHED_Detail "Terminado" +StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no esta instalado en el directorio '$INSTDIR'.$\n$\n¿Continuar de todos modos? (No recomendado)" +StrCpy $UNINSTALL_ABORT "Des-instalación abortada por el usuario" +StrCpy $INIT_NO_QUICK_LAUNCH "Atajo de Acceso Rápido (N/A)" +StrCpy $INIT_NO_DESKTOP "Acceso Directo en Escritorio (Sobrescribe existentes)" +StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, error:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este instalador requiere acceso Administrador, intente de nuevo. " +StrCpy $INIT_INSTALLER_RUNNING "El instalador ya esta corriendo." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este des-instalador requiere acceso administrador, intente de nuevo" +StrCpy $UAC_ERROR_LOGON_SERVICE "Servicio Inicio de sesión no se está ejecutando, abortando!" +StrCpy $INIT_UNINSTALLER_RUNNING "El des-instalador ya esta corriendo" +StrCpy $SectionGroup_Shortcuts "Accesos Directos" diff --git a/admin/win/nsi/l10n/Swedish.nsh b/admin/win/nsi/l10n/Swedish.nsh new file mode 100644 index 000000000..73dfd2297 --- /dev/null +++ b/admin/win/nsi/l10n/Swedish.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Visa versionsinformationen" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Hittade ${APPLICATION_EXECUTABLE} process(er) som behöver stoppas.$\nVill du att installationsprogrammet ska stoppa dessa åt dig?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Dödar ${APPLICATION_EXECUTABLE} processer." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Processen att döda hittades inte!" +StrCpy $PageReinstall_NEW_Field_1 "En tidigare version av ${APPLICATION_NAME} är installerad på ditt system. Det är rekommenderat att du avinstallerar den nuvarande versionen före installation. Välj den åtgärd du vill utföra och klicka Nästa för att fortsätta." +StrCpy $PageReinstall_NEW_Field_2 "Avinstallera före installation" +StrCpy $PageReinstall_NEW_Field_3 "Avinstallera inte" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Redan installerad" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Välj hur du vill installera ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "En nyare version av ${APPLICATION_NAME} är redan installerad! Det rekommenderas inte att du installerar en äldre version. Om du verkligen vill installera denna äldre versionen, är det bättre att du avinstallerar den nuvarande versionen först. Välj den åtgärd du vill utföra och klicka Nästa för att fortsätta." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} är redan installerad.$\n$\nVälj den åtgärd du vill utföra och klicka på Nästa för att fortsätta." +StrCpy $PageReinstall_SAME_Field_2 "Lägg till/Ominstallera komponenter" +StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Välj underhålls alternativ att utföra." +StrCpy $SEC_APPLICATION_DETAILS "Installerar ${APPLICATION_NAME} väsentligheter." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration för Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installerar integration för Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start-meny program genväg" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lägger till genväg för ${APPLICATION_NAME} till Start-menyn." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Skrivbordsgenväg" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Skapar skrivbordsgenvägar" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Snabbstartsgenväg" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Skapar snabbstartsgenväg" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} väsentligheter." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} genväg." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Skrivbordsgenväg för ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Snabbstartsgenväg för ${APPLICATION_NAME}." +StrCpy $UNINSTALLER_FILE_Detail "Skriver avinstallationsprogram" +StrCpy $UNINSTALLER_REGISTRY_Detail "Skriver installationsprogrammets registernycklar" +StrCpy $UNINSTALLER_FINISHED_Detail "Klar" +StrCpy $UNINSTALL_MESSAGEBOX "Det verkar inte som ${APPLICATION_NAME} är installerad i katalogen '$INSTDIR'.$\n$\nFortsätt ändå (rekommenderas ej)?" +StrCpy $UNINSTALL_ABORT "Avinstallering avbröts av användare" +StrCpy $INIT_NO_QUICK_LAUNCH "Snabbstartsgenväg (N/A)" +StrCpy $INIT_NO_DESKTOP "Skrivbordsgenväg (skriver över nuvarande)" +StrCpy $UAC_ERROR_ELEVATE "Kunde inte få förhöjda rättigheter, fel:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Detta installationsprogram kräver adminstratörs rättigheter, försök igen" +StrCpy $INIT_INSTALLER_RUNNING "Installationsprogrammet körs redan." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörsrättigheter, försök igen" +StrCpy $UAC_ERROR_LOGON_SERVICE "Login-service körs inte, avbryter!" +StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan." +StrCpy $SectionGroup_Shortcuts "Genvägar" diff --git a/admin/win/nsi/l10n/Thai.nsh b/admin/win/nsi/l10n/Thai.nsh new file mode 100644 index 000000000..8b9b14a23 --- /dev/null +++ b/admin/win/nsi/l10n/Thai.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "แสดงบันทึกที่มี" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "พบว่ากระบวนการ ${APPLICATION_EXECUTABLE} จะต้องหยุดทำงาน$\nคุณต้องการติดตั้งเพื่อหยุดการทำงานเหล่านี้ของคุณ?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "ฆ่ากระบวนการทำงาน ${APPLICATION_EXECUTABLE}" +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "ไม่พบการฆ่ากระบวนการ!" +StrCpy $PageReinstall_NEW_Field_1 "รุ่นเก่าของ ${APPLICATION_NAME} ได้ถูกติดตั้งในระบบของคุณ ขอแนะนำให้คุณถอนการติดตั้งรุ่นปัจจุบันออกก่อน แล้วเลือกการดำเนินการที่คุณต้องการหลังจากนั้นคลิกถัดไปเพื่อดำเนินการต่อ" +StrCpy $PageReinstall_NEW_Field_2 "ถอนการติดตั้งก่อนการติดตั้ง" +StrCpy $PageReinstall_NEW_Field_3 "อย่าถอนการติดตั้ง" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "ติดตั้งแล้ว" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "เลือกวิธีที่คุณต้องการติดตั้ง ${APPLICATION_NAME}" +StrCpy $PageReinstall_OLD_Field_1 "รุ่นใหม่ของ ${APPLICATION_NAME} ถูกติดตั้งแล้ว! เราไม่แนะนำให้คุณติดตั้งรุ่นที่เก่ากว่า ถ้าคุณอยากจะติดตั้งรุ่นเก่าก็สามารถถอนการติดตั้งได้" +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} รุ่น ${VERSION} ถูกติดตั้งไปแล้ว$ $\nเลือกดำเนินงานที่คุณต้องการและคลิกถัดไปเพื่อดำเนินการต่อ" +StrCpy $PageReinstall_SAME_Field_2 "ส่วนประกอบ เพิ่ม/ติดตั้งใหม่ " +StrCpy $PageReinstall_SAME_Field_3 "ถอนการติดตั้ง ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "ถอนการติดตั้ง ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "เลือกตัวเลือกการบำรุงรักษาเพื่อดำเนินการ" +StrCpy $SEC_APPLICATION_DETAILS "กำลังติดตั้งข้อมูลที่เป็นเป็นของ ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "บูรณาการสำหรับ Windows Explorer" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "บูรณาการกำลังติดตั้งสำหรับ Windows Explorer" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "โปรแกรมทางลัดเมนูเริ่มต้น" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "เพิ่มทางลัดสำหรับ ${APPLICATION_NAME} ที่เมนูเริ่มต้น" +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "ทางลัดพื้นโต๊ะ" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "สร้างทางลัดบนเดสก์ทอป" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "ทางลัดเร่งด่วน" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "สร้างทางลัดเร่งด่วน" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} ที่จำเป็น" +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "ทางลัด ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "ทางลัดบนเดสก์ทอปสำหรับ ${APPLICATION_NAME}" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "ทางลัดเร่งด่วนสำหรับ ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_FILE_Detail "กำลังถอนการติดตั้ง" +StrCpy $UNINSTALLER_REGISTRY_Detail "กำลังติดตั้งรหัสรีจิสทรี" +StrCpy $UNINSTALLER_FINISHED_Detail "เสร็จสิ้น" +StrCpy $UNINSTALL_MESSAGEBOX "มันจะไม่ปรากฏ ${APPLICATION_NAME} ที่มีการติดตั้งในไดเรกทอรี '$INSTDIR' ดำเนินการต่อไป (ไม่แนะนำ)?" +StrCpy $UNINSTALL_ABORT "ถอนการติดตั้งถูกยกเลิกโดยผู้ใช้" +StrCpy $INIT_NO_QUICK_LAUNCH "ทางลัดเร่งด่วน (N/A)" +StrCpy $INIT_NO_DESKTOP "ทางลัดเดสก์ทอป (จะเขียนทับหากมีอยู่แล้ว)" +StrCpy $UAC_ERROR_ELEVATE "ไม่สามารถที่จะยกระดับข้อผิดพลาด:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "การติดตั้งนี้จะต้องมีการเข้าถึงผู้ดูแลระบบ กรุณาลองอีกครั้ง" +StrCpy $INIT_INSTALLER_RUNNING "กำลังทำการติดตั้ง" +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "การถอนการติดตั้งนี้จะต้องมีการเข้าถึงส่วนผู้ดูแลระบบ กรุณาลองอีกครั้ง" +StrCpy $UAC_ERROR_LOGON_SERVICE "บริการเข้าสู่ระบบไม่ทำงาน กำลังยกเลิก!" +StrCpy $INIT_UNINSTALLER_RUNNING "กำลังทำการถอนการติดตั้ง" +StrCpy $SectionGroup_Shortcuts "ทางลัด" diff --git a/admin/win/nsi/l10n/Turkish.nsh b/admin/win/nsi/l10n/Turkish.nsh new file mode 100644 index 000000000..9aca6b72f --- /dev/null +++ b/admin/win/nsi/l10n/Turkish.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Sürüm notlarını göster" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Durdurulması gereken ${APPLICATION_EXECUTABLE} süreçleri bulundu.$\nYükleyicinin bunları sizin için durdurmasını ister misiniz?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "${APPLICATION_EXECUTABLE} süreçleri sonlandırılıyor." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Sonlandırılacak süreç bulunamadı!" +StrCpy $PageReinstall_NEW_Field_1 "${APPLICATION_NAME} önceki sürümü sisteminizde yüklü. Kurulumdan önce bunu kaldırmanız önerilir. Yapmak istediğiniz işlemi seçip devam etmek için İleri tıklayın." +StrCpy $PageReinstall_NEW_Field_2 "Yüklemeden önce kaldır" +StrCpy $PageReinstall_NEW_Field_3 "Kaldırma" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Zaten Yüklü" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "${APPLICATION_NAME} uygulamasını nasıl yüklemek istediğinizi seçin." +StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME} uygulamasının daha yeni sürümü zaten yüklü! Daha eski bir sürümünü yüklemeniz önerilmez. Gerçekten bu eski sürümü yüklemek isterseniz, ilk olarak geçerli sürümü kaldırmanız tavsiye edilir. Yapmak istediğiniz işlemi seçin ve devam etmek üzere İleri tıklayın." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} zaten yüklü.$\n$\nYapmak istediğiniz işlemi seçin ve devam etmek için İleri tıklayın." +StrCpy $PageReinstall_SAME_Field_2 "Bileşenleri ekle/yeniden yükle" +StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} uygulamasını kaldır" +StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} uygulamasını kaldır" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Yapmak istediğiniz bakım işlemini seçin." +StrCpy $SEC_APPLICATION_DETAILS "${APPLICATION_NAME} gereklilikleri yükleniyor." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows Gezgini için tümleştirme" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows Gezgini için Tümleştirme Yükleme" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Başlat Menüsü Program Kısayolu" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "${APPLICATION_NAME} için Başlat Menüsü'ne kısayol ekleniyor." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Masaüstü Kısayolu" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Masaüstü Kısayolları Oluşturuluyor" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Hızlı Başlat Kısayolu" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Hızlı Başlat Kısayolu Oluşturuluyor" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} gereklilikleri." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} kısayolu." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "${APPLICATION_NAME} için masaüstü kısayolu." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "${APPLICATION_NAME} için Hızlı Başlat kısayolu." +StrCpy $UNINSTALLER_FILE_Detail "Kaldırıcı Yazılıyor" +StrCpy $UNINSTALLER_REGISTRY_Detail "Yükleyici Kayıt Anahtarları Yazılıyor" +StrCpy $UNINSTALLER_FINISHED_Detail "Tamamlandı" +StrCpy $UNINSTALL_MESSAGEBOX "${APPLICATION_NAME} uygulaması '$INSTDIR' dizinine yüklenmiş gibi görünmüyor.$\n$\nYine de devam edilsin mi (önerilmez)?" +StrCpy $UNINSTALL_ABORT "Kaldırma kullanıcı tarafından iptal edildi" +StrCpy $INIT_NO_QUICK_LAUNCH "Hızlı Başlat Kısayolu (Kullanılamıyor)" +StrCpy $INIT_NO_DESKTOP "Masaüstü Kısayolu (mevcut olanın üzerine yazılır)" +StrCpy $UAC_ERROR_ELEVATE "Yükseltme başarısız, hata:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Bu yükleyici yönetici erişimi gerektiriyor, yeniden deneyin" +StrCpy $INIT_INSTALLER_RUNNING "Yükleyici zaten çalışıyor." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Bu kaldırıcı yönetici erişimi gerektiriyor, yeniden deneyin" +StrCpy $UAC_ERROR_LOGON_SERVICE "Oturum açılacak sunucu çalışmadığından iptal ediliyor!" +StrCpy $INIT_UNINSTALLER_RUNNING "Kaldırıcı zaten çalışıyor." +StrCpy $SectionGroup_Shortcuts "Kısayollar" diff --git a/admin/win/nsi/l10n/Ukrainian.nsh b/admin/win/nsi/l10n/Ukrainian.nsh new file mode 100644 index 000000000..8ca57b89f --- /dev/null +++ b/admin/win/nsi/l10n/Ukrainian.nsh @@ -0,0 +1,42 @@ +StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Показати примітки до випуску" +StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Знайдено процес(и) ${APPLICATION_EXECUTABLE}, які необхідно зупинити.$\nХочете щоб програма установки зробила це самостійно?" +StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Завершення процесів ${APPLICATION_EXECUTABLE}." +StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Не знайдено процеси, які необхідно зупинити!" +StrCpy $PageReinstall_NEW_Field_1 "У вашої системі встановлена застаріла версія додатку ${APPLICATION_NAME}. Рекомендуємо видалити її перед початком встановлення поточної версії. Оберіть подальшу дію та натисніть $\"Далі$\"." +StrCpy $PageReinstall_NEW_Field_2 "Видалити перед установкою" +StrCpy $PageReinstall_NEW_Field_3 "Не видаляти" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Установлено" +StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Оберіть, як ви хочете установити ${APPLICATION_NAME}." +StrCpy $PageReinstall_OLD_Field_1 "Знайдено новішу версію ${APPLICATION_NAME}! Ми не рекомендуємо встановлювати стару версію. Якщо ви все ж бажаєте встановити цю версію, спочатку видаліть поточну версію. Оберіть подальшу дію та натисніть $\"Далі$\"." +StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} вже встановлено.$\n$\nОберіть подальшу дію та натисніть $\"Далі$\" для продовження." +StrCpy $PageReinstall_SAME_Field_2 "Додати/Перевстановити компоненти" +StrCpy $PageReinstall_SAME_Field_3 "Видалити ${APPLICATION_NAME}" +StrCpy $UNINSTALLER_APPDATA_TITLE "Видалити ${APPLICATION_NAME}" +StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Оберіть опцію обслуговування для виконання." +StrCpy $SEC_APPLICATION_DETAILS "Установка залежностей ${APPLICATION_NAME}." +StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Інтеграція з провідником Windows" +StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Встановлення інтеграції з провідником Windows" +StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлик в меню Пуск" +StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Створення ярлика ${APPLICATION_NAME} в меню Пуск." +StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлик на Робочому столі" +StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Створення ярлика на Робочому столі" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Ярлик на панелі швидкого запуску" +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Створення ярлика на панелі швидкого запуску" +StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} залежності." +StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} ярлик." +StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Ярлик ${APPLICATION_NAME} на Робочому столі." +StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Ярлик ${APPLICATION_NAME} на панелі швидкого запуску." +StrCpy $UNINSTALLER_FILE_Detail "Збереження Програми видалення" +StrCpy $UNINSTALLER_REGISTRY_Detail "Запис ключів реєстру" +StrCpy $UNINSTALLER_FINISHED_Detail "Завершено" +StrCpy $UNINSTALL_MESSAGEBOX "Скоріш за все ${APPLICATION_NAME} вже встановлено в теку '$INSTDIR'.$↩$\nВсе одно продовжити (не рекомендується)?" +StrCpy $UNINSTALL_ABORT "Видалення перервано користувачем." +StrCpy $INIT_NO_QUICK_LAUNCH "Ярлик в області швидкого запуску (недоступний)" +StrCpy $INIT_NO_DESKTOP "Ярлик на Робочому столі (перезаписати існуючий)" +StrCpy $UAC_ERROR_ELEVATE "Неможливо підняти, помилка:" +StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Для установки потрібні права адміністратора, спробуйте ще раз" +StrCpy $INIT_INSTALLER_RUNNING "Установка вже запущена." +StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Для видалення потрібні права адміністратора, спробуйте ще раз" +StrCpy $UAC_ERROR_LOGON_SERVICE "Сервіс авторизації не запущений, припиняю!" +StrCpy $INIT_UNINSTALLER_RUNNING "Програма видалення вже запущено." +StrCpy $SectionGroup_Shortcuts "Ярлики" diff --git a/admin/win/nsi/l10n/declarations.nsh b/admin/win/nsi/l10n/declarations.nsh new file mode 100644 index 000000000..6a25de1df --- /dev/null +++ b/admin/win/nsi/l10n/declarations.nsh @@ -0,0 +1,42 @@ +Var MUI_FINISHPAGE_SHOWREADME_TEXT_STRING +Var ConfirmEndProcess_MESSAGEBOX_TEXT +Var ConfirmEndProcess_KILLING_PROCESSES_TEXT +Var ConfirmEndProcess_KILL_NOT_FOUND_TEXT +Var PageReinstall_NEW_Field_1 +Var PageReinstall_NEW_Field_2 +Var PageReinstall_NEW_Field_3 +Var PageReinstall_NEW_MUI_HEADER_TEXT_TITLE +Var PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE +Var PageReinstall_OLD_Field_1 +Var PageReinstall_SAME_Field_1 +Var PageReinstall_SAME_Field_2 +Var PageReinstall_SAME_Field_3 +Var UNINSTALLER_APPDATA_TITLE +Var PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE +Var SEC_APPLICATION_DETAILS +Var OPTION_SECTION_SC_SHELL_EXT_SECTION +Var OPTION_SECTION_SC_SHELL_EXT_DetailPrint +Var OPTION_SECTION_SC_START_MENU_SECTION +Var OPTION_SECTION_SC_START_MENU_DetailPrint +Var OPTION_SECTION_SC_DESKTOP_SECTION +Var OPTION_SECTION_SC_DESKTOP_DetailPrint +Var OPTION_SECTION_SC_QUICK_LAUNCH_SECTION +Var OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint +Var OPTION_SECTION_SC_APPLICATION_Desc +Var OPTION_SECTION_SC_START_MENU_Desc +Var OPTION_SECTION_SC_DESKTOP_Desc +Var OPTION_SECTION_SC_QUICK_LAUNCH_Desc +Var UNINSTALLER_FILE_Detail +Var UNINSTALLER_REGISTRY_Detail +Var UNINSTALLER_FINISHED_Detail +Var UNINSTALL_MESSAGEBOX +Var UNINSTALL_ABORT +Var INIT_NO_QUICK_LAUNCH +Var INIT_NO_DESKTOP +Var UAC_ERROR_ELEVATE +Var UAC_INSTALLER_REQUIRE_ADMIN +Var INIT_INSTALLER_RUNNING +Var UAC_UNINSTALLER_REQUIRE_ADMIN +Var UAC_ERROR_LOGON_SERVICE +Var INIT_UNINSTALLER_RUNNING +Var SectionGroup_Shortcuts diff --git a/admin/win/nsi/l10n/languages.nsh b/admin/win/nsi/l10n/languages.nsh new file mode 100644 index 000000000..bc67938c5 --- /dev/null +++ b/admin/win/nsi/l10n/languages.nsh @@ -0,0 +1,28 @@ +!insertmacro MUI_LANGUAGE "Swedish" +!insertmacro MUI_LANGUAGE "Estonian" +!insertmacro MUI_LANGUAGE "Turkish" +!insertmacro MUI_LANGUAGE "PortugueseBR" +!insertmacro MUI_LANGUAGE "Slovenian" +!insertmacro MUI_LANGUAGE "SpanishInternational" +!insertmacro MUI_LANGUAGE "Dutch" +!insertmacro MUI_LANGUAGE "Norwegian" +!insertmacro MUI_LANGUAGE "Hungarian" +!insertmacro MUI_LANGUAGE "Ukrainian" +!insertmacro MUI_LANGUAGE "French" +!insertmacro MUI_LANGUAGE "Catalan" +!insertmacro MUI_LANGUAGE "Russian" +!insertmacro MUI_LANGUAGE "Thai" +!insertmacro MUI_LANGUAGE "Finnish" +!insertmacro MUI_LANGUAGE "Basque" +!insertmacro MUI_LANGUAGE "Greek" +!insertmacro MUI_LANGUAGE "SimpChinese" +!insertmacro MUI_LANGUAGE "Italian" +!insertmacro MUI_LANGUAGE "Portuguese" +!insertmacro MUI_LANGUAGE "Czech" +!insertmacro MUI_LANGUAGE "Japanese" +!insertmacro MUI_LANGUAGE "Galician" +!insertmacro MUI_LANGUAGE "German" +!insertmacro MUI_LANGUAGE "Slovak" +!insertmacro MUI_LANGUAGE "Spanish" +!insertmacro MUI_LANGUAGE "Polish" +!insertmacro MUI_LANGUAGE "Farsi" diff --git a/admin/win/nsi/lib/fileassoc.nsh b/admin/win/nsi/lib/fileassoc.nsh new file mode 100644 index 000000000..20fc75087 --- /dev/null +++ b/admin/win/nsi/lib/fileassoc.nsh @@ -0,0 +1,120 @@ +; fileassoc.nsh +; File association helper macros +; Written by Saivert +; See http://nsis.sourceforge.net/FileAssoc +; +; Features automatic backup system and UPDATEFILEASSOC macro for +; shell change notification. +; +; |> How to use <| +; To associate a file with an application so you can double-click it in explorer, use +; the APP_ASSOCIATE macro like this: +; +; Example: +; !insertmacro APP_ASSOCIATE "txt" "myapp.textfile" "Description of txt files" \ +; "$INSTDIR\myapp.exe,0" "Open with myapp" "$INSTDIR\myapp.exe $\"%1$\"" +; +; Never insert the APP_ASSOCIATE macro multiple times, it is only meant +; 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 +; = <"description"> +; shell +; = <"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 diff --git a/admin/win/nsi/page_header.bmp b/admin/win/nsi/page_header.bmp new file mode 100644 index 0000000000000000000000000000000000000000..427f4460662a6da259c9811363ad9f6fb8323137 GIT binary patch literal 25818 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

%MCyp8xvHz&8AU zb^IeU6VnIQRX6{hLRokS3uei*B$GgEtS#3!33QSqi=sEct@7THm+bhGYX*M&7vnn@ zO&))GrgA)-p)r1}Hn6k0_W@|sI`zPRi6Dm1ZAEXB)M1f&a5E_6yfZZFH8A9hm1y{h zV`2XuPSb9nErTdzM4@UqzUkwWFMP9hU|oG^R|6V3gBco)>WP_?TWfpnnRx0;(771`2y#Z*6wFPuONft~y34wOhIApt}ahWOHY8u{W8VB0KI_$WNxe-R5 z%4t}#LCf>I$vsOX&}0CQ3LLJ1C#;T3g49@&VK;)TXDO5c>o9uLSQj8QE?knc5!A)C z0oLTKZzRbC(8zf*DzYoBo_RI3cg4_(d2Ujx=bP{ezO#7A0A&QUz*?d#f3-*}%QfH6eiIPmiZDCE4 zIpZ@G>_D=Vpjj!57tg>&9n9Lz6PwkW1IgZ4d}Qeld4SH$;1O1YvYXGna){^ z=pB#YB-WWp&5PavsdGp&XOVizWn<5Mvr!x6p~rqzy*BaMox`i%X#$;-)a{dGabA-^ z^GMxdNfslunfmTu{VUZh`H&>Y!B%l_deu*rIIYY zaJlsI;Ya_p`r5*o;k}%r8I&WZ_O2Rx;(raTx&}~|OE9`Qq;91o1FV760&5azDtfz8 z-+?Ors1B zc&FwasJls$DPG%HXC}3mWLfUGL{p5g8zCxOqRBR)%ZSK`vPd1{H72!}WYjs!C|q`f zBnx0tv9k-oC@|z-ch;?RCdr9Vy zWK=zilln%I47JP`kYs?eSPu#vj!BIr8EFv30o-z)kjazs4%8giH+j!a-g8#EBx}1H z!OW6LNhWt{09s&ek-C#48LPWC@jz{~QR_1`2k2%>GL}Kqir#bp&mhSpsR3&asj(X& zVl+$%j@!w6mMqMH5x;VmneSB23# z*r_Gl2CstyHFQ!dW50YbNS#5FaZ}%JgJ`-N0b1}}U3gUV78y~Zo>fNSGOr{n%OIL? z&eEhdcufQCC0X-sqs|31ea=djWE$>(*KLU2&McXiWDvLI;-9k|2WpKnJj{gJj3%`a zy;0$^7bICmH-bHYP8+{lnkBP)cI0MllbYD3CC~xZZ6Gz4WXg>YjWB9^;nM1^b@gYl zT;DlU-$n}_gl-YN>5M3k)EaA?JTXY!b&^a>wlNni$$H2jsuXwR9F^jNV;m5G~J3 z)_amH0GhzsAhnldB^NGpB~KjMTeWgn+q97mwHYmd#=I6-yRYPsWsWR`OJcH(G#7=3 zELY~lOENUsMyI~*12ts7RR9kPmspZXpkr9)BX!*J&6sQxdC6Q@`<|UL4%9k&1JHG2 zzczs8NV1}nZLr12(S@h9x2w!S?$n(i$(l18!6vn0v>m-W?;!I&iX$C{mNDZv$vo^ah|M)&{A0(c6(F!()Nlo+X1!cx*62 z+p}bG=Lx@XX<<$8)Cr^ptPP;OB+GE1c4o;sPm)Pe+gS5R?Il@I@<6`9PAOc*&RH7h z`uc#^#!l@eSyaXfMg+reTj)k8GfO7VSr*m?&^brN=9Oe^cOzggSx-o^Fe4hF48m-^ zSmYg-$nqVXvwW5eMQ@h9zm1YifWH3fMkcJuow~f99p;rBO(|S~W z_ee6z_08$oiTdSdQ9v zykefnoY1xtXO@hY`o^S|SYuLKK>I8ieV|U1WKEcCquZ!Csc((7jNbBBGJsoHdr2m- zF5Za8CbeC-6mA3zG+&Y_xUWeeH3>8oy`8CVKiQ^fJv(9cd!6$@txy)itg&8UtqPZ3 zlC@BhWt(iHL$}T75NMnw(~?XAjj>LT-V~{E&kinJ`Yajl+0hm<^MNj07La6svRopD zD^goP&q7JYOMNG4?@*F8WwMRtb#mcSCQo9~TVVaeAcm7zlRI^JSu#J_#^kbm#*!>l zWo$Qs1R6(g0QwAI%?Fx_-cCuzGKeO6$?|5&+U`bZ(qtRS>l9KOSu#a!5x@ax3hVat z>|ie$J+6u{h_>!Zj`mKru_Rg0vt#-O^?}+&YK^tEQj{6JmmWE%@> O);TMbWRleI>;DI%0`Exx literal 0 HcmV?d00001 diff --git a/admin/win/tools/CMakeLists.txt b/admin/win/tools/CMakeLists.txt new file mode 100644 index 000000000..7117b5b60 --- /dev/null +++ b/admin/win/tools/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 17) + +if(CMAKE_SIZEOF_VOID_P MATCHES 4) + set(BITNESS 32) +else() + set(BITNESS 64) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + NCToolsShared +) + +add_definitions(-DUNICODE) +add_definitions(-D_UNICODE) +add_definitions(-DNDEBUG) +add_definitions(-D_WINDOWS) + +# Get APIs from from Vista onwards. +add_definitions(-D_WIN32_WINNT=0x0601) +add_definitions(-DWINVER=0x0601) + +# Use automatic overload for suitable CRT safe-functions +# See https://docs.microsoft.com/de-de/cpp/c-runtime-library/security-features-in-the-crt?view=vs-2019 +add_definitions(-D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1) +# Also: Disable compiler warnings because we don't use Windows CRT safe-functions explicitly and don't intend to +# as this is a pure cross-platform source the only alternative would be a ton of ifdefs with calls to the _s version +add_definitions(-D_CRT_SECURE_NO_WARNINGS) + +# Optimize for size +set(COMPILER_FLAGS "/GL /O1 /sdl /Zc:inline /Oi /EHsc /nologo") +set(LINKER_FLAGS "/LTCG /OPT:REF /SUBSYSTEM:WINDOWS /NOLOGO") + +# Enable DEP, ASLR and CFG +set(LINKER_FLAGS "${LINKER_FLAGS} /nxcompat /dynamicbase /guard:cf") + +# x86 only: Enable SafeSEH +if(CMAKE_SIZEOF_VOID_P MATCHES 4) + set(LINKER_FLAGS "${LINKER_FLAGS} /safeseh") +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS}") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") + +# Use static runtime for all subdirectories +foreach(buildType "" "_DEBUG" "_MINSIZEREL" "_RELEASE" "_RELWITHDEBINFO") + string(REPLACE "/MD" "/MT" "CMAKE_CXX_FLAGS${buildType}" "${CMAKE_CXX_FLAGS${buildType}}") +endforeach() + +add_subdirectory(NCToolsShared) + +if(BUILD_WIN_MSI) + add_subdirectory(NCMsiHelper) +endif() + +if(BUILD_WIN_TOOLS) + add_subdirectory(NCNavRemove) +endif() diff --git a/admin/win/tools/NCMsiHelper/CMakeLists.txt b/admin/win/tools/NCMsiHelper/CMakeLists.txt new file mode 100644 index 000000000..484b45422 --- /dev/null +++ b/admin/win/tools/NCMsiHelper/CMakeLists.txt @@ -0,0 +1,41 @@ +# Find WiX Toolset +if(NOT DEFINED ENV{WIX}) + # Example: WIX=C:\Program Files (x86)\WiX Toolset v3.11\ + message(FATAL_ERROR "WiX Toolset path not set (environment variable 'WIX'). Please install the WiX Toolset.") +else() + set(WIX_SDK_PATH $ENV{WIX}/SDK/VS2017) + message(STATUS "WiX Toolset SDK path: ${WIX_SDK_PATH}") +endif() + +include_directories(${WIX_SDK_PATH}/inc) + +if(CMAKE_SIZEOF_VOID_P MATCHES 4) + link_directories(${WIX_SDK_PATH}/lib/x86) +else() + link_directories(${WIX_SDK_PATH}/lib/x64) +endif() + +add_definitions(-D_NCMSIHELPER_EXPORTS) +add_definitions(-D_USRDLL) +add_definitions(-D_WINDLL) + +set(TARGET_NAME NCMsiHelper${BITNESS}) + +add_library(${TARGET_NAME} MODULE + CustomAction.cpp + CustomAction.def + LogResult.cpp + NCMsiHelper.cpp +) + +target_link_libraries(${TARGET_NAME} + NCToolsShared +) + +install(TARGETS ${TARGET_NAME} + DESTINATION msi/ +) +install(FILES + NCMsiHelper.wxs + DESTINATION msi/ +) diff --git a/admin/win/tools/NCMsiHelper/CustomAction.cpp b/admin/win/tools/NCMsiHelper/CustomAction.cpp new file mode 100644 index 000000000..db82ba6a7 --- /dev/null +++ b/admin/win/tools/NCMsiHelper/CustomAction.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Parts of this file are based on: + * https://www.codeproject.com/articles/570751/devmsi-an-example-cplusplus-msi-wix-deferred-custo + * + * Licensed under the The Code Project Open License (CPOL): + * https://www.codeproject.com/info/cpol10.aspx + * + */ + +#include "NCMsiHelper.h" + +/** + * Sets up logging for MSIs and then calls the appropriate custom action with argc/argv parameters. + * + * MSI deferred custom action dlls have to handle parameters (properties) a little differently, + * since the deferred action may not have an active session when it begins. Since the easiest + * way to pass parameter(s) is to put them all into a CustomActionData property and then retrieve it, + * the easiest thing to do on this ( C/C++ ) end is to pull the parameter and then split it into + * a list of parameter(s) that we need. + * + * For this implementation, it made sense to treat the single string provided in CustomActionData + * as if it were a command line, and then parse it out just as if it were a command line. Obviously, + * the "program name" isn't going to be the first argument unless the MSI writer is pedantic, but + * otherwise it seems to be a good way to do it. + * + * Since all entry points need to do this same work, it was easiest to have a single function that + * would do the setup, pull the CustomActionData parameter, split it into an argc/argv style of + * argument list, and then pass that argument list into a function that actually does something + * interesting. + * + * @param hInstall The hInstall parameter provided by MSI/WiX. + * @param func The function to be called with argc/argv parameters. + * @param actionName The text description of the function. It will be put in the log. + * @return Returns ERROR_SUCCESS or ERROR_INSTALL_FAILURE. + */ +UINT CustomActionArgcArgv(MSIHANDLE hInstall, CUSTOM_ACTION_ARGC_ARGV func, LPCSTR actionName) +{ + LPWSTR pszCustomActionData = nullptr, *argv = nullptr; + + HRESULT hr = WcaInitialize(hInstall, actionName); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized."); + + // Retrieve our custom action property. This is one of + // only three properties we can request on a Deferred + // Custom Action. So, we assume the caller puts all + // parameters in this one property. + hr = WcaGetProperty(L"CustomActionData", &pszCustomActionData); + ExitOnFailure(hr, "Failed to get Custom Action Data."); + WcaLog(LOGMSG_STANDARD, "Custom Action Data = '%ls'.", pszCustomActionData); + + // Convert the string retrieved into a standard argc/arg layout + // (ignoring the fact that the first parameter is whatever was + // passed, not necessarily the application name/path). + int argc = 0; + argv = CommandLineToArgvW(pszCustomActionData, &argc); + if (argv) { + hr = HRESULT_FROM_WIN32(GetLastError()); + ExitOnFailure(hr, "Failed to convert Custom Action Data to argc/argv."); + } + + hr = (func)(argc, argv); + ExitOnFailure(hr, "Custom action failed"); + +LExit: + // Resource freeing here! + ReleaseStr(pszCustomActionData); + if (argv) + LocalFree(argv); + + return WcaFinalize(SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE); +} + +UINT __stdcall ExecNsisUninstaller(MSIHANDLE hInstall) +{ + return CustomActionArgcArgv(hInstall, DoExecNsisUninstaller, "ExecNsisUninstaller"); +} + +UINT __stdcall RemoveNavigationPaneEntries(MSIHANDLE hInstall) +{ + return CustomActionArgcArgv(hInstall, DoRemoveNavigationPaneEntries, "RemoveNavigationPaneEntries"); +} + +/** + * DllMain - Initialize and cleanup WiX custom action utils. + */ +extern "C" BOOL WINAPI DllMain( + __in HINSTANCE hInst, + __in ULONG ulReason, + __in LPVOID + ) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + break; + } + + return TRUE; +} diff --git a/admin/win/tools/NCMsiHelper/CustomAction.def b/admin/win/tools/NCMsiHelper/CustomAction.def new file mode 100644 index 000000000..dc15a63d1 --- /dev/null +++ b/admin/win/tools/NCMsiHelper/CustomAction.def @@ -0,0 +1,3 @@ +EXPORTS +ExecNsisUninstaller +RemoveNavigationPaneEntries diff --git a/admin/win/tools/NCMsiHelper/LogResult.cpp b/admin/win/tools/NCMsiHelper/LogResult.cpp new file mode 100644 index 000000000..b6f37f28e --- /dev/null +++ b/admin/win/tools/NCMsiHelper/LogResult.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Parts of this file are based on: + * https://www.codeproject.com/articles/570751/devmsi-an-example-cplusplus-msi-wix-deferred-custo + * + * Licensed under the The Code Project Open License (CPOL): + * https://www.codeproject.com/info/cpol10.aspx + * + */ + +#include "NCMsiHelper.h" + +// +// This code modified from MSDN article 256348 +// "How to obtain error message descriptions using the FormatMessage API" +// Currently found at http://support.microsoft.com/kb/256348/en-us + +#define ERRMSGBUFFERSIZE 256 + +/** + * Use FormatMessage() to look an error code and log the error text. + * + * @param dwErrorMsgId The error code to be investigated. + */ +void LogError(DWORD dwErrorMsgId) +{ + HLOCAL pBuffer = nullptr; // Buffer to hold the textual error description. + DWORD ret = 0; // Temp space to hold a return value. + HINSTANCE hInst = nullptr; // Instance handle for DLL. + bool doLookup = true; + DWORD dwMessageId = dwErrorMsgId; + LPCSTR pMessage = "Error %d"; + DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS; + + if (HRESULT_FACILITY(dwErrorMsgId) == FACILITY_MSMQ) { + hInst = LoadLibrary(TEXT("MQUTIL.DLL")); + flags |= FORMAT_MESSAGE_FROM_HMODULE; + doLookup = (nullptr != hInst); + } else if (dwErrorMsgId >= NERR_BASE && dwErrorMsgId <= MAX_NERR) { + hInst = LoadLibrary(TEXT("NETMSG.DLL")); + flags |= FORMAT_MESSAGE_FROM_HMODULE; + doLookup = (nullptr != hInst); + } else if (HRESULT_FACILITY(dwErrorMsgId) == FACILITY_WIN32) { + // A "GetLastError" error, drop the HRESULT_FACILITY + dwMessageId &= 0x0000FFFF; + flags |= FORMAT_MESSAGE_FROM_SYSTEM; + } + + if (doLookup) { + ret = FormatMessageA( + flags, + hInst, // Handle to the DLL. + dwMessageId, // Message identifier. + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language. + reinterpret_cast(&pBuffer), // Buffer that will hold the text string. + ERRMSGBUFFERSIZE, // Allocate at least this many chars for pBuffer. + nullptr // No insert values. + ); + } + + if (0 < ret && nullptr != pBuffer) { + pMessage = static_cast(pBuffer); + } + + // Display the string. + if (WcaIsInitialized()) { + WcaLogError(dwErrorMsgId, pMessage, dwMessageId); + } else { + // Log to stdout/stderr + fprintf_s(stderr, pMessage, dwMessageId); + if ('\n' != pMessage[strlen(pMessage) - 1]) { + fprintf_s(stderr, "\n"); + } + } + + // Free the buffer. + LocalFree(pBuffer); +} + +void LogResult( + __in HRESULT hr, + __in_z __format_string PCSTR fmt, ... + ) +{ + // This code taken from MSDN vsprintf example found currently at + // http://msdn.microsoft.com/en-us/library/28d5ce15(v=vs.71).aspx + // ...and then modified... because it doesn't seem to work! + va_list args; + + va_start(args, fmt); +#pragma warning(push) +#pragma warning(disable : 4996) + const auto len = _vsnprintf(nullptr, 0, fmt, args) + 1; +#pragma warning(pop) + auto buffer = static_cast(malloc(len * sizeof(char))); + +#ifdef _DEBUG + ::ZeroMemory(buffer, len); +#endif // _DEBUG + _vsnprintf_s(buffer, len, len - 1, fmt, args); + + // (MSDN code complete) + + // Now that the buffer holds the formatted string, send it to + // the appropriate output. + if (WcaIsInitialized()) { + if (FAILED(hr)) { + WcaLogError(hr, buffer); + LogError(hr); + } else { + WcaLog(LOGMSG_STANDARD, buffer); + } + } else { // Log to stdout/stderr + if (FAILED(hr)) { + fprintf_s(stderr, "%s\n", buffer); + LogError(hr); + } else { + fprintf_s(stdout, "%s\n", buffer); + } + } + + free(buffer); +} diff --git a/admin/win/tools/NCMsiHelper/LogResult.h b/admin/win/tools/NCMsiHelper/LogResult.h new file mode 100644 index 000000000..f98465835 --- /dev/null +++ b/admin/win/tools/NCMsiHelper/LogResult.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Parts of this file are based on: + * https://www.codeproject.com/articles/570751/devmsi-an-example-cplusplus-msi-wix-deferred-custo + * + * Licensed under the The Code Project Open License (CPOL): + * https://www.codeproject.com/info/cpol10.aspx + * + */ + +/** + * Function prototype for LogResult() + */ +#pragma once + +/** + * Log a message. + * + * If the DLL is being used in a WiX MSI environment, LogResult() will + * route any log messages to the MSI log file via WcaLog() or WcaLogError(). + * + * If the DLL is NOT being used in a WiX MSI environment, LogResult() will + * route any log messages to stdout or stderr. + * + * If the result is an error code, LogResult will attempt to gather a + * text version of the error code and place it in the log. For example, + * if the error code means ERROR_FILE_NOT_FOUND, it will look up the appropriate + * message ( via FormatMessage() ) and add "The system cannot find the file specified." + * to the log. + * + * @param hr The HRESULT to be interrogated for success or failure. + * @param fmt The string format for a user-specified error message. + */ +void LogResult( + __in HRESULT hr, + __in_z __format_string PCSTR fmt, ... +); diff --git a/admin/win/tools/NCMsiHelper/NCMsiHelper.cpp b/admin/win/tools/NCMsiHelper/NCMsiHelper.cpp new file mode 100644 index 000000000..6ad1d6aa2 --- /dev/null +++ b/admin/win/tools/NCMsiHelper/NCMsiHelper.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "NCMsiHelper.h" +#include "utility.h" +#include "LogResult.h" + +using namespace NCTools; + +HRESULT NCMSIHELPER_API DoExecNsisUninstaller(int argc, LPWSTR *argv) +{ + if (argc != 2) { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + const auto appShortName = std::wstring(argv[0]); + const auto uninstallExePath = std::wstring(argv[1]); + + if (appShortName.empty() + || uninstallExePath.empty()) { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + auto appInstallDir = uninstallExePath; + const auto posLastSlash = appInstallDir.find_last_of(PathSeparator); + if (posLastSlash != std::wstring::npos) { + appInstallDir.erase(posLastSlash); + } else { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + // Run uninstaller + const std::wstring cmd = L'\"' + uninstallExePath + L"\" /S _?=" + appInstallDir; + LogResult(S_OK, "Running '%ls'.", cmd.data()); + Utility::execCmd(cmd); + + LogResult(S_OK, "Waiting for NSIS uninstaller."); + + // Can't wait for the process because Uninstall.exe (opposed to Setup.exe) immediately returns, so we'll sleep a bit. + Utility::waitForNsisUninstaller(appShortName); + + LogResult(S_OK, "Removing the NSIS uninstaller."); + + // Sleep a bit and clean up the NSIS mess + Sleep(1500); + DeleteFile(uninstallExePath.data()); + RemoveDirectory(appInstallDir.data()); + + LogResult(S_OK, "Finished."); + + return S_OK; +} + +HRESULT NCMSIHELPER_API DoRemoveNavigationPaneEntries(int argc, LPWSTR *argv) +{ + if (argc != 1) { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + const auto appName = std::wstring(argv[0]); + + if (appName.empty()) { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + LogResult(S_OK, "Removing '%ls' sync folders from Explorer's Navigation Pane for the current user.", appName.data()); + + Utility::removeNavigationPaneEntries(appName); + + LogResult(S_OK, "Finished."); + + return S_OK; +} diff --git a/admin/win/tools/NCMsiHelper/NCMsiHelper.h b/admin/win/tools/NCMsiHelper/NCMsiHelper.h new file mode 100644 index 000000000..36f6d505e --- /dev/null +++ b/admin/win/tools/NCMsiHelper/NCMsiHelper.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Parts of this file are based on: + * https://www.codeproject.com/articles/570751/devmsi-an-example-cplusplus-msi-wix-deferred-custo + * + * Licensed under the The Code Project Open License (CPOL): + * https://www.codeproject.com/info/cpol10.aspx + * + */ + +/** + * Function prototypes for external "C" interfaces into the DLL. + * + * This project builds a "hybrid" DLL that will work either from + * a MSI Custom Action environment or from an external C program. + * The former routes through "C" interface functions defined in + * CustomAction.def. The latter uses the interfaces defined here. + * + * This header is suitable for inclusion by a project wanting to + * call these methods. Note that _NCMSIHELPER_EXPORTS should not be + * defined for the accessing application source code. + */ +#pragma once + +#include + +#ifdef _NCMSIHELPER_EXPORTS +# pragma comment (lib, "newdev") +# pragma comment (lib, "setupapi") +# pragma comment (lib, "msi") +# pragma comment (lib, "dutil") +# pragma comment (lib, "wcautil") +# pragma comment (lib, "Version") + +# include +# include +# include +# include +# include + +// WiX Header Files: +# include +# include + +# define NCMSIHELPER_API __declspec(dllexport) +#else +# define NCMSIHELPER_API __declspec(dllimport) +#endif + +/** + * Runs the NSIS uninstaller and waits for its completion. + * + * argc MUST be 2. + * + * argv[0] is APPLICATION_EXECUTABLE, e.g. "nextcloud" + * argv[1] is the full path to "Uninstall.exe" + * + * @param argc The count of valid arguments in argv. + * @param argv An array of string arguments for the function. + * @return Returns an HRESULT indicating success or failure. + */ +HRESULT NCMSIHELPER_API DoExecNsisUninstaller(int argc, LPWSTR *argv); + + +/** + * Removes the Explorer's Navigation Pane entries. + * + * argc MUST be 1. + * + * argv[0] is APPLICATION_NAME, e.g. "Nextcloud" + * + * @param argc The count of valid arguments in argv. + * @param argv An array of string arguments for the function. + * @return Returns an HRESULT indicating success or failure. + */ +HRESULT NCMSIHELPER_API DoRemoveNavigationPaneEntries(int argc, LPWSTR *argv); + +/** + * Standardized function prototype for NCMsiHelper. + * + * Functions in NCMsiHelper can be called through the MSI Custom + * Action DLL or through an external C program. Both + * methods expect to wrap things into this function prototype. + * + * As a result, all functions defined in this header should + * conform to this function prototype. + */ +using CUSTOM_ACTION_ARGC_ARGV = NCMSIHELPER_API HRESULT(*)(int argc, LPWSTR *argv); diff --git a/admin/win/tools/NCMsiHelper/NCMsiHelper.wxs b/admin/win/tools/NCMsiHelper/NCMsiHelper.wxs new file mode 100644 index 000000000..181a55a0c --- /dev/null +++ b/admin/win/tools/NCMsiHelper/NCMsiHelper.wxs @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + diff --git a/admin/win/tools/NCNavRemove/CMakeLists.txt b/admin/win/tools/NCNavRemove/CMakeLists.txt new file mode 100644 index 000000000..8199d3a09 --- /dev/null +++ b/admin/win/tools/NCNavRemove/CMakeLists.txt @@ -0,0 +1,14 @@ +project(NCNavRemove) + +set(MUTEX_NAME "NCNavRemove") + +configure_file(NavRemoveConstants.h.in ${CMAKE_CURRENT_BINARY_DIR}/NavRemoveConstants.h) +configure_file(NavRemove.ini.in ${CMAKE_CURRENT_BINARY_DIR}/NavRemove.ini) +configure_file(version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc) + +add_subdirectory(dll) +add_subdirectory(exe) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/NavRemove.ini + DESTINATION tools/NCNavRemove/ +) diff --git a/admin/win/tools/NCNavRemove/ConfigIni.cpp b/admin/win/tools/NCNavRemove/ConfigIni.cpp new file mode 100644 index 000000000..9ffb228aa --- /dev/null +++ b/admin/win/tools/NCNavRemove/ConfigIni.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include "3rdparty/SimpleIni.h" +#include "NavRemoveConstants.h" +#include "ConfigIni.h" + +ConfigIni::ConfigIni() +{ +} + +bool ConfigIni::load() +{ + const DWORD bufferLen = GetCurrentDirectory(0, nullptr); + TCHAR *pszBuffer = nullptr; + + if (bufferLen == 0) { + return false; + } + + pszBuffer = new TCHAR[bufferLen]; + if (!pszBuffer) { + return false; + } + + std::wstring filename; + if (GetCurrentDirectory(bufferLen, pszBuffer) != 0) { + filename = pszBuffer; + } + delete[] pszBuffer; + + if (filename.empty()) { + return false; + } + + filename.append(L"\\"); + filename.append(INI_NAME); + + CSimpleIni ini; + const wchar_t iniSection[] = CFG_KEY; + const wchar_t iniKey[] = CFG_VAR_APPNAME; + + const auto rc = ini.LoadFile(filename.data()); + + if (rc != SI_OK) { + return false; + } + + const auto pv = ini.GetValue(iniSection, iniKey); + bool success = false; + + if (pv) { + _appName = pv; + success = !_appName.empty(); + } + + ini.Reset(); + + return success; +} + +std::wstring ConfigIni::getAppName() const +{ + return _appName; +} diff --git a/admin/win/tools/NCNavRemove/ConfigIni.h b/admin/win/tools/NCNavRemove/ConfigIni.h new file mode 100644 index 000000000..8d6de716f --- /dev/null +++ b/admin/win/tools/NCNavRemove/ConfigIni.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include + +class ConfigIni +{ +public: + ConfigIni(); + + bool load(); + + std::wstring getAppName() const; + +private: + std::wstring _appName; +}; diff --git a/admin/win/tools/NCNavRemove/NavRemove.ini.in b/admin/win/tools/NCNavRemove/NavRemove.ini.in new file mode 100644 index 000000000..3f7ac1a93 --- /dev/null +++ b/admin/win/tools/NCNavRemove/NavRemove.ini.in @@ -0,0 +1,2 @@ +[NavRemove] +ApplicationName=@APPLICATION_NAME@ diff --git a/admin/win/tools/NCNavRemove/NavRemoveConstants.h.in b/admin/win/tools/NCNavRemove/NavRemoveConstants.h.in new file mode 100644 index 000000000..476a7e653 --- /dev/null +++ b/admin/win/tools/NCNavRemove/NavRemoveConstants.h.in @@ -0,0 +1,9 @@ +#pragma once + +#define MUTEX_NAME L"@MUTEX_NAME@" +#define TOOL_NAME L"NCNavRemove (@BITNESS@-bit)" +#define TOOL_DESCRIPTION L"Removes all Explorer Navigation Pane entries for a given ApplicationName." + +#define INI_NAME L"NavRemove.ini" +#define CFG_KEY L"NavRemove" +#define CFG_VAR_APPNAME L"ApplicationName" diff --git a/admin/win/tools/NCNavRemove/dll/CMakeLists.txt b/admin/win/tools/NCNavRemove/dll/CMakeLists.txt new file mode 100644 index 000000000..3b653cf7c --- /dev/null +++ b/admin/win/tools/NCNavRemove/dll/CMakeLists.txt @@ -0,0 +1,25 @@ +add_definitions(-D_NAVREMOVE_EXPORTS) +add_definitions(-D_USRDLL) +add_definitions(-D_WINDLL) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../ +) + +set(TARGET_NAME libNavRemove${BITNESS}) + +add_library(${TARGET_NAME} MODULE + dllmain.cpp + NavRemove.cpp + exports.def + ../ConfigIni.cpp + ${CMAKE_CURRENT_BINARY_DIR}/../version.rc +) + +target_link_libraries(${TARGET_NAME} + NCToolsShared +) + +install(TARGETS ${TARGET_NAME} + DESTINATION tools/NCNavRemove/dll/ +) diff --git a/admin/win/tools/NCNavRemove/dll/NavRemove.cpp b/admin/win/tools/NCNavRemove/dll/NavRemove.cpp new file mode 100644 index 000000000..b60091c16 --- /dev/null +++ b/admin/win/tools/NCNavRemove/dll/NavRemove.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include "utility.h" +#include "NavRemove.h" +#include "../ConfigIni.h" + +using namespace NCTools; + +extern bool g_alreadyRunning; + +HRESULT NAVREMOVE_API RemoveNavigationPaneEntries() +{ + if (g_alreadyRunning) { + return S_OK; + } + + // Config + ConfigIni ini; + + if (!ini.load()) { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + + Utility::removeNavigationPaneEntries(ini.getAppName()); + + return S_OK; +} diff --git a/admin/win/tools/NCNavRemove/dll/NavRemove.h b/admin/win/tools/NCNavRemove/dll/NavRemove.h new file mode 100644 index 000000000..143cd917c --- /dev/null +++ b/admin/win/tools/NCNavRemove/dll/NavRemove.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the _NAVREMOVE_EXPORTS +// symbol defined on the command line. This symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// NAVREMOVE_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. + +#ifdef _NAVREMOVE_EXPORTS +#define NAVREMOVE_API __declspec(dllexport) +#else +#define NAVREMOVE_API __declspec(dllimport) +#endif + +NAVREMOVE_API HRESULT RemoveNavigationPaneEntries(); diff --git a/admin/win/tools/NCNavRemove/dll/dllmain.cpp b/admin/win/tools/NCNavRemove/dll/dllmain.cpp new file mode 100644 index 000000000..d70a53d76 --- /dev/null +++ b/admin/win/tools/NCNavRemove/dll/dllmain.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include "SimpleNamedMutex.h" +#include "NavRemoveConstants.h" + +SimpleNamedMutex g_mutex(std::wstring(MUTEX_NAME)); +bool g_alreadyRunning = false; + +extern "C" BOOL WINAPI DllMain( + __in HINSTANCE hInst, + __in ULONG ulReason, + __in LPVOID + ) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + // Mutex + g_alreadyRunning = !g_mutex.lock(); + break; + + case DLL_PROCESS_DETACH: + // Release mutex + g_mutex.unlock(); + break; + } + + return TRUE; +} diff --git a/admin/win/tools/NCNavRemove/dll/exports.def b/admin/win/tools/NCNavRemove/dll/exports.def new file mode 100644 index 000000000..fac11532b --- /dev/null +++ b/admin/win/tools/NCNavRemove/dll/exports.def @@ -0,0 +1,2 @@ +EXPORTS +RemoveNavigationPaneEntries diff --git a/admin/win/tools/NCNavRemove/exe/CMakeLists.txt b/admin/win/tools/NCNavRemove/exe/CMakeLists.txt new file mode 100644 index 000000000..1288266bd --- /dev/null +++ b/admin/win/tools/NCNavRemove/exe/CMakeLists.txt @@ -0,0 +1,19 @@ +set(TARGET_NAME NavRemove${BITNESS}) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../ +) + +add_executable(${TARGET_NAME} WIN32 + main.cpp + ../ConfigIni.cpp + ${CMAKE_CURRENT_BINARY_DIR}/../version.rc +) + +target_link_libraries(${TARGET_NAME} + NCToolsShared +) + +install(TARGETS ${TARGET_NAME} + DESTINATION tools/NCNavRemove/exe/ +) diff --git a/admin/win/tools/NCNavRemove/exe/main.cpp b/admin/win/tools/NCNavRemove/exe/main.cpp new file mode 100644 index 000000000..851f34652 --- /dev/null +++ b/admin/win/tools/NCNavRemove/exe/main.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include "utility.h" +#include "SimpleNamedMutex.h" +#include "NavRemoveConstants.h" +#include "../ConfigIni.h" + +using namespace NCTools; + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) +{ + UNREFERENCED_PARAMETER(hInstance); + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + UNREFERENCED_PARAMETER(nCmdShow); + + // Mutex + SimpleNamedMutex mutex(std::wstring(MUTEX_NAME)); + + if (!mutex.lock()) { + return 0; + } + + // Config + ConfigIni ini; + + if (!ini.load()) { + return 1; + } + + Utility::removeNavigationPaneEntries(ini.getAppName()); + + // Release mutex + mutex.unlock(); + + return 0; +} diff --git a/admin/win/tools/NCNavRemove/version.rc.in b/admin/win/tools/NCNavRemove/version.rc.in new file mode 100644 index 000000000..069ac7cfa --- /dev/null +++ b/admin/win/tools/NCNavRemove/version.rc.in @@ -0,0 +1,40 @@ +#include "winresrc.h" +#include "NavRemoveConstants.h" + +#define VER_FILEVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@MIRALL_VERSION_BUILD@ +#define VER_FILEVERSION_STR "@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@.@MIRALL_VERSION_PATCH@.@MIRALL_VERSION_BUILD@\0" + +#define VER_PRODUCTVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@MIRALL_VERSION_BUILD@ +#define VER_PRODUCTVERSION_STR "@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@.@MIRALL_VERSION_PATCH@.@MIRALL_VERSION_BUILD@\0" + +#define VER_PRODUCTNAME_STR TOOL_NAME +#define VER_COMPANYNAME_STR "@APPLICATION_VENDOR@" +#define VER_COPYRIGHT_STR "(c) @MIRALL_VERSION_YEAR@" + +#define VER_PRODUCTDESC_STR TOOL_DESCRIPTION + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "LegalCopyright", VER_COPYRIGHT_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "Comment", VER_PRODUCTNAME_STR + VALUE "FileDescription", VER_PRODUCTDESC_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END diff --git a/admin/win/tools/NCToolsShared/3rdparty/SimpleIni.h b/admin/win/tools/NCToolsShared/3rdparty/SimpleIni.h new file mode 100644 index 000000000..da923c4fe --- /dev/null +++ b/admin/win/tools/NCToolsShared/3rdparty/SimpleIni.h @@ -0,0 +1,3474 @@ +/** @mainpage + + +
Library SimpleIni +
File SimpleIni.h +
Author Brodie Thiesfield [brofield at gmail dot com] +
Source https://github.com/brofield/simpleini +
Version 4.17 +
+ + Jump to the @link CSimpleIniTempl CSimpleIni @endlink interface documentation. + + @section intro INTRODUCTION + + This component allows an INI-style configuration file to be used on both + Windows and Linux/Unix. It is fast, simple and source code using this + component will compile unchanged on either OS. + + + @section features FEATURES + + - MIT Licence allows free use in all software (including GPL and commercial) + - multi-platform (Windows CE/9x/NT..10/etc, Linux, MacOSX, Unix) + - loading and saving of INI-style configuration files + - configuration files can have any newline format on all platforms + - liberal acceptance of file format + - key/values with no section + - removal of whitespace around sections, keys and values + - support for multi-line values (values with embedded newline characters) + - optional support for multiple keys with the same name + - optional case-insensitive sections and keys (for ASCII characters only) + - saves files with sections and keys in the same order as they were loaded + - preserves comments on the file, section and keys where possible. + - supports both char or wchar_t programming interfaces + - supports both MBCS (system locale) and UTF-8 file encodings + - system locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file + - support for non-ASCII characters in section, keys, values and comments + - support for non-standard character types or file encodings + via user-written converter classes + - support for adding/modifying values programmatically + - compiles cleanly in the following compilers: + - Windows/VC6 (warning level 3) + - Windows/VC.NET 2003 (warning level 4) + - Windows/VC 2005 (warning level 4) + - Linux/gcc (-Wall) + + + @section usage USAGE SUMMARY + + -# Define the appropriate symbol for the converter you wish to use and + include the SimpleIni.h header file. If no specific converter is defined + then the default converter is used. The default conversion mode uses + SI_CONVERT_WIN32 on Windows and SI_CONVERT_GENERIC on all other + platforms. If you are using ICU then SI_CONVERT_ICU is supported on all + platforms. + -# Declare an instance the appropriate class. Note that the following + definitions are just shortcuts for commonly used types. Other types + (PRUnichar, unsigned short, unsigned char) are also possible. + +
Interface Case-sensitive Load UTF-8 Load MBCS Typedef +
SI_CONVERT_GENERIC +
char No Yes Yes #1 CSimpleIniA +
char Yes Yes Yes CSimpleIniCaseA +
wchar_t No Yes Yes CSimpleIniW +
wchar_t Yes Yes Yes CSimpleIniCaseW +
SI_CONVERT_WIN32 +
char No No #2 Yes CSimpleIniA +
char Yes Yes Yes CSimpleIniCaseA +
wchar_t No Yes Yes CSimpleIniW +
wchar_t Yes Yes Yes CSimpleIniCaseW +
SI_CONVERT_ICU +
char No Yes Yes CSimpleIniA +
char Yes Yes Yes CSimpleIniCaseA +
UChar No Yes Yes CSimpleIniW +
UChar Yes Yes Yes CSimpleIniCaseW +
+ #1 On Windows you are better to use CSimpleIniA with SI_CONVERT_WIN32.
+ #2 Only affects Windows. On Windows this uses MBCS functions and + so may fold case incorrectly leading to uncertain results. + -# Call LoadData() or LoadFile() to load and parse the INI configuration file + -# Access and modify the data of the file using the following functions + +
GetAllSections Return all section names +
GetAllKeys Return all key names within a section +
GetAllValues Return all values within a section & key +
GetSection Return all key names and values in a section +
GetSectionSize Return the number of keys in a section +
GetValue Return a value for a section & key +
SetValue Add or update a value for a section & key +
Delete Remove a section, or a key from a section +
+ -# Call Save() or SaveFile() to save the INI configuration data + + @section iostreams IO STREAMS + + SimpleIni supports reading from and writing to STL IO streams. Enable this + by defining SI_SUPPORT_IOSTREAMS before including the SimpleIni.h header + file. Ensure that if the streams are backed by a file (e.g. ifstream or + ofstream) then the flag ios_base::binary has been used when the file was + opened. + + @section multiline MULTI-LINE VALUES + + Values that span multiple lines are created using the following format. + +

+        key = <<
+
+    Note the following:
+    - The text used for ENDTAG can be anything and is used to find
+      where the multi-line text ends.
+    - The newline after ENDTAG in the start tag, and the newline
+      before ENDTAG in the end tag is not included in the data value.
+    - The ending tag must be on it's own line with no whitespace before
+      or after it.
+    - The multi-line value is modified at load so that each line in the value
+      is delimited by a single '\\n' character on all platforms. At save time
+      it will be converted into the newline format used by the current
+      platform.
+
+    @section comments COMMENTS
+
+    Comments are preserved in the file within the following restrictions:
+    - Every file may have a single "file comment". It must start with the
+      first character in the file, and will end with the first non-comment
+      line in the file.
+    - Every section may have a single "section comment". It will start
+      with the first comment line following the file comment, or the last
+      data entry. It ends at the beginning of the section.
+    - Every key may have a single "key comment". This comment will start
+      with the first comment line following the section start, or the file
+      comment if there is no section name.
+    - Comments are set at the time that the file, section or key is first
+      created. The only way to modify a comment on a section or a key is to
+      delete that entry and recreate it with the new comment. There is no
+      way to change the file comment.
+
+    @section save SAVE ORDER
+
+    The sections and keys are written out in the same order as they were
+    read in from the file. Sections and keys added to the data after the
+    file has been loaded will be added to the end of the file when it is
+    written. There is no way to specify the location of a section or key
+    other than in first-created, first-saved order.
+
+    @section notes NOTES
+
+    - To load UTF-8 data on Windows 95, you need to use Microsoft Layer for
+      Unicode, or SI_CONVERT_GENERIC, or SI_CONVERT_ICU.
+    - When using SI_CONVERT_GENERIC, ConvertUTF.c must be compiled and linked.
+    - When using SI_CONVERT_ICU, ICU header files must be on the include
+      path and icuuc.lib must be linked in.
+    - To load a UTF-8 file on Windows AND expose it with SI_CHAR == char,
+      you should use SI_CONVERT_GENERIC.
+    - The collation (sorting) order used for sections and keys returned from
+      iterators is NOT DEFINED. If collation order of the text is important
+      then it should be done yourself by either supplying a replacement
+      SI_STRLESS class, or by sorting the strings external to this library.
+    - Usage of the  header on Windows can be disabled by defining
+      SI_NO_MBCS. This is defined automatically on Windows CE platforms.
+    - Not thread-safe so manage your own locking
+
+    @section contrib CONTRIBUTIONS
+    
+    - 2010/05/03: Tobias Gehrig: added GetDoubleValue()
+
+    @section licence MIT LICENCE
+
+    The licence text below is the boilerplate "MIT Licence" used from:
+    http://www.opensource.org/licenses/mit-license.php
+
+    Copyright (c) 2006-2012, Brodie Thiesfield
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is furnished
+    to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+    FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef INCLUDED_SimpleIni_h
+#define INCLUDED_SimpleIni_h
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// Disable these warnings in MSVC:
+//  4127 "conditional expression is constant" as the conversion classes trigger
+//  it with the statement if (sizeof(SI_CHAR) == sizeof(char)). This test will
+//  be optimized away in a release build.
+//  4503 'insert' : decorated name length exceeded, name was truncated
+//  4702 "unreachable code" as the MS STL header causes it in release mode.
+//  Again, the code causing the warning will be cleaned up by the compiler.
+//  4786 "identifier truncated to 256 characters" as this is thrown hundreds
+//  of times VC6 as soon as STL is used.
+#ifdef _MSC_VER
+# pragma warning (push)
+# pragma warning (disable: 4127 4503 4702 4786)
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef SI_SUPPORT_IOSTREAMS
+# include 
+#endif // SI_SUPPORT_IOSTREAMS
+
+#ifdef _DEBUG
+# ifndef assert
+#  include 
+# endif
+# define SI_ASSERT(x)   assert(x)
+#else
+# define SI_ASSERT(x)
+#endif
+
+enum SI_Error {
+    SI_OK       =  0,   //!< No error
+    SI_UPDATED  =  1,   //!< An existing value was updated
+    SI_INSERTED =  2,   //!< A new value was inserted
+
+    // note: test for any error with (retval < 0)
+    SI_FAIL     = -1,   //!< Generic failure
+    SI_NOMEM    = -2,   //!< Out of memory error
+    SI_FILE     = -3    //!< File error (see errno for detail error)
+};
+
+#define SI_UTF8_SIGNATURE     "\xEF\xBB\xBF"
+
+#ifdef _WIN32
+# define SI_NEWLINE_A   "\r\n"
+# define SI_NEWLINE_W   L"\r\n"
+#else // !_WIN32
+# define SI_NEWLINE_A   "\n"
+# define SI_NEWLINE_W   L"\n"
+#endif // _WIN32
+
+#if defined(SI_CONVERT_ICU)
+# include 
+#endif
+
+#if defined(_WIN32)
+# define SI_HAS_WIDE_FILE
+# define SI_WCHAR_T     wchar_t
+#elif defined(SI_CONVERT_ICU)
+# define SI_HAS_WIDE_FILE
+# define SI_WCHAR_T     UChar
+#endif
+
+
+// ---------------------------------------------------------------------------
+//                              MAIN TEMPLATE CLASS
+// ---------------------------------------------------------------------------
+
+/** Simple INI file reader.
+
+    This can be instantiated with the choice of unicode or native characterset,
+    and case sensitive or insensitive comparisons of section and key names.
+    The supported combinations are pre-defined with the following typedefs:
+
+    
+        
Interface Case-sensitive Typedef +
char No CSimpleIniA +
char Yes CSimpleIniCaseA +
wchar_t No CSimpleIniW +
wchar_t Yes CSimpleIniCaseW +
+ + Note that using other types for the SI_CHAR is supported. For instance, + unsigned char, unsigned short, etc. Note that where the alternative type + is a different size to char/wchar_t you may need to supply new helper + classes for SI_STRLESS and SI_CONVERTER. + */ +template +class CSimpleIniTempl +{ +public: + typedef SI_CHAR SI_CHAR_T; + + /** key entry */ + struct Entry { + const SI_CHAR * pItem; + const SI_CHAR * pComment; + int nOrder; + + Entry(const SI_CHAR * a_pszItem = nullptr, int a_nOrder = 0) + : pItem(a_pszItem) + , pComment(nullptr) + , nOrder(a_nOrder) + { } + Entry(const SI_CHAR * a_pszItem, const SI_CHAR * a_pszComment, int a_nOrder) + : pItem(a_pszItem) + , pComment(a_pszComment) + , nOrder(a_nOrder) + { } + Entry(const Entry & rhs) { operator=(rhs); } + Entry & operator=(const Entry & rhs) { + pItem = rhs.pItem; + pComment = rhs.pComment; + nOrder = rhs.nOrder; + return *this; + } + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + /** STL of VC6 doesn't allow me to specify my own comparator for list::sort() */ + bool operator<(const Entry & rhs) const { return LoadOrder()(*this, rhs); } + bool operator>(const Entry & rhs) const { return LoadOrder()(rhs, *this); } +#endif + + /** Strict less ordering by name of key only */ + struct KeyOrder { + bool operator()(const Entry & lhs, const Entry & rhs) const { + const static SI_STRLESS isLess = SI_STRLESS(); + return isLess(lhs.pItem, rhs.pItem); + } + }; + + /** Strict less ordering by order, and then name of key */ + struct LoadOrder { + bool operator()(const Entry & lhs, const Entry & rhs) const { + if (lhs.nOrder != rhs.nOrder) { + return lhs.nOrder < rhs.nOrder; + } + return KeyOrder()(lhs.pItem, rhs.pItem); + } + }; + }; + + /** map keys to values */ + typedef std::multimap TKeyVal; + + /** map sections to key/value map */ + typedef std::map TSection; + + /** set of dependent string pointers. Note that these pointers are + dependent on memory owned by CSimpleIni. + */ + typedef std::list TNamesDepend; + + /** interface definition for the OutputWriter object to pass to Save() + in order to output the INI file data. + */ + class OutputWriter { + public: + OutputWriter() { } + virtual ~OutputWriter() { } + virtual void Write(const char * a_pBuf) = 0; + private: + OutputWriter(const OutputWriter &); // disable + OutputWriter & operator=(const OutputWriter &); // disable + }; + + /** OutputWriter class to write the INI data to a file */ + class FileWriter : public OutputWriter { + FILE * m_file; + public: + FileWriter(FILE * a_file) : m_file(a_file) { } + void Write(const char * a_pBuf) { + fputs(a_pBuf, m_file); + } + private: + FileWriter(const FileWriter &); // disable + FileWriter & operator=(const FileWriter &); // disable + }; + + /** OutputWriter class to write the INI data to a string */ + class StringWriter : public OutputWriter { + std::string & m_string; + public: + StringWriter(std::string & a_string) : m_string(a_string) { } + void Write(const char * a_pBuf) { + m_string.append(a_pBuf); + } + private: + StringWriter(const StringWriter &); // disable + StringWriter & operator=(const StringWriter &); // disable + }; + +#ifdef SI_SUPPORT_IOSTREAMS + /** OutputWriter class to write the INI data to an ostream */ + class StreamWriter : public OutputWriter { + std::ostream & m_ostream; + public: + StreamWriter(std::ostream & a_ostream) : m_ostream(a_ostream) { } + void Write(const char * a_pBuf) { + m_ostream << a_pBuf; + } + private: + StreamWriter(const StreamWriter &); // disable + StreamWriter & operator=(const StreamWriter &); // disable + }; +#endif // SI_SUPPORT_IOSTREAMS + + /** Characterset conversion utility class to convert strings to the + same format as is used for the storage. + */ + class Converter : private SI_CONVERTER { + public: + Converter(bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) { + m_scratch.resize(1024); + } + Converter(const Converter & rhs) { operator=(rhs); } + Converter & operator=(const Converter & rhs) { + m_scratch = rhs.m_scratch; + return *this; + } + bool ConvertToStore(const SI_CHAR * a_pszString) { + size_t uLen = SI_CONVERTER::SizeToStore(a_pszString); + if (uLen == (size_t)(-1)) { + return false; + } + while (uLen > m_scratch.size()) { + m_scratch.resize(m_scratch.size() * 2); + } + return SI_CONVERTER::ConvertToStore( + a_pszString, + const_cast(m_scratch.data()), + m_scratch.size()); + } + const char * Data() { return m_scratch.data(); } + private: + std::string m_scratch; + }; + +public: + /*-----------------------------------------------------------------------*/ + + /** Default constructor. + + @param a_bIsUtf8 See the method SetUnicode() for details. + @param a_bMultiKey See the method SetMultiKey() for details. + @param a_bMultiLine See the method SetMultiLine() for details. + */ + CSimpleIniTempl( + bool a_bIsUtf8 = false, + bool a_bMultiKey = false, + bool a_bMultiLine = false + ); + + /** Destructor */ + ~CSimpleIniTempl(); + + /** Deallocate all memory stored by this object */ + void Reset(); + + /** Has any data been loaded */ + bool IsEmpty() const { return m_data.empty(); } + + /*-----------------------------------------------------------------------*/ + /** @{ @name Settings */ + + /** Set the storage format of the INI data. This affects both the loading + and saving of the INI data using all of the Load/Save API functions. + This value cannot be changed after any INI data has been loaded. + + If the file is not set to Unicode (UTF-8), then the data encoding is + assumed to be the OS native encoding. This encoding is the system + locale on Linux/Unix and the legacy MBCS encoding on Windows NT/2K/XP. + If the storage format is set to Unicode then the file will be loaded + as UTF-8 encoded data regardless of the native file encoding. If + SI_CHAR == char then all of the char* parameters take and return UTF-8 + encoded data regardless of the system locale. + + \param a_bIsUtf8 Assume UTF-8 encoding for the source? + */ + void SetUnicode(bool a_bIsUtf8 = true) { + if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8; + } + + /** Get the storage format of the INI data. */ + bool IsUnicode() const { return m_bStoreIsUtf8; } + + /** Should multiple identical keys be permitted in the file. If set to false + then the last value encountered will be used as the value of the key. + If set to true, then all values will be available to be queried. For + example, with the following input: + +
+        [section]
+        test=value1
+        test=value2
+        
+ + Then with SetMultiKey(true), both of the values "value1" and "value2" + will be returned for the key test. If SetMultiKey(false) is used, then + the value for "test" will only be "value2". This value may be changed + at any time. + + \param a_bAllowMultiKey Allow multi-keys in the source? + */ + void SetMultiKey(bool a_bAllowMultiKey = true) { + m_bAllowMultiKey = a_bAllowMultiKey; + } + + /** Get the storage format of the INI data. */ + bool IsMultiKey() const { return m_bAllowMultiKey; } + + /** Should data values be permitted to span multiple lines in the file. If + set to false then the multi-line construct << + SI_CHAR FORMAT + char same format as when loaded (MBCS or UTF-8) + wchar_t UTF-8 + other UTF-8 + + + Note that comments from the original data is preserved as per the + documentation on comments. The order of the sections and values + from the original file will be preserved. + + Any data prepended or appended to the output device must use the the + same format (MBCS or UTF-8). You may use the GetConverter() method to + convert text to the correct format regardless of the output format + being used by SimpleIni. + + To add a BOM to UTF-8 data, write it out manually at the very beginning + like is done in SaveFile when a_bUseBOM is true. + + @param a_oOutput Output writer to write the data to. + + @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in + UTF-8 format. If it is not UTF-8 then this value is + ignored. Do not set this to true if anything has + already been written to the OutputWriter. + + @return SI_Error See error definitions + */ + SI_Error Save( + OutputWriter & a_oOutput, + bool a_bAddSignature = false + ) const; + +#ifdef SI_SUPPORT_IOSTREAMS + /** Save the INI data to an ostream. See Save() for details. + + @param a_ostream String to have the INI data appended to. + + @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in + UTF-8 format. If it is not UTF-8 then this value is + ignored. Do not set this to true if anything has + already been written to the stream. + + @return SI_Error See error definitions + */ + SI_Error Save( + std::ostream & a_ostream, + bool a_bAddSignature = false + ) const + { + StreamWriter writer(a_ostream); + return Save(writer, a_bAddSignature); + } +#endif // SI_SUPPORT_IOSTREAMS + + /** Append the INI data to a string. See Save() for details. + + @param a_sBuffer String to have the INI data appended to. + + @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in + UTF-8 format. If it is not UTF-8 then this value is + ignored. Do not set this to true if anything has + already been written to the string. + + @return SI_Error See error definitions + */ + SI_Error Save( + std::string & a_sBuffer, + bool a_bAddSignature = false + ) const + { + StringWriter writer(a_sBuffer); + return Save(writer, a_bAddSignature); + } + + /*-----------------------------------------------------------------------*/ + /** @} + @{ @name Accessing INI Data */ + + /** Retrieve all section names. The list is returned as an STL vector of + names and can be iterated or searched as necessary. Note that the + sort order of the returned strings is NOT DEFINED. You can sort + the names into the load order if desired. Search this file for ".sort" + for an example. + + NOTE! This structure contains only pointers to strings. The actual + string data is stored in memory owned by CSimpleIni. Ensure that the + CSimpleIni object is not destroyed or Reset() while these pointers + are in use! + + @param a_names Vector that will receive all of the section + names. See note above! + */ + void GetAllSections( + TNamesDepend & a_names + ) const; + + /** Retrieve all unique key names in a section. The sort order of the + returned strings is NOT DEFINED. You can sort the names into the load + order if desired. Search this file for ".sort" for an example. Only + unique key names are returned. + + NOTE! This structure contains only pointers to strings. The actual + string data is stored in memory owned by CSimpleIni. Ensure that the + CSimpleIni object is not destroyed or Reset() while these strings + are in use! + + @param a_pSection Section to request data for + @param a_names List that will receive all of the key + names. See note above! + + @return true Section was found. + @return false Matching section was not found. + */ + bool GetAllKeys( + const SI_CHAR * a_pSection, + TNamesDepend & a_names + ) const; + + /** Retrieve all values for a specific key. This method can be used when + multiple keys are both enabled and disabled. Note that the sort order + of the returned strings is NOT DEFINED. You can sort the names into + the load order if desired. Search this file for ".sort" for an example. + + NOTE! The returned values are pointers to string data stored in memory + owned by CSimpleIni. Ensure that the CSimpleIni object is not destroyed + or Reset while you are using this pointer! + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_values List to return if the key is not found + + @return true Key was found. + @return false Matching section/key was not found. + */ + bool GetAllValues( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + TNamesDepend & a_values + ) const; + + /** Query the number of keys in a specific section. Note that if multiple + keys are enabled, then this value may be different to the number of + keys returned by GetAllKeys. + + @param a_pSection Section to request data for + + @return -1 Section does not exist in the file + @return >=0 Number of keys in the section + */ + int GetSectionSize( + const SI_CHAR * a_pSection + ) const; + + /** Retrieve all key and value pairs for a section. The data is returned + as a pointer to an STL map and can be iterated or searched as + desired. Note that multiple entries for the same key may exist when + multiple keys have been enabled. + + NOTE! This structure contains only pointers to strings. The actual + string data is stored in memory owned by CSimpleIni. Ensure that the + CSimpleIni object is not destroyed or Reset() while these strings + are in use! + + @param a_pSection Name of the section to return + @return boolean Was a section matching the supplied + name found. + */ + const TKeyVal * GetSection( + const SI_CHAR * a_pSection + ) const; + + /** Retrieve the value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + NOTE! The returned value is a pointer to string data stored in memory + owned by CSimpleIni. Ensure that the CSimpleIni object is not destroyed + or Reset while you are using this pointer! + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_pDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_pDefault Key was not found in the section + @return other Value of the key + */ + const SI_CHAR * GetValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pDefault = nullptr, + bool * a_pHasMultiple = nullptr + ) const; + + /** Retrieve a numeric value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_nDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_nDefault Key was not found in the section + @return other Value of the key + */ + long GetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nDefault = 0, + bool * a_pHasMultiple = nullptr + ) const; + + /** Retrieve a numeric value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_nDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_nDefault Key was not found in the section + @return other Value of the key + */ + double GetDoubleValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + double a_nDefault = 0, + bool * a_pHasMultiple = nullptr + ) const; + + /** Retrieve a boolean value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + Strings starting with "t", "y", "on" or "1" are returned as logically true. + Strings starting with "f", "n", "of" or "0" are returned as logically false. + For all other values the default is returned. Character comparisons are + case-insensitive. + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_bDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_nDefault Key was not found in the section + @return other Value of the key + */ + bool GetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bDefault = false, + bool * a_pHasMultiple = nullptr + ) const; + + /** Add or update a section or value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. Set to nullptr to + create an empty section. + @param a_pValue Value to set. Set to nullptr to create an + empty section. + @param a_pComment Comment to be associated with the section or the + key. If a_pKey is nullptr then it will be associated + with the section, otherwise the key. Note that a + comment may be set ONLY when the section or key is + first created (i.e. when this function returns the + value SI_INSERTED). If you wish to create a section + with a comment then you need to create the section + separately to the key. The comment string must be + in full comment form already (have a comment + character starting every line). + @param a_bForceReplace Should all existing values in a multi-key INI + file be replaced with this entry. This option has + no effect if not using multi-key files. The + difference between Delete/SetValue and SetValue + with a_bForceReplace = true, is that the load + order and comment will be preserved this way. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pValue, + const SI_CHAR * a_pComment = nullptr, + bool a_bForceReplace = false + ) + { + return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace, true); + } + + /** Add or update a numeric value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. + @param a_nValue Value to set. + @param a_pComment Comment to be associated with the key. See the + notes on SetValue() for comments. + @param a_bUseHex By default the value will be written to the file + in decimal format. Set this to true to write it + as hexadecimal. + @param a_bForceReplace Should all existing values in a multi-key INI + file be replaced with this entry. This option has + no effect if not using multi-key files. The + difference between Delete/SetLongValue and + SetLongValue with a_bForceReplace = true, is that + the load order and comment will be preserved this + way. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nValue, + const SI_CHAR * a_pComment = nullptr, + bool a_bUseHex = false, + bool a_bForceReplace = false + ); + + /** Add or update a double value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. + @param a_nValue Value to set. + @param a_pComment Comment to be associated with the key. See the + notes on SetValue() for comments. + @param a_bForceReplace Should all existing values in a multi-key INI + file be replaced with this entry. This option has + no effect if not using multi-key files. The + difference between Delete/SetDoubleValue and + SetDoubleValue with a_bForceReplace = true, is that + the load order and comment will be preserved this + way. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetDoubleValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + double a_nValue, + const SI_CHAR * a_pComment = nullptr, + bool a_bForceReplace = false + ); + + /** Add or update a boolean value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. + @param a_bValue Value to set. + @param a_pComment Comment to be associated with the key. See the + notes on SetValue() for comments. + @param a_bForceReplace Should all existing values in a multi-key INI + file be replaced with this entry. This option has + no effect if not using multi-key files. The + difference between Delete/SetBoolValue and + SetBoolValue with a_bForceReplace = true, is that + the load order and comment will be preserved this + way. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bValue, + const SI_CHAR * a_pComment = nullptr, + bool a_bForceReplace = false + ); + + /** Delete an entire section, or a key from a section. Note that the + data returned by GetSection is invalid and must not be used after + anything has been deleted from that section using this method. + Note when multiple keys is enabled, this will delete all keys with + that name; to selectively delete individual key/values, use + DeleteValue. + + @param a_pSection Section to delete key from, or if + a_pKey is nullptr, the section to remove. + @param a_pKey Key to remove from the section. Set to + nullptr to remove the entire section. + @param a_bRemoveEmpty If the section is empty after this key has + been deleted, should the empty section be + removed? + + @return true Key or section was deleted. + @return false Key or section was not found. + */ + bool Delete( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bRemoveEmpty = false + ); + + /** Delete an entire section, or a key from a section. If value is + provided, only remove keys with the value. Note that the data + returned by GetSection is invalid and must not be used after + anything has been deleted from that section using this method. + Note when multiple keys is enabled, all keys with the value will + be deleted. + + @param a_pSection Section to delete key from, or if + a_pKey is nullptr, the section to remove. + @param a_pKey Key to remove from the section. Set to + nullptr to remove the entire section. + @param a_pValue Value of key to remove from the section. + Set to nullptr to remove all keys. + @param a_bRemoveEmpty If the section is empty after this key has + been deleted, should the empty section be + removed? + + @return true Key/value or section was deleted. + @return false Key/value or section was not found. + */ + bool DeleteValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pValue, + bool a_bRemoveEmpty = false + ); + + /*-----------------------------------------------------------------------*/ + /** @} + @{ @name Converter */ + + /** Return a conversion object to convert text to the same encoding + as is used by the Save(), SaveFile() and SaveString() functions. + Use this to prepare the strings that you wish to append or prepend + to the output INI data. + */ + Converter GetConverter() const { + return Converter(m_bStoreIsUtf8); + } + + /*-----------------------------------------------------------------------*/ + /** @} */ + +private: + // copying is not permitted + CSimpleIniTempl(const CSimpleIniTempl &); // disabled + CSimpleIniTempl & operator=(const CSimpleIniTempl &); // disabled + + /** Parse the data looking for a file comment and store it if found. + */ + SI_Error FindFileComment( + SI_CHAR *& a_pData, + bool a_bCopyStrings + ); + + /** Parse the data looking for the next valid entry. The memory pointed to + by a_pData is modified by inserting NULL characters. The pointer is + updated to the current location in the block of text. + */ + bool FindEntry( + SI_CHAR *& a_pData, + const SI_CHAR *& a_pSection, + const SI_CHAR *& a_pKey, + const SI_CHAR *& a_pVal, + const SI_CHAR *& a_pComment + ) const; + + /** Add the section/key/value to our data. + + @param a_pSection Section name. Sections will be created if they + don't already exist. + @param a_pKey Key name. May be nullptr to create an empty section. + Existing entries will be updated. New entries will + be created. + @param a_pValue Value for the key. + @param a_pComment Comment to be associated with the section or the + key. If a_pKey is nullptr then it will be associated + with the section, otherwise the key. This must be + a string in full comment form already (have a + comment character starting every line). + @param a_bForceReplace Should all existing values in a multi-key INI + file be replaced with this entry. This option has + no effect if not using multi-key files. The + difference between Delete/AddEntry and AddEntry + with a_bForceReplace = true, is that the load + order and comment will be preserved this way. + @param a_bCopyStrings Should copies of the strings be made or not. + If false then the pointers will be used as is. + */ + SI_Error AddEntry( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pValue, + const SI_CHAR * a_pComment, + bool a_bForceReplace, + bool a_bCopyStrings + ); + + /** Is the supplied character a whitespace character? */ + inline bool IsSpace(SI_CHAR ch) const { + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); + } + + /** Does the supplied character start a comment line? */ + inline bool IsComment(SI_CHAR ch) const { + return (ch == ';' || ch == '#'); + } + + + /** Skip over a newline character (or characters) for either DOS or UNIX */ + inline void SkipNewLine(SI_CHAR *& a_pData) const { + a_pData += (*a_pData == '\r' && *(a_pData+1) == '\n') ? 2 : 1; + } + + /** Make a copy of the supplied string, replacing the original pointer */ + SI_Error CopyString(const SI_CHAR *& a_pString); + + /** Delete a string from the copied strings buffer if necessary */ + void DeleteString(const SI_CHAR * a_pString); + + /** Internal use of our string comparison function */ + bool IsLess(const SI_CHAR * a_pLeft, const SI_CHAR * a_pRight) const { + const static SI_STRLESS isLess = SI_STRLESS(); + return isLess(a_pLeft, a_pRight); + } + + bool IsMultiLineTag(const SI_CHAR * a_pData) const; + bool IsMultiLineData(const SI_CHAR * a_pData) const; + bool LoadMultiLineText( + SI_CHAR *& a_pData, + const SI_CHAR *& a_pVal, + const SI_CHAR * a_pTagName, + bool a_bAllowBlankLinesInComment = false + ) const; + bool IsNewLineChar(SI_CHAR a_c) const; + + bool OutputMultiLineText( + OutputWriter & a_oOutput, + Converter & a_oConverter, + const SI_CHAR * a_pText + ) const; + +private: + /** Copy of the INI file data in our character format. This will be + modified when parsed to have NULL characters added after all + interesting string entries. All of the string pointers to sections, + keys and values point into this block of memory. + */ + SI_CHAR * m_pData; + + /** Length of the data that we have stored. Used when deleting strings + to determine if the string is stored here or in the allocated string + buffer. + */ + size_t m_uDataLen; + + /** File comment for this data, if one exists. */ + const SI_CHAR * m_pFileComment; + + /** Parsed INI data. Section -> (Key -> Value). */ + TSection m_data; + + /** This vector stores allocated memory for copies of strings that have + been supplied after the file load. It will be empty unless SetValue() + has been called. + */ + TNamesDepend m_strings; + + /** Is the format of our datafile UTF-8 or MBCS? */ + bool m_bStoreIsUtf8; + + /** Are multiple values permitted for the same key? */ + bool m_bAllowMultiKey; + + /** Are data values permitted to span multiple lines? */ + bool m_bAllowMultiLine; + + /** Should spaces be written out surrounding the equals sign? */ + bool m_bSpaces; + + /** Next order value, used to ensure sections and keys are output in the + same order that they are loaded/added. + */ + int m_nOrder; +}; + +// --------------------------------------------------------------------------- +// IMPLEMENTATION +// --------------------------------------------------------------------------- + +template +CSimpleIniTempl::CSimpleIniTempl( + bool a_bIsUtf8, + bool a_bAllowMultiKey, + bool a_bAllowMultiLine + ) + : m_pData(0) + , m_uDataLen(0) + , m_pFileComment(nullptr) + , m_bStoreIsUtf8(a_bIsUtf8) + , m_bAllowMultiKey(a_bAllowMultiKey) + , m_bAllowMultiLine(a_bAllowMultiLine) + , m_bSpaces(true) + , m_nOrder(0) +{ } + +template +CSimpleIniTempl::~CSimpleIniTempl() +{ + Reset(); +} + +template +void +CSimpleIniTempl::Reset() +{ + // remove all data + delete[] m_pData; + m_pData = nullptr; + m_uDataLen = 0; + m_pFileComment = nullptr; + if (!m_data.empty()) { + m_data.erase(m_data.begin(), m_data.end()); + } + + // remove all strings + if (!m_strings.empty()) { + typename TNamesDepend::iterator i = m_strings.begin(); + for (; i != m_strings.end(); ++i) { + delete[] const_cast(i->pItem); + } + m_strings.erase(m_strings.begin(), m_strings.end()); + } +} + +template +SI_Error +CSimpleIniTempl::LoadFile( + const char * a_pszFile + ) +{ + FILE * fp = nullptr; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + fopen_s(&fp, a_pszFile, "rb"); +#else // !__STDC_WANT_SECURE_LIB__ + fp = fopen(a_pszFile, "rb"); +#endif // __STDC_WANT_SECURE_LIB__ + if (!fp) { + return SI_FILE; + } + SI_Error rc = LoadFile(fp); + fclose(fp); + return rc; +} + +#ifdef SI_HAS_WIDE_FILE +template +SI_Error +CSimpleIniTempl::LoadFile( + const SI_WCHAR_T * a_pwszFile + ) +{ +#ifdef _WIN32 + FILE * fp = nullptr; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + _wfopen_s(&fp, a_pwszFile, L"rb"); +#else // !__STDC_WANT_SECURE_LIB__ + fp = _wfopen(a_pwszFile, L"rb"); +#endif // __STDC_WANT_SECURE_LIB__ + if (!fp) return SI_FILE; + SI_Error rc = LoadFile(fp); + fclose(fp); + return rc; +#else // !_WIN32 (therefore SI_CONVERT_ICU) + char szFile[256]; + u_austrncpy(szFile, a_pwszFile, sizeof(szFile)); + return LoadFile(szFile); +#endif // _WIN32 +} +#endif // SI_HAS_WIDE_FILE + +template +SI_Error +CSimpleIniTempl::LoadFile( + FILE * a_fpFile + ) +{ + // load the raw file data + int retval = fseek(a_fpFile, 0, SEEK_END); + if (retval != 0) { + return SI_FILE; + } + long lSize = ftell(a_fpFile); + if (lSize < 0) { + return SI_FILE; + } + if (lSize == 0) { + return SI_OK; + } + + // allocate and ensure NULL terminated + char * pData = new(std::nothrow) char[lSize+1]; + if (!pData) { + return SI_NOMEM; + } + pData[lSize] = 0; + + // load data into buffer + fseek(a_fpFile, 0, SEEK_SET); + size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile); + if (uRead != (size_t) lSize) { + delete[] pData; + return SI_FILE; + } + + // convert the raw data to unicode + SI_Error rc = LoadData(pData, uRead); + delete[] pData; + return rc; +} + +template +SI_Error +CSimpleIniTempl::LoadData( + const char * a_pData, + size_t a_uDataLen + ) +{ + if (!a_pData) { + return SI_OK; + } + + // if the UTF-8 BOM exists, consume it and set mode to unicode, if we have + // already loaded data and try to change mode half-way through then this will + // be ignored and we will assert in debug versions + if (a_uDataLen >= 3 && memcmp(a_pData, SI_UTF8_SIGNATURE, 3) == 0) { + a_pData += 3; + a_uDataLen -= 3; + SI_ASSERT(m_bStoreIsUtf8 || !m_pData); // we don't expect mixed mode data + SetUnicode(); + } + + if (a_uDataLen == 0) { + return SI_OK; + } + + // determine the length of the converted data + SI_CONVERTER converter(m_bStoreIsUtf8); + size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen); + if (uLen == (size_t)(-1)) { + return SI_FAIL; + } + + // allocate memory for the data, ensure that there is a NULL + // terminator wherever the converted data ends + SI_CHAR * pData = new(std::nothrow) SI_CHAR[uLen+1]; + if (!pData) { + return SI_NOMEM; + } + memset(pData, 0, sizeof(SI_CHAR)*(uLen+1)); + + // convert the data + if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) { + delete[] pData; + return SI_FAIL; + } + + // parse it + const static SI_CHAR empty = 0; + SI_CHAR * pWork = pData; + const SI_CHAR * pSection = ∅ + const SI_CHAR * pItem = nullptr; + const SI_CHAR * pVal = nullptr; + const SI_CHAR * pComment = nullptr; + + // We copy the strings if we are loading data into this class when we + // already have stored some. + bool bCopyStrings = (m_pData != nullptr); + + // find a file comment if it exists, this is a comment that starts at the + // beginning of the file and continues until the first blank line. + SI_Error rc = FindFileComment(pWork, bCopyStrings); + if (rc < 0) return rc; + + // add every entry in the file to the data table + while (FindEntry(pWork, pSection, pItem, pVal, pComment)) { + rc = AddEntry(pSection, pItem, pVal, pComment, false, bCopyStrings); + if (rc < 0) return rc; + } + + // store these strings if we didn't copy them + if (bCopyStrings) { + delete[] pData; + } + else { + m_pData = pData; + m_uDataLen = uLen+1; + } + + return SI_OK; +} + +#ifdef SI_SUPPORT_IOSTREAMS +template +SI_Error +CSimpleIniTempl::LoadData( + std::istream & a_istream + ) +{ + std::string strData; + char szBuf[512]; + do { + a_istream.get(szBuf, sizeof(szBuf), '\0'); + strData.append(szBuf); + } + while (a_istream.good()); + return LoadData(strData); +} +#endif // SI_SUPPORT_IOSTREAMS + +template +SI_Error +CSimpleIniTempl::FindFileComment( + SI_CHAR *& a_pData, + bool a_bCopyStrings + ) +{ + // there can only be a single file comment + if (m_pFileComment) { + return SI_OK; + } + + // Load the file comment as multi-line text, this will modify all of + // the newline characters to be single \n chars + if (!LoadMultiLineText(a_pData, m_pFileComment, nullptr, false)) { + return SI_OK; + } + + // copy the string if necessary + if (a_bCopyStrings) { + SI_Error rc = CopyString(m_pFileComment); + if (rc < 0) return rc; + } + + return SI_OK; +} + +template +bool +CSimpleIniTempl::FindEntry( + SI_CHAR *& a_pData, + const SI_CHAR *& a_pSection, + const SI_CHAR *& a_pKey, + const SI_CHAR *& a_pVal, + const SI_CHAR *& a_pComment + ) const +{ + a_pComment = nullptr; + + SI_CHAR * pTrail = nullptr; + while (*a_pData) { + // skip spaces and empty lines + while (*a_pData && IsSpace(*a_pData)) { + ++a_pData; + } + if (!*a_pData) { + break; + } + + // skip processing of comment lines but keep a pointer to + // the start of the comment. + if (IsComment(*a_pData)) { + LoadMultiLineText(a_pData, a_pComment, nullptr, true); + continue; + } + + // process section names + if (*a_pData == '[') { + // skip leading spaces + ++a_pData; + while (*a_pData && IsSpace(*a_pData)) { + ++a_pData; + } + + // find the end of the section name (it may contain spaces) + // and convert it to lowercase as necessary + a_pSection = a_pData; + while (*a_pData && *a_pData != ']' && !IsNewLineChar(*a_pData)) { + ++a_pData; + } + + // if it's an invalid line, just skip it + if (*a_pData != ']') { + continue; + } + + // remove trailing spaces from the section + pTrail = a_pData - 1; + while (pTrail >= a_pSection && IsSpace(*pTrail)) { + --pTrail; + } + ++pTrail; + *pTrail = 0; + + // skip to the end of the line + ++a_pData; // safe as checked that it == ']' above + while (*a_pData && !IsNewLineChar(*a_pData)) { + ++a_pData; + } + + a_pKey = nullptr; + a_pVal = nullptr; + return true; + } + + // find the end of the key name (it may contain spaces) + // and convert it to lowercase as necessary + a_pKey = a_pData; + while (*a_pData && *a_pData != '=' && !IsNewLineChar(*a_pData)) { + ++a_pData; + } + + // if it's an invalid line, just skip it + if (*a_pData != '=') { + continue; + } + + // empty keys are invalid + if (a_pKey == a_pData) { + while (*a_pData && !IsNewLineChar(*a_pData)) { + ++a_pData; + } + continue; + } + + // remove trailing spaces from the key + pTrail = a_pData - 1; + while (pTrail >= a_pKey && IsSpace(*pTrail)) { + --pTrail; + } + ++pTrail; + *pTrail = 0; + + // skip leading whitespace on the value + ++a_pData; // safe as checked that it == '=' above + while (*a_pData && !IsNewLineChar(*a_pData) && IsSpace(*a_pData)) { + ++a_pData; + } + + // find the end of the value which is the end of this line + a_pVal = a_pData; + while (*a_pData && !IsNewLineChar(*a_pData)) { + ++a_pData; + } + + // remove trailing spaces from the value + pTrail = a_pData - 1; + if (*a_pData) { // prepare for the next round + SkipNewLine(a_pData); + } + while (pTrail >= a_pVal && IsSpace(*pTrail)) { + --pTrail; + } + ++pTrail; + *pTrail = 0; + + // check for multi-line entries + if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) { + // skip the "<<<" to get the tag that will end the multiline + const SI_CHAR * pTagName = a_pVal + 3; + return LoadMultiLineText(a_pData, a_pVal, pTagName); + } + + // return the standard entry + return true; + } + + return false; +} + +template +bool +CSimpleIniTempl::IsMultiLineTag( + const SI_CHAR * a_pVal + ) const +{ + // check for the "<<<" prefix for a multi-line entry + if (*a_pVal++ != '<') return false; + if (*a_pVal++ != '<') return false; + if (*a_pVal++ != '<') return false; + return true; +} + +template +bool +CSimpleIniTempl::IsMultiLineData( + const SI_CHAR * a_pData + ) const +{ + // data is multi-line if it has any of the following features: + // * whitespace prefix + // * embedded newlines + // * whitespace suffix + + // empty string + if (!*a_pData) { + return false; + } + + // check for prefix + if (IsSpace(*a_pData)) { + return true; + } + + // embedded newlines + while (*a_pData) { + if (IsNewLineChar(*a_pData)) { + return true; + } + ++a_pData; + } + + // check for suffix + if (IsSpace(*--a_pData)) { + return true; + } + + return false; +} + +template +bool +CSimpleIniTempl::IsNewLineChar( + SI_CHAR a_c + ) const +{ + return (a_c == '\n' || a_c == '\r'); +} + +template +bool +CSimpleIniTempl::LoadMultiLineText( + SI_CHAR *& a_pData, + const SI_CHAR *& a_pVal, + const SI_CHAR * a_pTagName, + bool a_bAllowBlankLinesInComment + ) const +{ + // we modify this data to strip all newlines down to a single '\n' + // character. This means that on Windows we need to strip out some + // characters which will make the data shorter. + // i.e. LINE1-LINE1\r\nLINE2-LINE2\0 will become + // LINE1-LINE1\nLINE2-LINE2\0 + // The pDataLine entry is the pointer to the location in memory that + // the current line needs to start to run following the existing one. + // This may be the same as pCurrLine in which case no move is needed. + SI_CHAR * pDataLine = a_pData; + SI_CHAR * pCurrLine; + + // value starts at the current line + a_pVal = a_pData; + + // find the end tag. This tag must start in column 1 and be + // followed by a newline. We ignore any whitespace after the end + // tag but not whitespace before it. + SI_CHAR cEndOfLineChar = *a_pData; + for(;;) { + // if we are loading comments then we need a comment character as + // the first character on every line + if (!a_pTagName && !IsComment(*a_pData)) { + // if we aren't allowing blank lines then we're done + if (!a_bAllowBlankLinesInComment) { + break; + } + + // if we are allowing blank lines then we only include them + // in this comment if another comment follows, so read ahead + // to find out. + SI_CHAR * pCurr = a_pData; + int nNewLines = 0; + while (IsSpace(*pCurr)) { + if (IsNewLineChar(*pCurr)) { + ++nNewLines; + SkipNewLine(pCurr); + } + else { + ++pCurr; + } + } + + // we have a comment, add the blank lines to the output + // and continue processing from here + if (IsComment(*pCurr)) { + for (; nNewLines > 0; --nNewLines) *pDataLine++ = '\n'; + a_pData = pCurr; + continue; + } + + // the comment ends here + break; + } + + // find the end of this line + pCurrLine = a_pData; + while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData; + + // move this line down to the location that it should be if necessary + if (pDataLine < pCurrLine) { + size_t nLen = (size_t) (a_pData - pCurrLine); + memmove(pDataLine, pCurrLine, nLen * sizeof(SI_CHAR)); + pDataLine[nLen] = '\0'; + } + + // end the line with a NULL + cEndOfLineChar = *a_pData; + *a_pData = 0; + + // if are looking for a tag then do the check now. This is done before + // checking for end of the data, so that if we have the tag at the end + // of the data then the tag is removed correctly. + if (a_pTagName) { + // strip whitespace from the end of this tag + SI_CHAR* pc = a_pData - 1; + while (pc > pDataLine && IsSpace(*pc)) --pc; + SI_CHAR ch = *++pc; + *pc = 0; + + if (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine)) { + break; + } + + *pc = ch; + } + + // if we are at the end of the data then we just automatically end + // this entry and return the current data. + if (!cEndOfLineChar) { + return true; + } + + // otherwise we need to process this newline to ensure that it consists + // of just a single \n character. + pDataLine += (a_pData - pCurrLine); + *a_pData = cEndOfLineChar; + SkipNewLine(a_pData); + *pDataLine++ = '\n'; + } + + // if we didn't find a comment at all then return false + if (a_pVal == a_pData) { + a_pVal = nullptr; + return false; + } + + // the data (which ends at the end of the last line) needs to be + // null-terminated BEFORE before the newline character(s). If the + // user wants a new line in the multi-line data then they need to + // add an empty line before the tag. + *--pDataLine = '\0'; + + // if looking for a tag and if we aren't at the end of the data, + // then move a_pData to the start of the next line. + if (a_pTagName && cEndOfLineChar) { + SI_ASSERT(IsNewLineChar(cEndOfLineChar)); + *a_pData = cEndOfLineChar; + SkipNewLine(a_pData); + } + + return true; +} + +template +SI_Error +CSimpleIniTempl::CopyString( + const SI_CHAR *& a_pString + ) +{ + size_t uLen = 0; + if (sizeof(SI_CHAR) == sizeof(char)) { + uLen = strlen((const char *)a_pString); + } + else if (sizeof(SI_CHAR) == sizeof(wchar_t)) { + uLen = wcslen((const wchar_t *)a_pString); + } + else { + for ( ; a_pString[uLen]; ++uLen) /*loop*/ ; + } + ++uLen; // NULL character + SI_CHAR * pCopy = new(std::nothrow) SI_CHAR[uLen]; + if (!pCopy) { + return SI_NOMEM; + } + memcpy(pCopy, a_pString, sizeof(SI_CHAR)*uLen); + m_strings.push_back(pCopy); + a_pString = pCopy; + return SI_OK; +} + +template +SI_Error +CSimpleIniTempl::AddEntry( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pValue, + const SI_CHAR * a_pComment, + bool a_bForceReplace, + bool a_bCopyStrings + ) +{ + SI_Error rc; + bool bInserted = false; + + SI_ASSERT(!a_pComment || IsComment(*a_pComment)); + + // if we are copying strings then make a copy of the comment now + // because we will need it when we add the entry. + if (a_bCopyStrings && a_pComment) { + rc = CopyString(a_pComment); + if (rc < 0) return rc; + } + + // create the section entry if necessary + typename TSection::iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + // if the section doesn't exist then we need a copy as the + // string needs to last beyond the end of this function + if (a_bCopyStrings) { + rc = CopyString(a_pSection); + if (rc < 0) return rc; + } + + // only set the comment if this is a section only entry + Entry oSection(a_pSection, ++m_nOrder); + if (a_pComment && (!a_pKey || !a_pValue)) { + oSection.pComment = a_pComment; + } + + typename TSection::value_type oEntry(oSection, TKeyVal()); + typedef typename TSection::iterator SectionIterator; + std::pair i = m_data.insert(oEntry); + iSection = i.first; + bInserted = true; + } + if (!a_pKey || !a_pValue) { + // section only entries are specified with pItem and pVal as nullptr + return bInserted ? SI_INSERTED : SI_UPDATED; + } + + // check for existence of the key + TKeyVal & keyval = iSection->second; + typename TKeyVal::iterator iKey = keyval.find(a_pKey); + bInserted = iKey == keyval.end(); + + // remove all existing entries but save the load order and + // comment of the first entry + int nLoadOrder = ++m_nOrder; + if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) { + const SI_CHAR * pComment = nullptr; + while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) { + if (iKey->first.nOrder < nLoadOrder) { + nLoadOrder = iKey->first.nOrder; + pComment = iKey->first.pComment; + } + ++iKey; + } + if (pComment) { + DeleteString(a_pComment); + a_pComment = pComment; + CopyString(a_pComment); + } + Delete(a_pSection, a_pKey); + iKey = keyval.end(); + } + + // make string copies if necessary + bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace; + if (a_bCopyStrings) { + if (bForceCreateNewKey || iKey == keyval.end()) { + // if the key doesn't exist then we need a copy as the + // string needs to last beyond the end of this function + // because we will be inserting the key next + rc = CopyString(a_pKey); + if (rc < 0) return rc; + } + + // we always need a copy of the value + rc = CopyString(a_pValue); + if (rc < 0) return rc; + } + + // create the key entry + if (iKey == keyval.end() || bForceCreateNewKey) { + Entry oKey(a_pKey, nLoadOrder); + if (a_pComment) { + oKey.pComment = a_pComment; + } + typename TKeyVal::value_type oEntry(oKey, static_cast(nullptr)); + iKey = keyval.insert(oEntry); + } + + iKey->second = a_pValue; + return bInserted ? SI_INSERTED : SI_UPDATED; +} + +template +const SI_CHAR * +CSimpleIniTempl::GetValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pDefault, + bool * a_pHasMultiple + ) const +{ + if (a_pHasMultiple) { + *a_pHasMultiple = false; + } + if (!a_pSection || !a_pKey) { + return a_pDefault; + } + typename TSection::const_iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + return a_pDefault; + } + typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey); + if (iKeyVal == iSection->second.end()) { + return a_pDefault; + } + + // check for multiple entries with the same key + if (m_bAllowMultiKey && a_pHasMultiple) { + typename TKeyVal::const_iterator iTemp = iKeyVal; + if (++iTemp != iSection->second.end()) { + if (!IsLess(a_pKey, iTemp->first.pItem)) { + *a_pHasMultiple = true; + } + } + } + + return iKeyVal->second; +} + +template +long +CSimpleIniTempl::GetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nDefault, + bool * a_pHasMultiple + ) const +{ + // return the default if we don't have a value + const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, nullptr, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_nDefault; + + // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII + char szValue[64] = { 0 }; + SI_CONVERTER c(m_bStoreIsUtf8); + if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { + return a_nDefault; + } + + // handle the value as hex if prefaced with "0x" + long nValue = a_nDefault; + char * pszSuffix = szValue; + if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) { + if (!szValue[2]) return a_nDefault; + nValue = strtol(&szValue[2], &pszSuffix, 16); + } + else { + nValue = strtol(szValue, &pszSuffix, 10); + } + + // any invalid strings will return the default value + if (*pszSuffix) { + return a_nDefault; + } + + return nValue; +} + +template +SI_Error +CSimpleIniTempl::SetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nValue, + const SI_CHAR * a_pComment, + bool a_bUseHex, + bool a_bForceReplace + ) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_FAIL; + + // convert to an ASCII string + char szInput[64]; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + sprintf_s(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue); +#else // !__STDC_WANT_SECURE_LIB__ + sprintf(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue); +#endif // __STDC_WANT_SECURE_LIB__ + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(szInput, strlen(szInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); +} + +template +double +CSimpleIniTempl::GetDoubleValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + double a_nDefault, + bool * a_pHasMultiple + ) const +{ + // return the default if we don't have a value + const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, nullptr, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_nDefault; + + // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII + char szValue[64] = { 0 }; + SI_CONVERTER c(m_bStoreIsUtf8); + if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { + return a_nDefault; + } + + char * pszSuffix = nullptr; + double nValue = strtod(szValue, &pszSuffix); + + // any invalid strings will return the default value + if (!pszSuffix || *pszSuffix) { + return a_nDefault; + } + + return nValue; +} + +template +SI_Error +CSimpleIniTempl::SetDoubleValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + double a_nValue, + const SI_CHAR * a_pComment, + bool a_bForceReplace + ) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_FAIL; + + // convert to an ASCII string + char szInput[64]; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + sprintf_s(szInput, "%f", a_nValue); +#else // !__STDC_WANT_SECURE_LIB__ + sprintf(szInput, "%f", a_nValue); +#endif // __STDC_WANT_SECURE_LIB__ + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(szInput, strlen(szInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); +} + +template +bool +CSimpleIniTempl::GetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bDefault, + bool * a_pHasMultiple + ) const +{ + // return the default if we don't have a value + const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, nullptr, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_bDefault; + + // we only look at the minimum number of characters + switch (pszValue[0]) { + case 't': case 'T': // true + case 'y': case 'Y': // yes + case '1': // 1 (one) + return true; + + case 'f': case 'F': // false + case 'n': case 'N': // no + case '0': // 0 (zero) + return false; + + case 'o': case 'O': + if (pszValue[1] == 'n' || pszValue[1] == 'N') return true; // on + if (pszValue[1] == 'f' || pszValue[1] == 'F') return false; // off + break; + } + + // no recognized value, return the default + return a_bDefault; +} + +template +SI_Error +CSimpleIniTempl::SetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bValue, + const SI_CHAR * a_pComment, + bool a_bForceReplace + ) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_FAIL; + + // convert to an ASCII string + const char * pszInput = a_bValue ? "true" : "false"; + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(pszInput, strlen(pszInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); +} + +template +bool +CSimpleIniTempl::GetAllValues( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + TNamesDepend & a_values + ) const +{ + a_values.clear(); + + if (!a_pSection || !a_pKey) { + return false; + } + typename TSection::const_iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + return false; + } + typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey); + if (iKeyVal == iSection->second.end()) { + return false; + } + + // insert all values for this key + a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder)); + if (m_bAllowMultiKey) { + ++iKeyVal; + while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) { + a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder)); + ++iKeyVal; + } + } + + return true; +} + +template +int +CSimpleIniTempl::GetSectionSize( + const SI_CHAR * a_pSection + ) const +{ + if (!a_pSection) { + return -1; + } + + typename TSection::const_iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + return -1; + } + const TKeyVal & section = iSection->second; + + // if multi-key isn't permitted then the section size is + // the number of keys that we have. + if (!m_bAllowMultiKey || section.empty()) { + return (int) section.size(); + } + + // otherwise we need to count them + int nCount = 0; + const SI_CHAR * pLastKey = nullptr; + typename TKeyVal::const_iterator iKeyVal = section.begin(); + for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) { + if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) { + ++nCount; + pLastKey = iKeyVal->first.pItem; + } + } + return nCount; +} + +template +const typename CSimpleIniTempl::TKeyVal * +CSimpleIniTempl::GetSection( + const SI_CHAR * a_pSection + ) const +{ + if (a_pSection) { + typename TSection::const_iterator i = m_data.find(a_pSection); + if (i != m_data.end()) { + return &(i->second); + } + } + return 0; +} + +template +void +CSimpleIniTempl::GetAllSections( + TNamesDepend & a_names + ) const +{ + a_names.clear(); + typename TSection::const_iterator i = m_data.begin(); + for (int n = 0; i != m_data.end(); ++i, ++n ) { + a_names.push_back(i->first); + } +} + +template +bool +CSimpleIniTempl::GetAllKeys( + const SI_CHAR * a_pSection, + TNamesDepend & a_names + ) const +{ + a_names.clear(); + + if (!a_pSection) { + return false; + } + + typename TSection::const_iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + return false; + } + + const TKeyVal & section = iSection->second; + const SI_CHAR * pLastKey = nullptr; + typename TKeyVal::const_iterator iKeyVal = section.begin(); + for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n ) { + if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) { + a_names.push_back(iKeyVal->first); + pLastKey = iKeyVal->first.pItem; + } + } + + return true; +} + +template +SI_Error +CSimpleIniTempl::SaveFile( + const char * a_pszFile, + bool a_bAddSignature + ) const +{ + FILE * fp = nullptr; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + fopen_s(&fp, a_pszFile, "wb"); +#else // !__STDC_WANT_SECURE_LIB__ + fp = fopen(a_pszFile, "wb"); +#endif // __STDC_WANT_SECURE_LIB__ + if (!fp) return SI_FILE; + SI_Error rc = SaveFile(fp, a_bAddSignature); + fclose(fp); + return rc; +} + +#ifdef SI_HAS_WIDE_FILE +template +SI_Error +CSimpleIniTempl::SaveFile( + const SI_WCHAR_T * a_pwszFile, + bool a_bAddSignature + ) const +{ +#ifdef _WIN32 + FILE * fp = nullptr; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + _wfopen_s(&fp, a_pwszFile, L"wb"); +#else // !__STDC_WANT_SECURE_LIB__ + fp = _wfopen(a_pwszFile, L"wb"); +#endif // __STDC_WANT_SECURE_LIB__ + if (!fp) return SI_FILE; + SI_Error rc = SaveFile(fp, a_bAddSignature); + fclose(fp); + return rc; +#else // !_WIN32 (therefore SI_CONVERT_ICU) + char szFile[256]; + u_austrncpy(szFile, a_pwszFile, sizeof(szFile)); + return SaveFile(szFile, a_bAddSignature); +#endif // _WIN32 +} +#endif // SI_HAS_WIDE_FILE + +template +SI_Error +CSimpleIniTempl::SaveFile( + FILE * a_pFile, + bool a_bAddSignature + ) const +{ + FileWriter writer(a_pFile); + return Save(writer, a_bAddSignature); +} + +template +SI_Error +CSimpleIniTempl::Save( + OutputWriter & a_oOutput, + bool a_bAddSignature + ) const +{ + Converter convert(m_bStoreIsUtf8); + + // add the UTF-8 signature if it is desired + if (m_bStoreIsUtf8 && a_bAddSignature) { + a_oOutput.Write(SI_UTF8_SIGNATURE); + } + + // get all of the sections sorted in load order + TNamesDepend oSections; + GetAllSections(oSections); +#if defined(_MSC_VER) && _MSC_VER <= 1200 + oSections.sort(); +#elif defined(__BORLANDC__) + oSections.sort(Entry::LoadOrder()); +#else + oSections.sort(typename Entry::LoadOrder()); +#endif + + // if there is an empty section name, then it must be written out first + // regardless of the load order + typename TNamesDepend::iterator is = oSections.begin(); + for (; is != oSections.end(); ++is) { + if (!*is->pItem) { + // move the empty section name to the front of the section list + if (is != oSections.begin()) { + oSections.splice(oSections.begin(), oSections, is, std::next(is)); + } + break; + } + } + + // write the file comment if we have one + bool bNeedNewLine = false; + if (m_pFileComment) { + if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) { + return SI_FAIL; + } + bNeedNewLine = true; + } + + // iterate through our sections and output the data + typename TNamesDepend::const_iterator iSection = oSections.begin(); + for ( ; iSection != oSections.end(); ++iSection ) { + // write out the comment if there is one + if (iSection->pComment) { + if (bNeedNewLine) { + a_oOutput.Write(SI_NEWLINE_A); + a_oOutput.Write(SI_NEWLINE_A); + } + if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) { + return SI_FAIL; + } + bNeedNewLine = false; + } + + if (bNeedNewLine) { + a_oOutput.Write(SI_NEWLINE_A); + a_oOutput.Write(SI_NEWLINE_A); + bNeedNewLine = false; + } + + // write the section (unless there is no section name) + if (*iSection->pItem) { + if (!convert.ConvertToStore(iSection->pItem)) { + return SI_FAIL; + } + a_oOutput.Write("["); + a_oOutput.Write(convert.Data()); + a_oOutput.Write("]"); + a_oOutput.Write(SI_NEWLINE_A); + } + + // get all of the keys sorted in load order + TNamesDepend oKeys; + GetAllKeys(iSection->pItem, oKeys); +#if defined(_MSC_VER) && _MSC_VER <= 1200 + oKeys.sort(); +#elif defined(__BORLANDC__) + oKeys.sort(Entry::LoadOrder()); +#else + oKeys.sort(typename Entry::LoadOrder()); +#endif + + // write all keys and values + typename TNamesDepend::const_iterator iKey = oKeys.begin(); + for ( ; iKey != oKeys.end(); ++iKey) { + // get all values for this key + TNamesDepend oValues; + GetAllValues(iSection->pItem, iKey->pItem, oValues); + + typename TNamesDepend::const_iterator iValue = oValues.begin(); + for ( ; iValue != oValues.end(); ++iValue) { + // write out the comment if there is one + if (iValue->pComment) { + a_oOutput.Write(SI_NEWLINE_A); + if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) { + return SI_FAIL; + } + } + + // write the key + if (!convert.ConvertToStore(iKey->pItem)) { + return SI_FAIL; + } + a_oOutput.Write(convert.Data()); + + // write the value + if (!convert.ConvertToStore(iValue->pItem)) { + return SI_FAIL; + } + a_oOutput.Write(m_bSpaces ? " = " : "="); + if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) { + // multi-line data needs to be processed specially to ensure + // that we use the correct newline format for the current system + a_oOutput.Write("<<pItem)) { + return SI_FAIL; + } + a_oOutput.Write("END_OF_TEXT"); + } + else { + a_oOutput.Write(convert.Data()); + } + a_oOutput.Write(SI_NEWLINE_A); + } + } + + bNeedNewLine = true; + } + + return SI_OK; +} + +template +bool +CSimpleIniTempl::OutputMultiLineText( + OutputWriter & a_oOutput, + Converter & a_oConverter, + const SI_CHAR * a_pText + ) const +{ + const SI_CHAR * pEndOfLine; + SI_CHAR cEndOfLineChar = *a_pText; + while (cEndOfLineChar) { + // find the end of this line + pEndOfLine = a_pText; + for (; *pEndOfLine && *pEndOfLine != '\n'; ++pEndOfLine) /*loop*/ ; + cEndOfLineChar = *pEndOfLine; + + // temporarily null terminate, convert and output the line + *const_cast(pEndOfLine) = 0; + if (!a_oConverter.ConvertToStore(a_pText)) { + return false; + } + *const_cast(pEndOfLine) = cEndOfLineChar; + a_pText += (pEndOfLine - a_pText) + 1; + a_oOutput.Write(a_oConverter.Data()); + a_oOutput.Write(SI_NEWLINE_A); + } + return true; +} + +template +bool +CSimpleIniTempl::Delete( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bRemoveEmpty + ) +{ + return DeleteValue(a_pSection, a_pKey, nullptr, a_bRemoveEmpty); +} + +template +bool +CSimpleIniTempl::DeleteValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + const SI_CHAR * a_pValue, + bool a_bRemoveEmpty + ) +{ + if (!a_pSection) { + return false; + } + + typename TSection::iterator iSection = m_data.find(a_pSection); + if (iSection == m_data.end()) { + return false; + } + + // remove a single key if we have a keyname + if (a_pKey) { + typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey); + if (iKeyVal == iSection->second.end()) { + return false; + } + + const static SI_STRLESS isLess = SI_STRLESS(); + + // remove any copied strings and then the key + typename TKeyVal::iterator iDelete; + bool bDeleted = false; + do { + iDelete = iKeyVal++; + + if(a_pValue == nullptr || + (isLess(a_pValue, iDelete->second) == false && + isLess(iDelete->second, a_pValue) == false)) { + DeleteString(iDelete->first.pItem); + DeleteString(iDelete->second); + iSection->second.erase(iDelete); + bDeleted = true; + } + } + while (iKeyVal != iSection->second.end() + && !IsLess(a_pKey, iKeyVal->first.pItem)); + + if(!bDeleted) { + return false; + } + + // done now if the section is not empty or we are not pruning away + // the empty sections. Otherwise let it fall through into the section + // deletion code + if (!a_bRemoveEmpty || !iSection->second.empty()) { + return true; + } + } + else { + // delete all copied strings from this section. The actual + // entries will be removed when the section is removed. + typename TKeyVal::iterator iKeyVal = iSection->second.begin(); + for ( ; iKeyVal != iSection->second.end(); ++iKeyVal) { + DeleteString(iKeyVal->first.pItem); + DeleteString(iKeyVal->second); + } + } + + // delete the section itself + DeleteString(iSection->first.pItem); + m_data.erase(iSection); + + return true; +} + +template +void +CSimpleIniTempl::DeleteString( + const SI_CHAR * a_pString + ) +{ + // strings may exist either inside the data block, or they will be + // individually allocated and stored in m_strings. We only physically + // delete those stored in m_strings. + if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) { + typename TNamesDepend::iterator i = m_strings.begin(); + for (;i != m_strings.end(); ++i) { + if (a_pString == i->pItem) { + delete[] const_cast(i->pItem); + m_strings.erase(i); + break; + } + } + } +} + +// --------------------------------------------------------------------------- +// CONVERSION FUNCTIONS +// --------------------------------------------------------------------------- + +// Defines the conversion classes for different libraries. Before including +// SimpleIni.h, set the converter that you wish you use by defining one of the +// following symbols. +// +// SI_NO_CONVERSION Do not make the "W" wide character version of the +// library available. Only CSimpleIniA etc is defined. +// SI_CONVERT_GENERIC Use the Unicode reference conversion library in +// the accompanying files ConvertUTF.h/c +// SI_CONVERT_ICU Use the IBM ICU conversion library. Requires +// ICU headers on include path and icuuc.lib +// SI_CONVERT_WIN32 Use the Win32 API functions for conversion. + +#if !defined(SI_NO_CONVERSION) && !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU) +# ifdef _WIN32 +# define SI_CONVERT_WIN32 +# else +# define SI_CONVERT_GENERIC +# endif +#endif + +/** + * Generic case-sensitive less than comparison. This class returns numerically + * ordered ASCII case-sensitive text for all possible sizes and types of + * SI_CHAR. + */ +template +struct SI_GenericCase { + bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { + long cmp; + for ( ;*pLeft && *pRight; ++pLeft, ++pRight) { + cmp = (long) *pLeft - (long) *pRight; + if (cmp != 0) { + return cmp < 0; + } + } + return *pRight != 0; + } +}; + +/** + * Generic ASCII case-insensitive less than comparison. This class returns + * numerically ordered ASCII case-insensitive text for all possible sizes + * and types of SI_CHAR. It is not safe for MBCS text comparison where + * ASCII A-Z characters are used in the encoding of multi-byte characters. + */ +template +struct SI_GenericNoCase { + inline SI_CHAR locase(SI_CHAR ch) const { + return (ch < 'A' || ch > 'Z') ? ch : (ch - 'A' + 'a'); + } + bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { + long cmp; + for ( ;*pLeft && *pRight; ++pLeft, ++pRight) { + cmp = (long) locase(*pLeft) - (long) locase(*pRight); + if (cmp != 0) { + return cmp < 0; + } + } + return *pRight != 0; + } +}; + +/** + * Null conversion class for MBCS/UTF-8 to char (or equivalent). + */ +template +class SI_ConvertA { + bool m_bStoreIsUtf8; +protected: + SI_ConvertA() { } +public: + SI_ConvertA(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { } + + /* copy and assignment */ + SI_ConvertA(const SI_ConvertA & rhs) { operator=(rhs); } + SI_ConvertA & operator=(const SI_ConvertA & rhs) { + m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8; + return *this; + } + + /** Calculate the number of SI_CHAR required for converting the input + * from the storage format. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @return Number of SI_CHAR required by the string when + * converted. If there are embedded NULL bytes in the + * input data, only the string up and not including + * the NULL byte will be converted. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeFromStore( + const char * a_pInputData, + size_t a_uInputDataLen) + { + (void)a_pInputData; + SI_ASSERT(a_uInputDataLen != (size_t) -1); + + // ASCII/MBCS/UTF-8 needs no conversion + return a_uInputDataLen; + } + + /** Convert the input string from the storage format to SI_CHAR. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @param a_pOutputData Pointer to the output buffer to received the + * converted data. + * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. + * @return true if all of the input data was successfully + * converted. + */ + bool ConvertFromStore( + const char * a_pInputData, + size_t a_uInputDataLen, + SI_CHAR * a_pOutputData, + size_t a_uOutputDataSize) + { + // ASCII/MBCS/UTF-8 needs no conversion + if (a_uInputDataLen > a_uOutputDataSize) { + return false; + } + memcpy(a_pOutputData, a_pInputData, a_uInputDataLen); + return true; + } + + /** Calculate the number of char required by the storage format of this + * data. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated string to calculate the number of + * bytes required to be converted to storage format. + * @return Number of bytes required by the string when + * converted to storage format. This size always + * includes space for the terminating NULL character. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeToStore( + const SI_CHAR * a_pInputData) + { + // ASCII/MBCS/UTF-8 needs no conversion + return strlen((const char *)a_pInputData) + 1; + } + + /** Convert the input string to the storage format of this data. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated source string to convert. All of + * the data will be converted including the + * terminating NULL character. + * @param a_pOutputData Pointer to the buffer to receive the converted + * string. + * @param a_uOutputDataSize Size of the output buffer in char. + * @return true if all of the input data, including the + * terminating NULL character was successfully + * converted. + */ + bool ConvertToStore( + const SI_CHAR * a_pInputData, + char * a_pOutputData, + size_t a_uOutputDataSize) + { + // calc input string length (SI_CHAR type and size independent) + size_t uInputLen = strlen((const char *)a_pInputData) + 1; + if (uInputLen > a_uOutputDataSize) { + return false; + } + + // ascii/UTF-8 needs no conversion + memcpy(a_pOutputData, a_pInputData, uInputLen); + return true; + } +}; + + +// --------------------------------------------------------------------------- +// SI_CONVERT_GENERIC +// --------------------------------------------------------------------------- +#ifdef SI_CONVERT_GENERIC + +#define SI_Case SI_GenericCase +#define SI_NoCase SI_GenericNoCase + +#include +#include "ConvertUTF.h" + +/** + * Converts UTF-8 to a wchar_t (or equivalent) using the Unicode reference + * library functions. This can be used on all platforms. + */ +template +class SI_ConvertW { + bool m_bStoreIsUtf8; +protected: + SI_ConvertW() { } +public: + SI_ConvertW(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { } + + /* copy and assignment */ + SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } + SI_ConvertW & operator=(const SI_ConvertW & rhs) { + m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8; + return *this; + } + + /** Calculate the number of SI_CHAR required for converting the input + * from the storage format. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @return Number of SI_CHAR required by the string when + * converted. If there are embedded NULL bytes in the + * input data, only the string up and not including + * the NULL byte will be converted. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeFromStore( + const char * a_pInputData, + size_t a_uInputDataLen) + { + SI_ASSERT(a_uInputDataLen != (size_t) -1); + + if (m_bStoreIsUtf8) { + // worst case scenario for UTF-8 to wchar_t is 1 char -> 1 wchar_t + // so we just return the same number of characters required as for + // the source text. + return a_uInputDataLen; + } + +#if defined(SI_NO_MBSTOWCS_NULL) || (!defined(_MSC_VER) && !defined(_linux)) + // fall back processing for platforms that don't support a NULL dest to mbstowcs + // worst case scenario is 1:1, this will be a sufficient buffer size + (void)a_pInputData; + return a_uInputDataLen; +#else + // get the actual required buffer size + return mbstowcs(nullptr, a_pInputData, a_uInputDataLen); +#endif + } + + /** Convert the input string from the storage format to SI_CHAR. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @param a_pOutputData Pointer to the output buffer to received the + * converted data. + * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. + * @return true if all of the input data was successfully + * converted. + */ + bool ConvertFromStore( + const char * a_pInputData, + size_t a_uInputDataLen, + SI_CHAR * a_pOutputData, + size_t a_uOutputDataSize) + { + if (m_bStoreIsUtf8) { + // This uses the Unicode reference implementation to do the + // conversion from UTF-8 to wchar_t. The required files are + // ConvertUTF.h and ConvertUTF.c which should be included in + // the distribution but are publically available from unicode.org + // at http://www.unicode.org/Public/PROGRAMS/CVTUTF/ + ConversionResult retval; + const UTF8 * pUtf8 = (const UTF8 *) a_pInputData; + if (sizeof(wchar_t) == sizeof(UTF32)) { + UTF32 * pUtf32 = (UTF32 *) a_pOutputData; + retval = ConvertUTF8toUTF32( + &pUtf8, pUtf8 + a_uInputDataLen, + &pUtf32, pUtf32 + a_uOutputDataSize, + lenientConversion); + } + else if (sizeof(wchar_t) == sizeof(UTF16)) { + UTF16 * pUtf16 = (UTF16 *) a_pOutputData; + retval = ConvertUTF8toUTF16( + &pUtf8, pUtf8 + a_uInputDataLen, + &pUtf16, pUtf16 + a_uOutputDataSize, + lenientConversion); + } + return retval == conversionOK; + } + + // convert to wchar_t + size_t retval = mbstowcs(a_pOutputData, + a_pInputData, a_uOutputDataSize); + return retval != (size_t)(-1); + } + + /** Calculate the number of char required by the storage format of this + * data. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated string to calculate the number of + * bytes required to be converted to storage format. + * @return Number of bytes required by the string when + * converted to storage format. This size always + * includes space for the terminating NULL character. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeToStore( + const SI_CHAR * a_pInputData) + { + if (m_bStoreIsUtf8) { + // worst case scenario for wchar_t to UTF-8 is 1 wchar_t -> 6 char + size_t uLen = 0; + while (a_pInputData[uLen]) { + ++uLen; + } + return (6 * uLen) + 1; + } + else { + size_t uLen = wcstombs(nullptr, a_pInputData, 0); + if (uLen == (size_t)(-1)) { + return uLen; + } + return uLen + 1; // include NULL terminator + } + } + + /** Convert the input string to the storage format of this data. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated source string to convert. All of + * the data will be converted including the + * terminating NULL character. + * @param a_pOutputData Pointer to the buffer to receive the converted + * string. + * @param a_uOutputDataSize Size of the output buffer in char. + * @return true if all of the input data, including the + * terminating NULL character was successfully + * converted. + */ + bool ConvertToStore( + const SI_CHAR * a_pInputData, + char * a_pOutputData, + size_t a_uOutputDataSize + ) + { + if (m_bStoreIsUtf8) { + // calc input string length (SI_CHAR type and size independent) + size_t uInputLen = 0; + while (a_pInputData[uInputLen]) { + ++uInputLen; + } + ++uInputLen; // include the NULL char + + // This uses the Unicode reference implementation to do the + // conversion from wchar_t to UTF-8. The required files are + // ConvertUTF.h and ConvertUTF.c which should be included in + // the distribution but are publically available from unicode.org + // at http://www.unicode.org/Public/PROGRAMS/CVTUTF/ + ConversionResult retval; + UTF8 * pUtf8 = (UTF8 *) a_pOutputData; + if (sizeof(wchar_t) == sizeof(UTF32)) { + const UTF32 * pUtf32 = (const UTF32 *) a_pInputData; + retval = ConvertUTF32toUTF8( + &pUtf32, pUtf32 + uInputLen, + &pUtf8, pUtf8 + a_uOutputDataSize, + lenientConversion); + } + else if (sizeof(wchar_t) == sizeof(UTF16)) { + const UTF16 * pUtf16 = (const UTF16 *) a_pInputData; + retval = ConvertUTF16toUTF8( + &pUtf16, pUtf16 + uInputLen, + &pUtf8, pUtf8 + a_uOutputDataSize, + lenientConversion); + } + return retval == conversionOK; + } + else { + size_t retval = wcstombs(a_pOutputData, + a_pInputData, a_uOutputDataSize); + return retval != (size_t) -1; + } + } +}; + +#endif // SI_CONVERT_GENERIC + + +// --------------------------------------------------------------------------- +// SI_CONVERT_ICU +// --------------------------------------------------------------------------- +#ifdef SI_CONVERT_ICU + +#define SI_Case SI_GenericCase +#define SI_NoCase SI_GenericNoCase + +#include + +/** + * Converts MBCS/UTF-8 to UChar using ICU. This can be used on all platforms. + */ +template +class SI_ConvertW { + const char * m_pEncoding; + UConverter * m_pConverter; +protected: + SI_ConvertW() : m_pEncoding(nullptr), m_pConverter(nullptr) { } +public: + SI_ConvertW(bool a_bStoreIsUtf8) : m_pConverter(nullptr) { + m_pEncoding = a_bStoreIsUtf8 ? "UTF-8" : nullptr; + } + + /* copy and assignment */ + SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } + SI_ConvertW & operator=(const SI_ConvertW & rhs) { + m_pEncoding = rhs.m_pEncoding; + m_pConverter = nullptr; + return *this; + } + ~SI_ConvertW() { if (m_pConverter) ucnv_close(m_pConverter); } + + /** Calculate the number of UChar required for converting the input + * from the storage format. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to UChar. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @return Number of UChar required by the string when + * converted. If there are embedded NULL bytes in the + * input data, only the string up and not including + * the NULL byte will be converted. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeFromStore( + const char * a_pInputData, + size_t a_uInputDataLen) + { + SI_ASSERT(a_uInputDataLen != (size_t) -1); + + UErrorCode nError; + + if (!m_pConverter) { + nError = U_ZERO_ERROR; + m_pConverter = ucnv_open(m_pEncoding, &nError); + if (U_FAILURE(nError)) { + return (size_t) -1; + } + } + + nError = U_ZERO_ERROR; + int32_t nLen = ucnv_toUChars(m_pConverter, nullptr, 0, + a_pInputData, (int32_t) a_uInputDataLen, &nError); + if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) { + return (size_t) -1; + } + + return (size_t) nLen; + } + + /** Convert the input string from the storage format to UChar. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to UChar. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @param a_pOutputData Pointer to the output buffer to received the + * converted data. + * @param a_uOutputDataSize Size of the output buffer in UChar. + * @return true if all of the input data was successfully + * converted. + */ + bool ConvertFromStore( + const char * a_pInputData, + size_t a_uInputDataLen, + UChar * a_pOutputData, + size_t a_uOutputDataSize) + { + UErrorCode nError; + + if (!m_pConverter) { + nError = U_ZERO_ERROR; + m_pConverter = ucnv_open(m_pEncoding, &nError); + if (U_FAILURE(nError)) { + return false; + } + } + + nError = U_ZERO_ERROR; + ucnv_toUChars(m_pConverter, + a_pOutputData, (int32_t) a_uOutputDataSize, + a_pInputData, (int32_t) a_uInputDataLen, &nError); + if (U_FAILURE(nError)) { + return false; + } + + return true; + } + + /** Calculate the number of char required by the storage format of this + * data. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated string to calculate the number of + * bytes required to be converted to storage format. + * @return Number of bytes required by the string when + * converted to storage format. This size always + * includes space for the terminating NULL character. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeToStore( + const UChar * a_pInputData) + { + UErrorCode nError; + + if (!m_pConverter) { + nError = U_ZERO_ERROR; + m_pConverter = ucnv_open(m_pEncoding, &nError); + if (U_FAILURE(nError)) { + return (size_t) -1; + } + } + + nError = U_ZERO_ERROR; + int32_t nLen = ucnv_fromUChars(m_pConverter, nullptr, 0, + a_pInputData, -1, &nError); + if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) { + return (size_t) -1; + } + + return (size_t) nLen + 1; + } + + /** Convert the input string to the storage format of this data. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated source string to convert. All of + * the data will be converted including the + * terminating NULL character. + * @param a_pOutputData Pointer to the buffer to receive the converted + * string. + * @param a_pOutputDataSize Size of the output buffer in char. + * @return true if all of the input data, including the + * terminating NULL character was successfully + * converted. + */ + bool ConvertToStore( + const UChar * a_pInputData, + char * a_pOutputData, + size_t a_uOutputDataSize) + { + UErrorCode nError; + + if (!m_pConverter) { + nError = U_ZERO_ERROR; + m_pConverter = ucnv_open(m_pEncoding, &nError); + if (U_FAILURE(nError)) { + return false; + } + } + + nError = U_ZERO_ERROR; + ucnv_fromUChars(m_pConverter, + a_pOutputData, (int32_t) a_uOutputDataSize, + a_pInputData, -1, &nError); + if (U_FAILURE(nError)) { + return false; + } + + return true; + } +}; + +#endif // SI_CONVERT_ICU + + +// --------------------------------------------------------------------------- +// SI_CONVERT_WIN32 +// --------------------------------------------------------------------------- +#ifdef SI_CONVERT_WIN32 + +#define SI_Case SI_GenericCase + +// Windows CE doesn't have errno or MBCS libraries +#ifdef _WIN32_WCE +# ifndef SI_NO_MBCS +# define SI_NO_MBCS +# endif +#endif + +#include +#ifdef SI_NO_MBCS +# define SI_NoCase SI_GenericNoCase +#else // !SI_NO_MBCS +/** + * Case-insensitive comparison class using Win32 MBCS functions. This class + * returns a case-insensitive semi-collation order for MBCS text. It may not + * be safe for UTF-8 text returned in char format as we don't know what + * characters will be folded by the function! Therefore, if you are using + * SI_CHAR == char and SetUnicode(true), then you need to use the generic + * SI_NoCase class instead. + */ +#include +template +struct SI_NoCase { + bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { + if (sizeof(SI_CHAR) == sizeof(char)) { + return _mbsicmp((const unsigned char *)pLeft, + (const unsigned char *)pRight) < 0; + } + if (sizeof(SI_CHAR) == sizeof(wchar_t)) { + return _wcsicmp((const wchar_t *)pLeft, + (const wchar_t *)pRight) < 0; + } + return SI_GenericNoCase()(pLeft, pRight); + } +}; +#endif // SI_NO_MBCS + +/** + * Converts MBCS and UTF-8 to a wchar_t (or equivalent) on Windows. This uses + * only the Win32 functions and doesn't require the external Unicode UTF-8 + * conversion library. It will not work on Windows 95 without using Microsoft + * Layer for Unicode in your application. + */ +template +class SI_ConvertW { + UINT m_uCodePage; +protected: + SI_ConvertW() { } +public: + SI_ConvertW(bool a_bStoreIsUtf8) { + m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP; + } + + /* copy and assignment */ + SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } + SI_ConvertW & operator=(const SI_ConvertW & rhs) { + m_uCodePage = rhs.m_uCodePage; + return *this; + } + + /** Calculate the number of SI_CHAR required for converting the input + * from the storage format. The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @return Number of SI_CHAR required by the string when + * converted. If there are embedded NULL bytes in the + * input data, only the string up and not including + * the NULL byte will be converted. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeFromStore( + const char * a_pInputData, + size_t a_uInputDataLen) + { + SI_ASSERT(a_uInputDataLen != (size_t) -1); + + int retval = MultiByteToWideChar( + m_uCodePage, 0, + a_pInputData, (int) a_uInputDataLen, + 0, 0); + return (size_t)(retval > 0 ? retval : -1); + } + + /** Convert the input string from the storage format to SI_CHAR. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData Data in storage format to be converted to SI_CHAR. + * @param a_uInputDataLen Length of storage format data in bytes. This + * must be the actual length of the data, including + * NULL byte if NULL terminated string is required. + * @param a_pOutputData Pointer to the output buffer to received the + * converted data. + * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. + * @return true if all of the input data was successfully + * converted. + */ + bool ConvertFromStore( + const char * a_pInputData, + size_t a_uInputDataLen, + SI_CHAR * a_pOutputData, + size_t a_uOutputDataSize) + { + int nSize = MultiByteToWideChar( + m_uCodePage, 0, + a_pInputData, (int) a_uInputDataLen, + (wchar_t *) a_pOutputData, (int) a_uOutputDataSize); + return (nSize > 0); + } + + /** Calculate the number of char required by the storage format of this + * data. The storage format is always UTF-8. + * + * @param a_pInputData NULL terminated string to calculate the number of + * bytes required to be converted to storage format. + * @return Number of bytes required by the string when + * converted to storage format. This size always + * includes space for the terminating NULL character. + * @return -1 cast to size_t on a conversion error. + */ + size_t SizeToStore( + const SI_CHAR * a_pInputData) + { + int retval = WideCharToMultiByte( + m_uCodePage, 0, + (const wchar_t *) a_pInputData, -1, + 0, 0, 0, 0); + return (size_t) (retval > 0 ? retval : -1); + } + + /** Convert the input string to the storage format of this data. + * The storage format is always UTF-8 or MBCS. + * + * @param a_pInputData NULL terminated source string to convert. All of + * the data will be converted including the + * terminating NULL character. + * @param a_pOutputData Pointer to the buffer to receive the converted + * string. + * @param a_pOutputDataSize Size of the output buffer in char. + * @return true if all of the input data, including the + * terminating NULL character was successfully + * converted. + */ + bool ConvertToStore( + const SI_CHAR * a_pInputData, + char * a_pOutputData, + size_t a_uOutputDataSize) + { + int retval = WideCharToMultiByte( + m_uCodePage, 0, + (const wchar_t *) a_pInputData, -1, + a_pOutputData, (int) a_uOutputDataSize, 0, 0); + return retval > 0; + } +}; + +#endif // SI_CONVERT_WIN32 + + +// --------------------------------------------------------------------------- +// TYPE DEFINITIONS +// --------------------------------------------------------------------------- + +typedef CSimpleIniTempl,SI_ConvertA > CSimpleIniA; +typedef CSimpleIniTempl,SI_ConvertA > CSimpleIniCaseA; + +#if defined(SI_NO_CONVERSION) +// if there is no wide char conversion then we don't need to define the +// widechar "W" versions of CSimpleIni +# define CSimpleIni CSimpleIniA +# define CSimpleIniCase CSimpleIniCaseA +# define SI_NEWLINE SI_NEWLINE_A +#else +# if defined(SI_CONVERT_ICU) +typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniW; +typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniCaseW; +# else +typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniW; +typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniCaseW; +# endif + +# ifdef _UNICODE +# define CSimpleIni CSimpleIniW +# define CSimpleIniCase CSimpleIniCaseW +# define SI_NEWLINE SI_NEWLINE_W +# else // !_UNICODE +# define CSimpleIni CSimpleIniA +# define CSimpleIniCase CSimpleIniCaseA +# define SI_NEWLINE SI_NEWLINE_A +# endif // _UNICODE +#endif + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif // INCLUDED_SimpleIni_h + diff --git a/admin/win/tools/NCToolsShared/CMakeLists.txt b/admin/win/tools/NCToolsShared/CMakeLists.txt new file mode 100644 index 000000000..f5a323330 --- /dev/null +++ b/admin/win/tools/NCToolsShared/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(NCToolsShared STATIC + utility_win.cpp + SimpleNamedMutex.cpp +) diff --git a/admin/win/tools/NCToolsShared/SimpleNamedMutex.cpp b/admin/win/tools/NCToolsShared/SimpleNamedMutex.cpp new file mode 100644 index 000000000..f4f11d8f4 --- /dev/null +++ b/admin/win/tools/NCToolsShared/SimpleNamedMutex.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "SimpleNamedMutex.h" + +SimpleNamedMutex::SimpleNamedMutex(const std::wstring &name) +{ + _name = name; +} + +bool SimpleNamedMutex::lock() +{ + if (_name.empty() || _hMutex) { + return false; + } + + // Mutex + _hMutex = CreateMutex(nullptr, TRUE, _name.data()); + + if (GetLastError() == ERROR_ALREADY_EXISTS) { + CloseHandle(_hMutex); + _hMutex = nullptr; + return false; + } + + return true; +} + +void SimpleNamedMutex::unlock() +{ + // Release mutex + if (_hMutex) { + ReleaseMutex(_hMutex); + CloseHandle(_hMutex); + _hMutex = nullptr; + } +} diff --git a/admin/win/tools/NCToolsShared/SimpleNamedMutex.h b/admin/win/tools/NCToolsShared/SimpleNamedMutex.h new file mode 100644 index 000000000..d02564a37 --- /dev/null +++ b/admin/win/tools/NCToolsShared/SimpleNamedMutex.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) by Michael Schuster + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include +#include + +class SimpleNamedMutex +{ +public: + SimpleNamedMutex(const std::wstring &name); + + bool lock(); + void unlock(); + +private: + std::wstring _name; + HANDLE _hMutex = nullptr; +}; diff --git a/admin/win/tools/NCToolsShared/utility.h b/admin/win/tools/NCToolsShared/utility.h new file mode 100644 index 000000000..07fefaca6 --- /dev/null +++ b/admin/win/tools/NCToolsShared/utility.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) by Klaas Freitag + * Copyright (C) by Daniel Molkentin + * Copyright (C) by Michael Schuster + * + * 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 + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace NCTools { + +typedef std::variant> registryVariant; + +static const std::wstring PathSeparator = L"\\"; + +namespace Utility { + // Ported from libsync + registryVariant registryGetKeyValue(HKEY hRootKey, const std::wstring& subKey, const std::wstring& valueName); + bool registrySetKeyValue(HKEY hRootKey, const std::wstring &subKey, const std::wstring &valueName, DWORD type, const registryVariant &value); + bool registryDeleteKeyTree(HKEY hRootKey, const std::wstring &subKey); + bool registryDeleteKeyValue(HKEY hRootKey, const std::wstring &subKey, const std::wstring &valueName); + bool registryWalkSubKeys(HKEY hRootKey, const std::wstring &subKey, const std::function &callback); + + // Ported from gui, modified to optionally rename matching files + typedef std::function copy_dir_recursive_callback; + bool copy_dir_recursive(std::wstring from_dir, std::wstring to_dir, copy_dir_recursive_callback* callbackFileNameMatchReplace = nullptr); + + // Created for native Win32 + DWORD execCmd(std::wstring cmd, bool wait = true); + bool killProcess(const std::wstring &exePath); + bool isValidDirectory(const std::wstring &path); + std::wstring getAppRegistryString(const std::wstring &appVendor, const std::wstring &appName, const std::wstring &valueName); + std::wstring getAppPath(const std::wstring &appVendor, const std::wstring &appName); + std::wstring getConfigPath(const std::wstring &appName); + void waitForNsisUninstaller(const std::wstring& appShortName); + void removeNavigationPaneEntries(const std::wstring &appName); +} + +} // namespace NCTools diff --git a/admin/win/tools/NCToolsShared/utility_win.cpp b/admin/win/tools/NCToolsShared/utility_win.cpp new file mode 100644 index 000000000..34e083cdf --- /dev/null +++ b/admin/win/tools/NCToolsShared/utility_win.cpp @@ -0,0 +1,477 @@ +/* + * Copyright (C) by Daniel Molkentin + * Copyright (C) by Michael Schuster + * + * 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 "utility.h" +#include +#include +#include +#include + +#define ASSERT assert +#define Q_ASSERT assert + +namespace NCTools { + +// Ported from libsync + +registryVariant Utility::registryGetKeyValue(HKEY hRootKey, const std::wstring &subKey, const std::wstring &valueName) +{ + registryVariant value; + + HKEY hKey; + + REGSAM sam = KEY_READ | KEY_WOW64_64KEY; + LONG result = RegOpenKeyEx(hRootKey, reinterpret_cast(subKey.data()), 0, sam, &hKey); + ASSERT(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); + if (result != ERROR_SUCCESS) + return value; + + DWORD type = 0, sizeInBytes = 0; + result = RegQueryValueEx(hKey, reinterpret_cast(valueName.data()), 0, &type, nullptr, &sizeInBytes); + ASSERT(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); + if (result == ERROR_SUCCESS) { + switch (type) { + case REG_DWORD: + DWORD dword; + Q_ASSERT(sizeInBytes == sizeof(dword)); + if (RegQueryValueEx(hKey, reinterpret_cast(valueName.data()), 0, &type, reinterpret_cast(&dword), &sizeInBytes) == ERROR_SUCCESS) { + value = int(dword); + } + break; + case REG_EXPAND_SZ: + case REG_SZ: { + std::wstring string; + string.resize(sizeInBytes / sizeof(wchar_t)); + result = RegQueryValueEx(hKey, reinterpret_cast(valueName.data()), 0, &type, reinterpret_cast(string.data()), &sizeInBytes); + + if (result == ERROR_SUCCESS) { + int newCharSize = sizeInBytes / sizeof(wchar_t); + // From the doc: + // If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with + // the proper terminating null characters. Therefore, even if the function returns ERROR_SUCCESS, + // the application should ensure that the string is properly terminated before using it; otherwise, it may overwrite a buffer. + if (string.at(newCharSize - 1) == wchar_t('\0')) + string.resize(newCharSize - 1); + value = string; + } + break; + } + case REG_BINARY: { + std::vector buffer; + buffer.resize(sizeInBytes); + result = RegQueryValueEx(hKey, reinterpret_cast(valueName.data()), 0, &type, reinterpret_cast(buffer.data()), &sizeInBytes); + if (result == ERROR_SUCCESS) { + value = buffer.at(12); + } + break; + } + default: + break;// Q_UNREACHABLE(); + } + } + ASSERT(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); + + RegCloseKey(hKey); + return value; +} + +bool Utility::registrySetKeyValue(HKEY hRootKey, const std::wstring &subKey, const std::wstring &valueName, DWORD type, const registryVariant &value) +{ + HKEY hKey; + // KEY_WOW64_64KEY is necessary because CLSIDs are "Redirected and reflected only for CLSIDs that do not specify InprocServer32 or InprocHandler32." + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384253%28v=vs.85%29.aspx#redirected__shared__and_reflected_keys_under_wow64 + // This shouldn't be an issue in our case since we use shell32.dll as InprocServer32, so we could write those registry keys for both 32 and 64bit. + // FIXME: Not doing so at the moment means that explorer will show the cloud provider, but 32bit processes' open dialogs (like the ownCloud client itself) won't show it. + REGSAM sam = KEY_WRITE | KEY_WOW64_64KEY; + LONG result = RegCreateKeyEx(hRootKey, reinterpret_cast(subKey.data()), 0, nullptr, 0, sam, nullptr, &hKey, nullptr); + ASSERT(result == ERROR_SUCCESS); + if (result != ERROR_SUCCESS) + return false; + + result = -1; + switch (type) { + case REG_DWORD: { + try { + DWORD dword = std::get(value); + result = RegSetValueEx(hKey, reinterpret_cast(valueName.data()), 0, type, reinterpret_cast(&dword), sizeof(dword)); + } + catch (const std::bad_variant_access&) {} + break; + } + case REG_EXPAND_SZ: + case REG_SZ: { + try { + std::wstring string = std::get(value); + result = RegSetValueEx(hKey, reinterpret_cast(valueName.data()), 0, type, reinterpret_cast(string.data()), static_cast((string.size() + 1) * sizeof(wchar_t))); + } + catch (const std::bad_variant_access&) {} + break; + } + default: + break;// Q_UNREACHABLE(); + } + ASSERT(result == ERROR_SUCCESS); + + RegCloseKey(hKey); + return result == ERROR_SUCCESS; +} + +bool Utility::registryDeleteKeyTree(HKEY hRootKey, const std::wstring &subKey) +{ + HKEY hKey; + REGSAM sam = DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_64KEY; + LONG result = RegOpenKeyEx(hRootKey, reinterpret_cast(subKey.data()), 0, sam, &hKey); + ASSERT(result == ERROR_SUCCESS); + if (result != ERROR_SUCCESS) + return false; + + result = RegDeleteTree(hKey, nullptr); + RegCloseKey(hKey); + ASSERT(result == ERROR_SUCCESS); + + result |= RegDeleteKeyEx(hRootKey, reinterpret_cast(subKey.data()), sam, 0); + ASSERT(result == ERROR_SUCCESS); + + return result == ERROR_SUCCESS; +} + +bool Utility::registryDeleteKeyValue(HKEY hRootKey, const std::wstring &subKey, const std::wstring &valueName) +{ + HKEY hKey; + REGSAM sam = KEY_WRITE | KEY_WOW64_64KEY; + LONG result = RegOpenKeyEx(hRootKey, reinterpret_cast(subKey.data()), 0, sam, &hKey); + ASSERT(result == ERROR_SUCCESS); + if (result != ERROR_SUCCESS) + return false; + + result = RegDeleteValue(hKey, reinterpret_cast(valueName.data())); + ASSERT(result == ERROR_SUCCESS); + + RegCloseKey(hKey); + return result == ERROR_SUCCESS; +} + +bool Utility::registryWalkSubKeys(HKEY hRootKey, const std::wstring &subKey, const std::function &callback) +{ + HKEY hKey; + REGSAM sam = KEY_READ | KEY_WOW64_64KEY; + LONG result = RegOpenKeyEx(hRootKey, reinterpret_cast(subKey.data()), 0, sam, &hKey); + ASSERT(result == ERROR_SUCCESS); + if (result != ERROR_SUCCESS) + return false; + + DWORD maxSubKeyNameSize; + // Get the largest keyname size once instead of relying each call on ERROR_MORE_DATA. + result = RegQueryInfoKey(hKey, nullptr, nullptr, nullptr, nullptr, &maxSubKeyNameSize, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + ASSERT(result == ERROR_SUCCESS); + if (result != ERROR_SUCCESS) { + RegCloseKey(hKey); + return false; + } + + std::wstring subKeyName; + subKeyName.reserve(maxSubKeyNameSize + 1); + + DWORD retCode = ERROR_SUCCESS; + for (DWORD i = 0; retCode == ERROR_SUCCESS; ++i) { + Q_ASSERT(unsigned(subKeyName.capacity()) > maxSubKeyNameSize); + // Make the previously reserved capacity official again. + subKeyName.resize(subKeyName.capacity()); + DWORD subKeyNameSize = static_cast(subKeyName.size()); + retCode = RegEnumKeyEx(hKey, i, reinterpret_cast(subKeyName.data()), &subKeyNameSize, nullptr, nullptr, nullptr, nullptr); + + ASSERT(result == ERROR_SUCCESS || retCode == ERROR_NO_MORE_ITEMS); + if (retCode == ERROR_SUCCESS) { + // subKeyNameSize excludes the trailing \0 + subKeyName.resize(subKeyNameSize); + // Pass only the sub keyname, not the full path. + callback(hKey, subKeyName); + } + } + + RegCloseKey(hKey); + return retCode != ERROR_NO_MORE_ITEMS; +} + +// Created for Win32 + +DWORD Utility::execCmd(std::wstring cmd, bool wait) +{ + // https://docs.microsoft.com/en-us/windows/win32/procthread/creating-processes + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + // Start the child process. + if (!CreateProcess(nullptr, // No module name (use command line) + cmd.data(), // Command line + nullptr, // Process handle not inheritable + nullptr, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + nullptr, // Use parent's environment block + nullptr, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi) // Pointer to PROCESS_INFORMATION structure + ) + { + return ERROR_INVALID_FUNCTION; + } + + DWORD exitCode = 0; + + if (wait) { + // Wait until child process exits. + WaitForSingleObject(pi.hProcess, INFINITE); + + GetExitCodeProcess(pi.hProcess, &exitCode); + } + + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return exitCode; +} + +bool Utility::killProcess(const std::wstring &exePath) +{ + // https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes + // Get the list of process identifiers. + DWORD aProcesses[1024], cbNeeded, cProcesses, i; + + if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) { + return false; + } + + // Calculate how many process identifiers were returned. + cProcesses = cbNeeded / sizeof(DWORD); + + std::wstring tmpMatch = exePath; + std::transform(tmpMatch.begin(), tmpMatch.end(), tmpMatch.begin(), std::tolower); + + for (i = 0; i < cProcesses; i++) { + if (aProcesses[i] != 0) { + // Get a handle to the process. + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, FALSE, aProcesses[i]); + + // Get the process name. + if (hProcess) { + TCHAR szProcessName[MAX_PATH] = {0}; + DWORD cbSize = sizeof(szProcessName) / sizeof(TCHAR); + + if (QueryFullProcessImageName(hProcess, 0, szProcessName, &cbSize) == TRUE && cbSize > 0) { + std::wstring procName = szProcessName; + std::transform(procName.begin(), procName.end(), procName.begin(), std::tolower); + + if (procName == tmpMatch) { + if (TerminateProcess(hProcess, 0) == TRUE) { + WaitForSingleObject(hProcess, INFINITE); + CloseHandle(hProcess); + return true; + } + } + } + + CloseHandle(hProcess); + } + } + } + + return false; +} + +bool Utility::isValidDirectory(const std::wstring &path) +{ + auto attrib = GetFileAttributes(path.data()); + + if (attrib == INVALID_FILE_ATTRIBUTES || GetLastError() == ERROR_FILE_NOT_FOUND) { + return false; + } + + return (attrib & FILE_ATTRIBUTE_DIRECTORY); +} + +std::wstring Utility::getAppRegistryString(const std::wstring &appVendor, const std::wstring &appName, const std::wstring &valueName) +{ + std::wstring appKey = std::wstring(LR"(SOFTWARE\)") + appVendor + L'\\' + appName; + std::wstring appKeyWow64 = std::wstring(LR"(SOFTWARE\WOW6432Node\)") + appVendor + L'\\' + appName; + + std::vector appKeys = { appKey, appKeyWow64 }; + + for (auto &key : appKeys) { + try { + return std::get(Utility::registryGetKeyValue(HKEY_LOCAL_MACHINE, + key, + valueName)); + } + catch (const std::bad_variant_access&) {} + } + + return {}; +} + +std::wstring Utility::getAppPath(const std::wstring &appVendor, const std::wstring &appName) +{ + return getAppRegistryString(appVendor, appName, L""); // intentionally left empty to get the key's "(default)" value +} + +std::wstring Utility::getConfigPath(const std::wstring &appName) +{ + // On Windows, use AppDataLocation, that's where the roaming data is and where we should store the config file + PWSTR pszPath = nullptr; + if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &pszPath)) || !pszPath) { + return {}; + } + std::wstring path = pszPath + PathSeparator + appName + PathSeparator; + CoTaskMemFree(pszPath); + + auto newLocation = path; + + return newLocation; +} + +void Utility::waitForNsisUninstaller(const std::wstring &appShortName) +{ + // Can't WaitForSingleObject because NSIS Uninstall.exe copies itself to a TEMP directory and creates a new process, + // so we do sort of a hack and wait for its mutex (see nextcloud.nsi). + HANDLE hMutex; + DWORD lastError = ERROR_SUCCESS; + std::wstring name = appShortName + std::wstring(L"Uninstaller"); + + // Give the process enough time to start, to wait for the NSIS mutex. + Sleep(1500); + + do { + hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, name.data()); + lastError = GetLastError(); + if (hMutex) { + CloseHandle(hMutex); + } + + // This is sort of a hack because WaitForSingleObject immediately returns for the NSIS mutex. + Sleep(500); + } while (lastError != ERROR_FILE_NOT_FOUND); +} + +void Utility::removeNavigationPaneEntries(const std::wstring &appName) +{ + if (appName.empty()) { + return; + } + + // Start by looking at every registered namespace extension for the sidebar, and look for an "ApplicationName" value + // that matches ours when we saved. + std::vector entriesToRemove; + Utility::registryWalkSubKeys( + HKEY_CURRENT_USER, + LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace)", + [&entriesToRemove, &appName](HKEY key, const std::wstring &subKey) { + try { + auto curAppName = std::get(Utility::registryGetKeyValue(key, subKey, L"ApplicationName")); + + if (curAppName == appName) { + entriesToRemove.push_back(subKey); + } + } + catch (const std::bad_variant_access&) {} + }); + + for (auto &clsid : entriesToRemove) { + std::wstring clsidStr = clsid; + std::wstring clsidPath = std::wstring(LR"(Software\Classes\CLSID\)") + clsidStr; + std::wstring clsidPathWow64 = std::wstring(LR"(Software\Classes\Wow6432Node\CLSID\)") + clsidStr; + std::wstring namespacePath = std::wstring(LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\)") + clsidStr; + + Utility::registryDeleteKeyTree(HKEY_CURRENT_USER, clsidPath); + Utility::registryDeleteKeyTree(HKEY_CURRENT_USER, clsidPathWow64); + Utility::registryDeleteKeyTree(HKEY_CURRENT_USER, namespacePath); + Utility::registryDeleteKeyValue(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel)", clsidStr); + } +} + +// Ported from gui, modified to optionally rename matching files +bool Utility::copy_dir_recursive(std::wstring from_dir, std::wstring to_dir, copy_dir_recursive_callback *callbackFileNameMatchReplace) +{ + WIN32_FIND_DATA fileData; + + if (from_dir.empty() || to_dir.empty()) { + return false; + } + + if (from_dir.back() != PathSeparator.front()) + from_dir.append(PathSeparator); + if (to_dir.back() != PathSeparator.front()) + to_dir.append(PathSeparator); + + std::wstring startDir = from_dir; + startDir.append(L"*.*"); + + auto hFind = FindFirstFile(startDir.data(), &fileData); + + if (hFind == INVALID_HANDLE_VALUE) { + return false; + } + + bool success = true; + + do { + if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (std::wstring(fileData.cFileName) == L"." || std::wstring(fileData.cFileName) == L"..") { + continue; + } + + std::wstring from = from_dir + fileData.cFileName; + std::wstring to = to_dir + fileData.cFileName; + + if (CreateDirectoryEx(from.data(), to.data(), nullptr) == FALSE) { + success = false; + break; + } + + if (copy_dir_recursive(from, to, callbackFileNameMatchReplace) == false) { + success = false; + break; + } + } else { + std::wstring newFilename = fileData.cFileName; + + if (callbackFileNameMatchReplace) { + (*callbackFileNameMatchReplace)(std::wstring(fileData.cFileName), newFilename); + } + + std::wstring from = from_dir + fileData.cFileName; + std::wstring to = to_dir + newFilename; + + if (CopyFile(from.data(), to.data(), TRUE) == FALSE) { + success = false; + break; + } + } + } while (FindNextFile(hFind, &fileData)); + + FindClose(hFind); + + return success; +} + +} // namespace NCTools diff --git a/cmake/modules/AddCMockaTest.cmake b/cmake/modules/AddCMockaTest.cmake new file mode 100644 index 000000000..b2d1ca8a4 --- /dev/null +++ b/cmake/modules/AddCMockaTest.cmake @@ -0,0 +1,23 @@ +# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN) + +# Copyright (c) 2007 Daniel Gollub +# Copyright (c) 2007-2010 Andreas Schneider +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +enable_testing() +include(CTest) + +if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) + set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags") + set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") + set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") + set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") +endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) + +function (ADD_CMOCKA_TEST _testName _testSource) + add_executable(${_testName} ${_testSource}) + target_link_libraries(${_testName} ${ARGN}) + add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}) +endfunction (ADD_CMOCKA_TEST) diff --git a/cmake/modules/COPYING-CMAKE-SCRIPTS b/cmake/modules/COPYING-CMAKE-SCRIPTS new file mode 100644 index 000000000..4b417765f --- /dev/null +++ b/cmake/modules/COPYING-CMAKE-SCRIPTS @@ -0,0 +1,22 @@ +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. diff --git a/cmake/modules/CheckCCompilerFlagSSP.cmake b/cmake/modules/CheckCCompilerFlagSSP.cmake new file mode 100644 index 000000000..2fe43954a --- /dev/null +++ b/cmake/modules/CheckCCompilerFlagSSP.cmake @@ -0,0 +1,26 @@ +# - Check whether the C compiler supports a given flag in the +# context of a stack checking compiler option. + +# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE) +# +# FLAG - the compiler flag +# VARIABLE - variable to store the result +# +# This actually calls check_c_source_compiles. +# See help for CheckCSourceCompiles for a listing of variables +# that can modify the build. + +# Copyright (c) 2006, Alexander Neundorf, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +include(CheckCSourceCompiles) + +function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) + set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT}) + set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") +endfunction(CHECK_C_COMPILER_FLAG_SSP) diff --git a/cmake/modules/CheckPrototypeDefinition.c.in b/cmake/modules/CheckPrototypeDefinition.c.in new file mode 100644 index 000000000..a97344ac3 --- /dev/null +++ b/cmake/modules/CheckPrototypeDefinition.c.in @@ -0,0 +1,29 @@ +@CHECK_PROTOTYPE_DEFINITION_HEADER@ + +static void cmakeRequireSymbol(int dummy, ...) { + (void) dummy; +} + +static void checkSymbol(void) { +#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@ + cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@); +#endif +} + +@CHECK_PROTOTYPE_DEFINITION_PROTO@ { + return @CHECK_PROTOTYPE_DEFINITION_RETURN@; +} + +#ifdef __CLASSIC_C__ +int main() { + int ac; + char*av[]; +#else +int main(int ac, char *av[]) { +#endif + checkSymbol(); + if (ac > 1000) { + return *av[0]; + } + return 0; +} diff --git a/cmake/modules/CheckPrototypeDefinition.cmake b/cmake/modules/CheckPrototypeDefinition.cmake new file mode 100644 index 000000000..5d16eba4e --- /dev/null +++ b/cmake/modules/CheckPrototypeDefinition.cmake @@ -0,0 +1,98 @@ +# - Check if the prototype we expect is correct. +# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE) +# FUNCTION - The name of the function (used to check if prototype exists) +# PROTOTYPE- The prototype to check. +# RETURN - The return value of the function. +# HEADER - The header files required. +# VARIABLE - The variable to store the result. +# Example: +# check_prototype_definition(getpwent_r +# "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)" +# "NULL" +# "unistd.h;pwd.h" +# SOLARIS_GETPWENT_R) +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2010-2011 Andreas Schneider +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) +# + + +get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) + + +function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE) + + if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$") + set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n") + + set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS}) + if (CMAKE_REQUIRED_LIBRARIES) + set(CHECK_PROTOTYPE_DEFINITION_LIBS + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_PROTOTYPE_DEFINITION_LIBS) + endif() + if (CMAKE_REQUIRED_INCLUDES) + set(CMAKE_SYMBOL_EXISTS_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CMAKE_SYMBOL_EXISTS_INCLUDES) + endif() + + foreach(_FILE ${_HEADER}) + set(CHECK_PROTOTYPE_DEFINITION_HEADER + "${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n") + endforeach() + + set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION}) + set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE}) + set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN}) + + configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY) + + file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE) + + try_compile(${_VARIABLE} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_PROTOTYPE_DEFINITION_LIBS} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS} + "${CMAKE_SYMBOL_EXISTS_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + + if (${_VARIABLE}) + set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") + message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n" + "${OUTPUT}\n\n") + else () + message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False") + set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n" + "${OUTPUT}\n\n${_SOURCE}\n\n") + endif () + endif() + +endfunction() diff --git a/cmake/modules/Copyright.txt b/cmake/modules/Copyright.txt new file mode 100644 index 000000000..05cb143f1 --- /dev/null +++ b/cmake/modules/Copyright.txt @@ -0,0 +1,13 @@ +CMake - Cross Platform Makefile Generator +Copyright 2000-2009 Kitware, Inc., Insight Software Consortium +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the names of Kitware, Inc., the Insight Software Consortium, nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. diff --git a/cmake/modules/DBusMacros.cmake b/cmake/modules/DBusMacros.cmake new file mode 100644 index 000000000..e69de29bb diff --git a/cmake/modules/DefineCMakeDefaults.cmake b/cmake/modules/DefineCMakeDefaults.cmake new file mode 100644 index 000000000..8c00f49e7 --- /dev/null +++ b/cmake/modules/DefineCMakeDefaults.cmake @@ -0,0 +1,29 @@ +# (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. + +# Always include srcdir and builddir in include path +# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in +# about every subdir +# since cmake 2.4.0 +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Put the include dirs which are in the source or build tree +# before all other include dirs, so the headers in the sources +# are preferred over the already installed ones +# since cmake 2.4.1 +set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) + +# Use colored output +# since cmake 2.4.0 +set(CMAKE_COLOR_MAKEFILE ON) + +# Define the generic version of the libraries here +set(GENERIC_LIB_VERSION "0.1.0") +set(GENERIC_LIB_SOVERSION "0") + +# set -Werror +set(CMAKE_ENABLE_WERROR ON) + +# enables folders for targets to be visible in an IDE +set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/cmake/modules/DefineCompilerFlags.cmake b/cmake/modules/DefineCompilerFlags.cmake new file mode 100644 index 000000000..d2ef129c5 --- /dev/null +++ b/cmake/modules/DefineCompilerFlags.cmake @@ -0,0 +1,96 @@ +# (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. + +# define system dependent compiler flags + +include(CheckCCompilerFlag) +include(CheckCCompilerFlagSSP) + +# +# Define GNUCC compiler flags +# +if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") + + # add -Wconversion ? + # cannot be pedantic with sqlite3 directly linked + # FIXME Can we somehow not use those flags for sqlite3.* but use them for the rest of csync? + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -D_GNU_SOURCE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__STDC_FORMAT_MACROS=1") + + if (${CMAKE_C_COMPILER_ID} MATCHES "Clang") + # Disable warning for assert() statements in csync + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-gnu-statement-expression") + endif() + + set(CSYNC_STRICT OFF CACHE BOOL "Strict error checking, enabled -Werror and friends") + if (CSYNC_STRICT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + endif(CSYNC_STRICT) + + # with -fPIC + check_c_compiler_flag("-fPIC" WITH_FPIC) + if (WITH_FPIC AND NOT WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + endif (WITH_FPIC AND NOT WIN32) + + check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) + if (WITH_STACK_PROTECTOR AND NOT WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") + endif (WITH_STACK_PROTECTOR AND NOT WIN32) + + if (CMAKE_BUILD_TYPE) + string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) + if (CMAKE_BUILD_TYPE_LOWER MATCHES "(release|relwithdebinfo|minsizerel)" AND (NOT ${CMAKE_C_FLAGS} MATCHES "FORTIFY_SOURCE=[3-9]")) + check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) + if (WITH_FORTIFY_SOURCE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2") + endif (WITH_FORTIFY_SOURCE) + endif() + endif() +endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") + +if (UNIX AND NOT WIN32) + # + # Check for large filesystem support + # + if (CMAKE_SIZEOF_VOID_P MATCHES "8") + # with large file support + execute_process( + COMMAND + getconf LFS64_CFLAGS + OUTPUT_VARIABLE + _lfs_CFLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + else (CMAKE_SIZEOF_VOID_P MATCHES "8") + # with large file support + execute_process( + COMMAND + getconf LFS_CFLAGS + OUTPUT_VARIABLE + _lfs_CFLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif (CMAKE_SIZEOF_VOID_P MATCHES "8") + if (_lfs_CFLAGS) + string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}") + endif (_lfs_CFLAGS) +else(UNIX AND NOT WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64") +endif (UNIX AND NOT WIN32) + +if (MSVC) + # Use secure functions by default and suppress warnings about + #"deprecated" functions + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") +endif (MSVC) diff --git a/cmake/modules/DefineInstallationPaths.cmake b/cmake/modules/DefineInstallationPaths.cmake new file mode 100644 index 000000000..b1fb47d59 --- /dev/null +++ b/cmake/modules/DefineInstallationPaths.cmake @@ -0,0 +1,111 @@ +# (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. + +if (UNIX) + # Suffix for Linux + SET(LIB_SUFFIX + CACHE STRING "Define suffix of directory name (32/64)" + ) + + SET(EXEC_INSTALL_PREFIX + "${CMAKE_INSTALL_PREFIX}" + CACHE PATH "Base directory for executables and libraries" + ) + SET(SHARE_INSTALL_PREFIX + "${CMAKE_INSTALL_PREFIX}/share" + CACHE PATH "Base directory for files which go to share/" + ) + SET(DATA_INSTALL_PREFIX + "${SHARE_INSTALL_PREFIX}" + CACHE PATH "The parent directory where applications can install their data") + + # The following are directories where stuff will be installed to + SET(BIN_INSTALL_DIR + "${CMAKE_INSTALL_BINDIR}" + CACHE PATH "The ${APPLICATION_SHORTNAME} binary install dir (default prefix/bin)" + ) + SET(SBIN_INSTALL_DIR + "${EXEC_INSTALL_PREFIX}/sbin" + CACHE PATH "The ${APPLICATION_SHORTNAME} sbin install dir (default prefix/sbin)" + ) + SET(LIB_INSTALL_DIR + "${CMAKE_INSTALL_LIBDIR}" + CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" + ) + SET(LIBEXEC_INSTALL_DIR + "${EXEC_INSTALL_PREFIX}/libexec" + CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" + ) + SET(LIB_PRIVATE_INSTALL_DIR + "${LIB_INSTALL_DIR}" + CACHE PATH "The subdirectory relative to the install prefix where private libs are installed" + ) + SET(INCLUDE_INSTALL_DIR + "${CMAKE_INSTALL_PREFIX}/include" + CACHE PATH "The subdirectory to the header prefix (default prefix/include)" + ) + + SET(DATA_INSTALL_DIR + "${DATA_INSTALL_PREFIX}" + CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_SHORTNAME})" + ) + SET(HTML_INSTALL_DIR + "${DATA_INSTALL_PREFIX}/doc/HTML" + CACHE PATH "The HTML install dir for documentation (default data/doc/html)" + ) + SET(ICON_INSTALL_DIR + "${DATA_INSTALL_PREFIX}/icons" + CACHE PATH "The icon install dir (default data/icons/)" + ) + SET(SOUND_INSTALL_DIR + "${DATA_INSTALL_PREFIX}/sounds" + CACHE PATH "The install dir for sound files (default data/sounds)" + ) + + SET(LOCALE_INSTALL_DIR + "${SHARE_INSTALL_PREFIX}/locale" + CACHE PATH "The install dir for translations (default prefix/share/locale)" + ) + + SET(XDG_APPS_DIR + "${SHARE_INSTALL_PREFIX}/applications/" + CACHE PATH "The XDG apps dir" + ) + SET(XDG_DIRECTORY_DIR + "${SHARE_INSTALL_PREFIX}/desktop-directories" + CACHE PATH "The XDG directory" + ) + + IF(NOT "${EXEC_INSTALL_PREFIX}" STREQUAL "/usr") + SET(SYSCONFDIR_INSTALL_PREFIX "${EXEC_INSTALL_PREFIX}") + endif() + + SET(SYSCONF_INSTALL_DIR + "${SYSCONFDIR_INSTALL_PREFIX}/etc" + CACHE PATH "The ${APPLICATION_SHORTNAME} sysconfig install dir (default prefix/etc)" + ) + SET(MAN_INSTALL_DIR + "${SHARE_INSTALL_PREFIX}/man" + CACHE PATH "The ${APPLICATION_SHORTNAME} man install dir (default prefix/man)" + ) + SET(INFO_INSTALL_DIR + "${SHARE_INSTALL_PREFIX}/info" + CACHE PATH "The ${APPLICATION_SHORTNAME} info install dir (default prefix/info)" + ) +endif (UNIX) + +if (WIN32) + # Same same + set(SHARE_INSTALL_PREFIX "share" CACHE PATH "-") + set(BIN_INSTALL_DIR "." CACHE PATH "-") + set(SBIN_INSTALL_DIR "." CACHE PATH "-") + set(LIB_INSTALL_DIR "lib" CACHE PATH "-") + set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-") + set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-") + set(ICON_INSTALL_DIR "." CACHE PATH "-") + set(SOUND_INSTALL_DIR "." CACHE PATH "-") + set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-") + set(SYSCONF_INSTALL_DIR "config" CACHE PATH "-") + set(MAN_INSTALL_DIR "man" CACHE PATH "-") +endif (WIN32) diff --git a/cmake/modules/DefinePlatformDefaults.cmake b/cmake/modules/DefinePlatformDefaults.cmake new file mode 100644 index 000000000..91f659215 --- /dev/null +++ b/cmake/modules/DefinePlatformDefaults.cmake @@ -0,0 +1,32 @@ +# (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. + +# Set system vars + +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + set(LINUX TRUE) +endif(CMAKE_SYSTEM_NAME MATCHES "Linux") + +if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(FREEBSD TRUE) + set(BSD TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + +if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + set(OPENBSD TRUE) + set(BSD TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + +if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") + set(NETBSD TRUE) + set(BSD TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") + +if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") + set(SOLARIS TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") + +if (CMAKE_SYSTEM_NAME MATCHES "OS2") + set(OS2 TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "OS2") diff --git a/cmake/modules/DeployQt5.cmake b/cmake/modules/DeployQt5.cmake new file mode 100644 index 000000000..b9e5d7029 --- /dev/null +++ b/cmake/modules/DeployQt5.cmake @@ -0,0 +1,381 @@ +# - Functions to help assemble a standalone Qt5 executable. +# A collection of CMake utility functions useful for deploying +# Qt5 executables. +# +# The following functions are provided by this module: +# write_qt5_conf +# resolve_qt5_paths +# fixup_qt5_executable +# install_qt5_plugin_path +# install_qt5_plugin +# install_qt5_executable +# Requires CMake 2.6 or greater because it uses function and +# PARENT_SCOPE. Also depends on BundleUtilities.cmake. +# +# WRITE_QT5_CONF( ) +# Writes a qt.conf file with the into . +# +# RESOLVE_QT5_PATHS( []) +# Loop through list and if any don't exist resolve them +# relative to the (if supplied) or the CMAKE_INSTALL_PREFIX. +# +# FIXUP_QT5_EXECUTABLE( [ ]) +# Copies Qt plugins, writes a Qt configuration file (if needed) and fixes up a +# Qt5 executable using BundleUtilities so it is standalone and can be +# drag-and-drop copied to another machine as long as all of the system +# libraries are compatible. +# +# should point to the executable to be fixed-up. +# +# should contain a list of the names or paths of any Qt plugins +# to be installed. +# +# will be passed to BundleUtilities and should be a list of any already +# installed plugins, libraries or executables to also be fixed-up. +# +# will be passed to BundleUtilities and should contain and directories +# to be searched to find library dependencies. +# +# allows an custom plugins directory to be used. +# +# will force a qt.conf file to be written even if not needed. +# +# INSTALL_QT5_PLUGIN_PATH(plugin executable copy installed_plugin_path_var ) +# Install (or copy) a resolved to the default plugins directory +# (or ) relative to and store the result in +# . +# +# If is set to TRUE then the plugins will be copied rather than +# installed. This is to allow this module to be used at CMake time rather than +# install time. +# +# If is set then anything installed will use this COMPONENT. +# +# INSTALL_QT5_PLUGIN(plugin executable copy installed_plugin_path_var ) +# Install (or copy) an unresolved to the default plugins directory +# (or ) relative to and store the result in +# . See documentation of INSTALL_QT5_PLUGIN_PATH. +# +# INSTALL_QT5_EXECUTABLE( [ ]) +# Installs Qt plugins, writes a Qt configuration file (if needed) and fixes up +# a Qt5 executable using BundleUtilities so it is standalone and can be +# drag-and-drop copied to another machine as long as all of the system +# libraries are compatible. The executable will be fixed-up at install time. +# is the COMPONENT used for bundle fixup and plugin installation. +# See documentation of FIXUP_QT5_BUNDLE. + +#============================================================================= +# Copyright 2011 Mike McQuaid +# Copyright 2013 Mihai Moldovan +# CMake - Cross Platform Makefile Generator +# Copyright 2000-2011 Kitware, Inc., Insight Software Consortium +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "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 COPYRIGHT +# HOLDER OR CONTRIBUTORS 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. + +# The functions defined in this file depend on the fixup_bundle function +# (and others) found in BundleUtilities.cmake + +include(BundleUtilities) +set(DeployQt5_cmake_dir "${CMAKE_CURRENT_LIST_DIR}") +set(DeployQt5_apple_plugins_dir "PlugIns") + +function(write_qt5_conf qt_conf_dir qt_conf_contents) + set(qt_conf_path "${qt_conf_dir}/qt.conf") + message(STATUS "Writing ${qt_conf_path}") + file(WRITE "${qt_conf_path}" "${qt_conf_contents}") +endfunction() + +function(resolve_qt5_paths paths_var) + set(executable_path ${ARGV1}) + + set(paths_resolved) + foreach(path ${${paths_var}}) + if(EXISTS "${path}") + list(APPEND paths_resolved "${path}") + else() + if(${executable_path}) + list(APPEND paths_resolved +"${executable_path}/${path}") + else() + list(APPEND paths_resolved +"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}") + endif() + endif() + endforeach() + set(${paths_var} ${paths_resolved} PARENT_SCOPE) +endfunction() + +function(fixup_qt5_executable executable) + set(qtplugins ${ARGV1}) + set(libs ${ARGV2}) + set(dirs ${ARGV3}) + set(plugins_dir ${ARGV4}) + set(request_qt_conf ${ARGV5}) + + message(STATUS "fixup_qt5_executable") + message(STATUS " executable='${executable}'") + message(STATUS " qtplugins='${qtplugins}'") + message(STATUS " libs='${libs}'") + message(STATUS " dirs='${dirs}'") + message(STATUS " plugins_dir='${plugins_dir}'") + message(STATUS " request_qt_conf='${request_qt_conf}'") + + if(QT_LIBRARY_DIR) + list(APPEND dirs "${QT_LIBRARY_DIR}") + endif() + if(QT_BINARY_DIR) + list(APPEND dirs "${QT_BINARY_DIR}") + endif() + + if(APPLE) + set(qt_conf_dir "${executable}/Contents/Resources") + set(executable_path "${executable}") + set(write_qt_conf TRUE) + if(NOT plugins_dir) + set(plugins_dir "${DeployQt5_apple_plugins_dir}") + endif() + else() + get_filename_component(executable_path "${executable}" PATH) + if(NOT executable_path) + set(executable_path ".") + endif() + set(qt_conf_dir "${executable_path}") + set(write_qt_conf ${request_qt_conf}) + endif() + + foreach(plugin ${qtplugins}) + set(installed_plugin_path "") + install_qt5_plugin("${plugin}" "${executable}" 1 +installed_plugin_path) + list(APPEND libs ${installed_plugin_path}) + endforeach() + + foreach(lib ${libs}) + if(NOT EXISTS "${lib}") + message(FATAL_ERROR "Library does not exist: ${lib}") + endif() + endforeach() + + resolve_qt5_paths(libs "${executable_path}") + + if(write_qt_conf) + set(qt_conf_contents "[Paths]\nPlugins = ${plugins_dir}") + write_qt5_conf("${qt_conf_dir}" "${qt_conf_contents}") + endif() + + fixup_bundle("${executable}" "${libs}" "${dirs}") +endfunction() + +function(install_qt5_plugin_path plugin executable copy +installed_plugin_path_var) + set(plugins_dir ${ARGV4}) + set(component ${ARGV5}) + set(configurations ${ARGV6}) + if(EXISTS "${plugin}") + if(APPLE) + if(NOT plugins_dir) + set(plugins_dir +"${DeployQt5_apple_plugins_dir}") + endif() + set(plugins_path +"${executable}/Contents/${plugins_dir}") + else() + get_filename_component(plugins_path "${executable}" +PATH) + if(NOT plugins_path) + set(plugins_path ".") + endif() + if(plugins_dir) + set(plugins_path +"${plugins_path}/${plugins_dir}") + endif() + endif() + + set(plugin_group "") + + get_filename_component(plugin_path "${plugin}" PATH) + get_filename_component(plugin_parent_path "${plugin_path}" PATH) + get_filename_component(plugin_parent_dir_name +"${plugin_parent_path}" NAME) + get_filename_component(plugin_name "${plugin}" NAME) + string(TOLOWER "${plugin_parent_dir_name}" +plugin_parent_dir_name) + + if("${plugin_parent_dir_name}" STREQUAL "plugins") + get_filename_component(plugin_group "${plugin_path}" +NAME) + set(${plugin_group_var} "${plugin_group}") + endif() + set(plugins_path "${plugins_path}/${plugin_group}") + + if(${copy}) + file(MAKE_DIRECTORY "${plugins_path}") + file(COPY "${plugin}" DESTINATION "${plugins_path}") + else() + if(configurations AND (CMAKE_CONFIGURATION_TYPES OR +CMAKE_BUILD_TYPE)) + set(configurations CONFIGURATIONS +${configurations}) + else() + unset(configurations) + endif() + install(FILES "${plugin}" DESTINATION "${plugins_path}" +${configurations} ${component}) + endif() + set(${installed_plugin_path_var} +"${plugins_path}/${plugin_name}" PARENT_SCOPE) + endif() +endfunction() + +function(install_qt5_plugin plugin executable copy installed_plugin_path_var) + set(plugins_dir ${ARGV4}) + set(component ${ARGV5}) + if(EXISTS "${plugin}") + install_qt5_plugin_path("${plugin}" "${executable}" "${copy}" +"${installed_plugin_path_var}" "${plugins_dir}" "${component}") + else() + #string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var) + set(plugin_release) + set(plugin_debug) + set(plugin_tmp_path) + set(plugin_find_path "${Qt5Core_DIR}/../../../plugins/") + get_filename_component(plugin_find_path "${plugin_find_path}" +REALPATH) + set(plugin_find_release_filename "lib${plugin}.dylib") + set(plugin_find_debug_filename "lib${plugin}_debug.dylib") + file(GLOB_RECURSE pluginlist "${plugin_find_path}" +"${plugin_find_path}/*/lib*.dylib") + foreach(found_plugin ${pluginlist}) + get_filename_component(curname "${found_plugin}" NAME) + if("${curname}" STREQUAL "${plugin_find_release_filename}") + set(plugin_tmp_release_path "${found_plugin}") + endif() + if("${curname}" STREQUAL "${plugin_find_debug_filename}") + set(plugin_tmp_debug_path "${found_plugin}") + endif() + endforeach() + + if((NOT DEFINED plugin_tmp_release_path OR NOT EXISTS +"${plugin_tmp_release_path}") AND (NOT DEFINED plugin_tmp_debug_PATH OR NOT +EXISTS "${plugin_tmp_debug_path}")) + message(WARNING "Qt plugin \"${plugin}\" not recognized +or found.") + endif() + + if(EXISTS "${plugin_tmp_release_path}") + set(plugin_release "${plugin_tmp_release_path}") + elseif(EXISTS "${plugin_tmp_debug_path}") + set(plugin_release "${plugin_tmp_debug_path}") + endif() + + if(EXISTS "${plugin_tmp_debug_path}") + set(plugin_debug "${plugin_tmp_debug_path}") + elseif(EXISTS "${plugin_tmp_release_path}") + set(plugin_debug "${plugin_tmp_release_path}") + endif() + + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + install_qt5_plugin_path("${plugin_release}" +"${executable}" "${copy}" "${installed_plugin_path_var}_release" +"${plugins_dir}" "${component}" "Release|RelWithDebInfo|MinSizeRel") + install_qt5_plugin_path("${plugin_debug}" +"${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" +"${component}" "Debug") + + if(CMAKE_BUILD_TYPE MATCHES "^Debug$") + set(${installed_plugin_path_var} +${${installed_plugin_path_var}_debug}) + else() + set(${installed_plugin_path_var} +${${installed_plugin_path_var}_release}) + endif() + else() + install_qt5_plugin_path("${plugin_release}" +"${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" +"${component}") + endif() + endif() + set(${installed_plugin_path_var} ${${installed_plugin_path_var}} +PARENT_SCOPE) +endfunction() + +function(install_qt5_executable executable) + set(qtplugins ${ARGV1}) + set(libs ${ARGV2}) + set(dirs ${ARGV3}) + set(plugins_dir ${ARGV4}) + set(request_qt_conf ${ARGV5}) + set(component ${ARGV6}) + if(QT_LIBRARY_DIR) + list(APPEND dirs "${QT_LIBRARY_DIR}") + endif() + if(QT_BINARY_DIR) + list(APPEND dirs "${QT_BINARY_DIR}") + endif() + if(component) + set(component COMPONENT ${component}) + else() + unset(component) + endif() + + get_filename_component(executable_absolute "${executable}" ABSOLUTE) + if(EXISTS "${QT_QTCORE_LIBRARY_RELEASE}") + gp_file_type("${executable_absolute}" +"${QT_QTCORE_LIBRARY_RELEASE}" qtcore_type) + elseif(EXISTS "${QT_QTCORE_LIBRARY_DEBUG}") + gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_DEBUG}" +qtcore_type) + endif() + if(qtcore_type STREQUAL "system") + set(qt_plugins_dir "") + endif() + + if(QT_IS_STATIC) + message(WARNING "Qt built statically: not installing plugins.") + else() + foreach(plugin ${qtplugins}) + message(STATUS "trying to install plugin ${plugin}") + set(installed_plugin_paths "") + install_qt5_plugin("${plugin}" "${executable}" 0 +installed_plugin_paths "${plugins_dir}" "${component}") + list(APPEND libs ${installed_plugin_paths}) + endforeach() + endif() + + resolve_qt5_paths(libs "") + + install(CODE + "include(\"${DeployQt5_cmake_dir}/DeployQt5.cmake\") + set(BU_CHMOD_BUNDLE_ITEMS TRUE) + FIXUP_QT5_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" +\"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")" + ${component} + ) +endfunction() diff --git a/cmake/modules/ECMAddAppIcon.cmake b/cmake/modules/ECMAddAppIcon.cmake new file mode 100644 index 000000000..bd27b0590 --- /dev/null +++ b/cmake/modules/ECMAddAppIcon.cmake @@ -0,0 +1,415 @@ +#.rst: +# ECMAddAppIcon +# ------------- +# +# Add icons to executable files and packages. +# +# :: +# +# ecm_add_app_icon( +# ICONS [ [...]] +# [SIDEBAR_ICONS [ [...]] # Since 5.49 +# [OUTFILE_BASENAME ]) # Since 5.49 +# ) +# +# The given icons, whose names must match the pattern:: +# +# -.png +# +# will be added to the executable target whose sources are specified by +# ```` 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. +# +# ```` is a numeric pixel size (typically 16, 32, 48, 64, 128 or 256). +# ```` 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.49. +# +# ``OUTFILE_BASENAME`` will be used as the basename for the icon file. If +# you specify it, the icon file will be called ``.icns`` on Mac OS X +# and ``.ico`` on Windows. If you don't specify it, it defaults +# to ``.``. Since 5.49. +# +# +# 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. +# * One of the tools png2ico (See :find-module:`FindPng2Ico`) or +# icotool (see :find-module:`FindIcoTool`) is required. +# * Supported sizes: 16, 20, 24, 32, 40, 48, 64, 128, 256, 512 and 1024. +# +# 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 +# Copyright 2014 Ralf Habacker +# Copyright 2006-2009 Alexander Neundorf, +# Copyright 2006, 2007, Laurent Montel, +# Copyright 2007 Matthias Kretz +# +# 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_BASENAME ICON_INDEX DO_NOT_GENERATE_RC_FILE) + set(multiValueArgs ICONS SIDEBAR_ICONS RC_DEPENDENCIES) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (ARG_DO_NOT_GENERATE_RC_FILE) + set (_do_not_generate_rc_file TRUE) + else() + set (_do_not_generate_rc_file FALSE) + endif() + + 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() + + if (WIN32) + _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;20;24;32;40;48;64;128;256;512;1024") + else() + _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024") + endif() + if(ARG_SIDEBAR_ICONS) + _ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256") + 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}) + + set(mac_sidebar_icons + # 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_32px} + ${sidebar_icons_at_64px} + ${sidebar_icons_at_128px} + ${sidebar_icons_at_256px}) + + if (NOT (mac_icons OR mac_sidebar_icons)) + message(AUTHOR_WARNING "No icons suitable for use on macOS provided") + endif() + + + set(windows_icons ${icons_at_16px} + ${icons_at_20px} + ${icons_at_24px} + ${icons_at_32px} + ${icons_at_40px} + ${icons_at_48px} + ${icons_at_64px} + ${icons_at_128px} + ${icons_at_256px} + ${icons_at_512px} + ${icons_at_1024px}) + + if (NOT (windows_icons)) + message(AUTHOR_WARNING "No icons suitable for use on Windows provided") + endif() + + if (ARG_OUTFILE_BASENAME) + set (_outfilebasename "${ARG_OUTFILE_BASENAME}") + else() + set (_outfilebasename "${appsources}") + endif() + set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${_outfilebasename}") + + if (WIN32 AND windows_icons) + 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}" + ) + if (NOT _do_not_generate_rc_file) + # this bit's a little hacky to make the dependency stuff work + file(WRITE "${_outfilename}.rc.in" "IDI_ICON${ARG_ICON_INDEX} ICON DISCARDABLE \"${_outfilename}.ico\"\n") + add_custom_command( + OUTPUT "${_outfilename}.rc" + COMMAND ${CMAKE_COMMAND} + ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc" + DEPENDS ${ARG_RC_DEPENDENCIES} "${_outfilename}.ico" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + endif() + endfunction() + + if (IcoTool_FOUND) + list(APPEND 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 20 24 32 40 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 + # NOTE: We generally use https://github.com/hiiamok/png2ImageMagickICO + # or similar on windows, which is why we provide resolutions >= 256px here. + # Standard png2ico will fail with this. + elseif(Png2Ico_FOUND AND NOT Png2Ico_HAS_RCFILE_ARGUMENT AND windows_icons) + set(png2ico_args) + list(APPEND png2ico_args "${_outfilename}.ico") + list(APPEND png2ico_args "${windows_icons}") + create_windows_icon_and_rc(Png2Ico::Png2Ico "${png2ico_args}" "${windows_icons}") + + set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE) + + # png2ico from kdewin provides rcfile argument + elseif(Png2Ico_FOUND AND windows_icons) + add_custom_command( + OUTPUT "${_outfilename}.rc" "${_outfilename}.ico" + COMMAND Png2Ico::Png2Ico + ARGS + --rcfile "${_outfilename}.rc" + "${_outfilename}.ico" + ${windows_icons} + DEPENDS ${windows_icons} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + 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 OR mac_sidebar_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() + + # List of supported sizes and filenames taken from: + # https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4 + 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() + + # List of supported sizes and filenames taken from: + # https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15 + foreach(file ${sidebar_icons_at_16px}) + copy_icon("${file}" "16x16" "sidebar") + endforeach() + foreach(file ${sidebar_icons_at_32px}) + copy_icon("${file}" "16x16@2x" "sidebar") + endforeach() + foreach(file ${sidebar_icons_at_32px}) + copy_icon("${file}" "18x18" "sidebar") + endforeach() + foreach(file ${sidebar_icons_at_64px}) + copy_icon("${file}" "18x18@2x" "sidebar") + endforeach() + foreach(file ${sidebar_icons_at_128px}) + copy_icon("${file}" "32x32" "sidebar") + endforeach() + foreach(file ${sidebar_icons_at_256px}) + copy_icon("${file}" "32x32@2x" "sidebar") + 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() diff --git a/cmake/modules/ECMCoverageOption.cmake b/cmake/modules/ECMCoverageOption.cmake new file mode 100644 index 000000000..7a96280e9 --- /dev/null +++ b/cmake/modules/ECMCoverageOption.cmake @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez +# +# SPDX-License-Identifier: BSD-3-Clause + +#[=======================================================================[.rst: +ECMCoverageOption +-------------------- + +Allow users to easily enable GCov code coverage support. + +Code coverage allows you to check how much of your codebase is covered by +your tests. This module makes it easy to build with support for +`GCov `_. + +When this module is included, a ``BUILD_COVERAGE`` option is added (default +OFF). Turning this option on enables GCC's coverage instrumentation, and +links against ``libgcov``. + +Note that this will probably break the build if you are not using GCC. + +Since 1.3.0. +#]=======================================================================] + +option(BUILD_COVERAGE "Build the project with gcov support" OFF) + +if(BUILD_COVERAGE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") +endif() diff --git a/cmake/modules/ECMEnableSanitizers.cmake b/cmake/modules/ECMEnableSanitizers.cmake new file mode 100644 index 000000000..b4c1b2b3d --- /dev/null +++ b/cmake/modules/ECMEnableSanitizers.cmake @@ -0,0 +1,169 @@ +# SPDX-FileCopyrightText: 2014 Mathieu Tarral +# +# SPDX-License-Identifier: BSD-3-Clause + +#[=======================================================================[.rst: +ECMEnableSanitizers +------------------- + +Enable compiler sanitizer flags. + +The following sanitizers are supported: + +- Address Sanitizer +- Memory Sanitizer +- Thread Sanitizer +- Leak Sanitizer +- Undefined Behaviour Sanitizer + +All of them are implemented in Clang, depending on your version, and +there is an work in progress in GCC, where some of them are currently +implemented. + +This module will check your current compiler version to see if it +supports the sanitizers that you want to enable + +Usage +===== + +Simply add:: + + include(ECMEnableSanitizers) + +to your ``CMakeLists.txt``. Note that this module is included in +KDECompilerSettings, so projects using that module do not need to also +include this one. + +The sanitizers are not enabled by default. Instead, you must set +``ECM_ENABLE_SANITIZERS`` (either in your ``CMakeLists.txt`` or on the +command line) to a semicolon-separated list of sanitizers you wish to enable. +The options are: + +- address +- memory +- thread +- leak +- undefined +- fuzzer + +The sanitizers "address", "memory" and "thread" are mutually exclusive. You +cannot enable two of them in the same build. + +"leak" requires the "address" sanitizer. + +.. note:: + + To reduce the overhead induced by the instrumentation of the sanitizers, it + is advised to enable compiler optimizations (``-O1`` or higher). + +Example +======= + +This is an example of usage:: + + mkdir build + cd build + cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' .. + +.. note:: + + Most of the sanitizers will require Clang. To enable it, use:: + + -DCMAKE_CXX_COMPILER=clang++ + +Since 1.3.0. +#]=======================================================================] + +# MACRO check_compiler_version +#----------------------------- +macro (check_compiler_version gcc_required_version clang_required_version msvc_required_version) + if ( + ( + CMAKE_CXX_COMPILER_ID MATCHES "GNU" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${gcc_required_version} + ) + OR + ( + CMAKE_CXX_COMPILER_ID MATCHES "Clang" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${clang_required_version} + ) + OR + ( + CMAKE_CXX_COMPILER_ID MATCHES "MSVC" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${msvc_required_version} + ) + ) + # error ! + message(FATAL_ERROR "You ask to enable the sanitizer ${CUR_SANITIZER}, + but your compiler ${CMAKE_CXX_COMPILER_ID} version ${CMAKE_CXX_COMPILER_VERSION} + does not support it ! + You should use at least GCC ${gcc_required_version}, Clang ${clang_required_version} + or MSVC ${msvc_required_version} + (99.99 means not implemented yet)") + endif () +endmacro () + +# MACRO check_compiler_support +#------------------------------ +macro (enable_sanitizer_flags sanitize_option) + if (${sanitize_option} MATCHES "address") + check_compiler_version("4.8" "3.1" "19.28") + if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set(XSAN_COMPILE_FLAGS "-fsanitize=address") + else() + set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") + set(XSAN_LINKER_FLAGS "-fsanitize=address") + endif() + elseif (${sanitize_option} MATCHES "thread") + check_compiler_version("4.8" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=thread") + set(XSAN_LINKER_FLAGS "tsan") + elseif (${sanitize_option} MATCHES "memory") + check_compiler_version("99.99" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=memory") + elseif (${sanitize_option} MATCHES "leak") + check_compiler_version("4.9" "3.4" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=leak") + set(XSAN_LINKER_FLAGS "lsan") + elseif (${sanitize_option} MATCHES "undefined") + check_compiler_version("4.9" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls") + elseif (${sanitize_option} MATCHES "fuzzer") + check_compiler_version("99.99" "6.0" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer") + else () + message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.") + endif () +endmacro () + +if (ECM_ENABLE_SANITIZERS) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # for each element of the ECM_ENABLE_SANITIZERS list + foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} ) + # lowercase filter + string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER) + # check option and enable appropriate flags + enable_sanitizer_flags ( ${CUR_SANITIZER} ) + # TODO: GCC will not link pthread library if enabled ASan + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + link_libraries(${XSAN_LINKER_FLAGS}) + endif() + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + link_libraries(${XSAN_LINKER_FLAGS}) + endif() + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + link_libraries(${XSAN_LINKER_FLAGS}) + endif () + endforeach() + else() + message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \ +but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support") + endif() +endif() diff --git a/cmake/modules/ECMFindModuleHelpers.cmake b/cmake/modules/ECMFindModuleHelpers.cmake new file mode 100644 index 000000000..4e7ca880d --- /dev/null +++ b/cmake/modules/ECMFindModuleHelpers.cmake @@ -0,0 +1,297 @@ +#.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() +# +# 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( +# RESULT_VAR +# KNOWN_COMPONENTS [ [...]] +# [SKIP_DEPENDENCY_HANDLING]) +# +# This macro will populate with a list of components found in +# _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 _FIND_REQUIRED) and call +# return(). +# +# The order of components in 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 +# __component_deps will be checked for dependent components. +# If is listed in _FIND_COMPONENTS, then all its (transitive) +# dependencies will also be added to . +# +# :: +# +# ecm_find_package_handle_library_components( +# COMPONENTS [ [...]] +# [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 __lib variable should contain the name of this library, +# and __header variable should contain the name of a header +# file associated with it (whatever relative path is normally passed to +# '#include'). __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 ::. +# +# Additional variables can be used to provide additional information: +# +# If SKIP_PKG_CONFIG, the __pkg_config variable is set, and +# pkg-config is found, the pkg-config module given by +# __pkg_config will be searched for and used to help locate the +# library and header file. It will also be used to set +# __VERSION. +# +# Note that if version information is found via pkg-config, +# __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 will be set to contain the imported +# targets for the components listed in __component_deps. +# _FOUND will also be set to false if any of the components in +# __component_deps are not found. This requires the components +# in __component_deps to be listed before in the +# COMPONENTS argument. +# +# The following variables will be set: +# +# ``_TARGETS`` +# the imported targets +# ``_LIBRARIES`` +# the found libraries +# ``_INCLUDE_DIRS`` +# the combined required include directories for the components +# ``_DEFINITIONS`` +# the "other" CFLAGS provided by pkg-config, if any +# ``_VERSION`` +# the value of ``__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 +# ``_TARGETS``, for example, will contain all the targets found in any +# call (although no duplicates). +# +# Since pre-1.0.0. + +#============================================================================= +# Copyright 2014 Alex Merry +# +# 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() diff --git a/cmake/modules/ECMFindModuleHelpersStub.cmake b/cmake/modules/ECMFindModuleHelpersStub.cmake new file mode 100644 index 000000000..bb8c9a62f --- /dev/null +++ b/cmake/modules/ECMFindModuleHelpersStub.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/../modules/ECMFindModuleHelpers.cmake) diff --git a/cmake/modules/FindCMocka.cmake b/cmake/modules/FindCMocka.cmake new file mode 100644 index 000000000..65a13a76d --- /dev/null +++ b/cmake/modules/FindCMocka.cmake @@ -0,0 +1,49 @@ +# - Try to find CMocka +# Once done this will define +# +# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka +# +# Read-Only variables: +# CMOCKA_FOUND - system has CMocka +# CMOCKA_INCLUDE_DIR - the CMocka include directory +# CMOCKA_LIBRARIES - Link these to use CMocka +# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka +# +#============================================================================= +# Copyright (c) 2011-2012 Andreas Schneider +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# + +find_path(CMOCKA_INCLUDE_DIR + NAMES + cmocka.h + PATHS + ${CMOCKA_ROOT_DIR}/include +) + +find_library(CMOCKA_LIBRARY + NAMES + cmocka + PATHS + ${CMOCKA_ROOT_DIR}/lib +) + +if (CMOCKA_LIBRARY) + set(CMOCKA_LIBRARIES + ${CMOCKA_LIBRARIES} + ${CMOCKA_LIBRARY} + ) +endif (CMOCKA_LIBRARY) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR) + +# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view +mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES) diff --git a/cmake/modules/FindInotify.cmake b/cmake/modules/FindInotify.cmake new file mode 100644 index 000000000..8b0f8510c --- /dev/null +++ b/cmake/modules/FindInotify.cmake @@ -0,0 +1,62 @@ +#.rst: +# FindInotify +# -------------- +# +# Try to find inotify on this system. This finds: +# - libinotify on Unix like systems, or +# - the kernel's inotify on Linux systems. +# +# This will define the following variables: +# +# ``Inotify_FOUND`` +# True if inotify is available +# ``Inotify_LIBRARIES`` +# This has to be passed to target_link_libraries() +# ``Inotify_INCLUDE_DIRS`` +# This has to be passed to target_include_directories() +# +# On Linux, the libraries and include directories are empty, +# even though ``Inotify_FOUND`` may be set to TRUE. This is because +# no special includes or libraries are needed. On other systems +# these may be needed to use inotify. +# +# Since 5.32.0. + +#============================================================================= +# SPDX-FileCopyrightText: 2016 Tobias C. Berner +# SPDX-FileCopyrightText: 2017 Adriaan de Groot +# +# SPDX-License-Identifier: BSD-2-Clause +#============================================================================= + +find_path(Inotify_INCLUDE_DIRS sys/inotify.h) + +if(Inotify_INCLUDE_DIRS) +# On Linux there is no library to link against, on the BSDs there is. +# On the BSD's, inotify is implemented through a library, libinotify. + if( CMAKE_SYSTEM_NAME MATCHES "Linux") + set(Inotify_FOUND TRUE) + set(Inotify_LIBRARIES "") + set(Inotify_INCLUDE_DIRS "") + else() + find_library(Inotify_LIBRARIES NAMES inotify) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Inotify + FOUND_VAR + Inotify_FOUND + REQUIRED_VARS + Inotify_LIBRARIES + Inotify_INCLUDE_DIRS + ) + mark_as_advanced(Inotify_LIBRARIES Inotify_INCLUDE_DIRS) + include(FeatureSummary) + set_package_properties(Inotify PROPERTIES + URL "https://github.com/libinotify-kqueue/" + DESCRIPTION "inotify API on the *BSD family of operating systems." + ) + endif() +else() + set(Inotify_FOUND FALSE) +endif() + +mark_as_advanced(Inotify_LIBRARIES Inotify_INCLUDE_DIRS) diff --git a/cmake/modules/FindLibSSH.cmake b/cmake/modules/FindLibSSH.cmake new file mode 100644 index 000000000..94dbf762b --- /dev/null +++ b/cmake/modules/FindLibSSH.cmake @@ -0,0 +1,96 @@ +# - Try to find LibSSH +# Once done this will define +# +# LIBSSH_FOUND - system has LibSSH +# LIBSSH_INCLUDE_DIRS - the LibSSH include directory +# LIBSSH_LIBRARIES - Link these to use LibSSH +# LIBSSH_DEFINITIONS - Compiler switches required for using LibSSH +# +# Copyright (c) 2009 Andreas Schneider +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +if (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS) + # in cache already + set(LIBSSH_FOUND TRUE) +else (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS) + + find_path(LIBSSH_INCLUDE_DIR + NAMES + libssh/libssh.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ${CMAKE_INCLUDE_PATH} + ${CMAKE_INSTALL_PREFIX}/include + ) + + find_library(SSH_LIBRARY + NAMES + ssh + libssh + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ${CMAKE_LIBRARY_PATH} + ${CMAKE_INSTALL_PREFIX}/lib + ) + + if (LIBSSH_INCLUDE_DIR AND SSH_LIBRARY) + set(SSH_FOUND TRUE) + endif (LIBSSH_INCLUDE_DIR AND SSH_LIBRARY) + + set(LIBSSH_INCLUDE_DIRS + ${LIBSSH_INCLUDE_DIR} + ) + + if (SSH_FOUND) + set(LIBSSH_LIBRARIES + ${LIBSSH_LIBRARIES} + ${SSH_LIBRARY} + ) + + if (LibSSH_FIND_VERSION) + file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MAJOR + REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+") + # Older versions of libssh like libssh-0.2 have LIBSSH_VERSION but not LIBSSH_VERSION_MAJOR + if (LIBSSH_VERSION_MAJOR) + string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR}) + file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MINOR + REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+") + string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR}) + file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_PATCH + REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+") + string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH}) + + set(LibSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH}) + + include(FindPackageVersionCheck) + find_package_version_check(LibSSH DEFAULT_MSG) + else (LIBSSH_VERSION_MAJOR) + message(STATUS "LIBSSH_VERSION_MAJOR not found in ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h, assuming libssh is too old") + set(LIBSSH_FOUND FALSE) + endif (LIBSSH_VERSION_MAJOR) + endif (LibSSH_FIND_VERSION) + endif (SSH_FOUND) + + # If the version is too old, but libs and includes are set, + # find_package_handle_standard_args will set LIBSSH_FOUND to TRUE again, + # so we need this if() here. + if (LIBSSH_FOUND) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(LibSSH DEFAULT_MSG LIBSSH_LIBRARIES LIBSSH_INCLUDE_DIRS) + endif (LIBSSH_FOUND) + + # show the LIBSSH_INCLUDE_DIRS and LIBSSH_LIBRARIES variables only in the advanced view + mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES) + +endif (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS) + diff --git a/cmake/modules/FindPackageVersionCheck.cmake b/cmake/modules/FindPackageVersionCheck.cmake new file mode 100644 index 000000000..7c026f362 --- /dev/null +++ b/cmake/modules/FindPackageVersionCheck.cmake @@ -0,0 +1,72 @@ +# (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. + +# FIND_PACKAGE_VERSION_CHECK(NAME (DEFAULT_MSG|"Custom failure message")) +# This function is intended to be used in FindXXX.cmake modules files. +# It handles NAME_FIND_VERSION and NAME_VERSION variables in a Module. +# +# Example: +# find_package(LibSSH 0.3.2) +# +# # check for the version and set it +# set(LibSSH_VERSION 0.3.0) +# find_package_version_check(LibSSH DEFAULT_MSG) +# +# +# Copyright (c) 2009 Andreas Schneider +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. + +function(FIND_PACKAGE_VERSION_CHECK _NAME _FAIL_MSG) + string(TOUPPER ${_NAME} _NAME_UPPER) + set(_AGE "old") + + if(${_NAME}_FIND_VERSION_EXACT) + if (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION) + # exact version found + set(${_NAME_UPPER}_FOUND TRUE) + else (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION) + # exect version not found + set(${_NAME_UPPER}_FOUND FALSE) + # check if newer or older + if (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION) + set(_AGE "new") + else (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION) + set(_AGE "old") + endif (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION) + endif (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION) + else (${_NAME}_FIND_VERSION_EXACT) + if (${_NAME}_FIND_VERSION) + if (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION) + set(${_NAME_UPPER}_FOUND FALSE) + set(_AGE "old") + else (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION) + set(${_NAME_UPPER}_FOUND TRUE) + endif (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION) + endif (${_NAME}_FIND_VERSION) + endif(${_NAME}_FIND_VERSION_EXACT) + + if ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") + if (${_NAME}_FIND_VERSION_EXACT) + set(_FAIL_MESSAGE "The installed ${_NAME} version ${${_NAME}_VERSION} is too ${_AGE}, version ${${_NAME}_FIND_VERSION} is required.") + else (${_NAME}_FIND_VERSION_EXACT) + set(_FAIL_MESSAGE "The installed ${_NAME} version ${${_NAME}_VERSION} is too ${_AGE}, at least version ${${_NAME}_FIND_VERSION} is required.") + endif (${_NAME}_FIND_VERSION_EXACT) + else ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") + set(_FAIL_MESSAGE "${_FAIL_MSG}") + endif ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") + + if (NOT ${_NAME_UPPER}_FOUND) + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_FAIL_MESSAGE}") + else (${_NAME}_FIND_REQUIRED) + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_FAIL_MESSAGE}") + endif (NOT ${_NAME}_FIND_QUIETLY) + endif (${_NAME}_FIND_REQUIRED) + endif (NOT ${_NAME_UPPER}_FOUND) + + set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) +endfunction(FIND_PACKAGE_VERSION_CHECK) diff --git a/cmake/modules/FindPdfLatex.cmake b/cmake/modules/FindPdfLatex.cmake new file mode 100644 index 000000000..82fb8c659 --- /dev/null +++ b/cmake/modules/FindPdfLatex.cmake @@ -0,0 +1,20 @@ +# (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. + +find_program(PDFLATEX_EXECUTABLE NAMES pdflatex + HINTS + $ENV{PDFLATEX_DIR} + PATH_SUFFIXES bin + DOC "PDF LaTeX" +) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(PdfLatex DEFAULT_MSG + PDFLATEX_EXECUTABLE +) + +mark_as_advanced( + PDFLATEX_EXECUTABLE +) diff --git a/cmake/modules/FindPng2Ico.cmake b/cmake/modules/FindPng2Ico.cmake new file mode 100644 index 000000000..d84f66730 --- /dev/null +++ b/cmake/modules/FindPng2Ico.cmake @@ -0,0 +1,117 @@ +#.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 `_ does, while the +# version of png2ico from the `"KDE On Windows" (kdewin) +# `_ project does not. +# +# ``Png2Ico_HAS_RCFILE_ARGUMENT`` +# Whether png2ico accepts an ``--rcfile`` argument. The version of png2ico +# from the `"KDE On Windows" (kdewin) +# `_ project does, +# while `Matthias Benkmann's tool +# `_ does not. +# +# Since 1.7.0. + +#============================================================================= +# Copyright 2014 Alex Merry +# +# 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" +) + diff --git a/cmake/modules/FindSMBClient.cmake b/cmake/modules/FindSMBClient.cmake new file mode 100644 index 000000000..730498edd --- /dev/null +++ b/cmake/modules/FindSMBClient.cmake @@ -0,0 +1,66 @@ +# - Try to find SMBClient +# Once done this will define +# +# SMBCLIENT_FOUND - system has SMBClient +# SMBCLIENT_INCLUDE_DIRS - the SMBClient include directory +# SMBCLIENT_LIBRARIES - Link these to use SMBClient +# SMBCLIENT_DEFINITIONS - Compiler switches required for using SMBClient +# +# Copyright (c) 2013 Andreas Schneider +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +if (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS) + # in cache already + set(SMBCLIENT_FOUND TRUE) +else (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(_SMBCLIENT smbclient) + endif (PKG_CONFIG_FOUND) + + find_path(SMBCLIENT_INCLUDE_DIR + NAMES + libsmbclient.h + PATHS + ${_SMBCLIENT_INCLUDEDIR} + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ) + + find_library(SMBCLIENT_LIBRARY + NAMES + smbclient + PATHS + ${_SMBCLIENT_LIBDIR} + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ) + + set(SMBCLIENT_INCLUDE_DIRS + ${SMBCLIENT_INCLUDE_DIR} + ) + + if (SMBCLIENT_LIBRARY) + set(SMBCLIENT_LIBRARIES + ${SMBCLIENT_LIBRARIES} + ${SMBCLIENT_LIBRARY} + ) + endif (SMBCLIENT_LIBRARY) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(SMBClient DEFAULT_MSG SMBCLIENT_LIBRARIES SMBCLIENT_INCLUDE_DIRS) + + # show the SMBCLIENT_INCLUDE_DIRS and SMBCLIENT_LIBRARIES variables only in the advanced view + mark_as_advanced(SMBCLIENT_INCLUDE_DIRS SMBCLIENT_LIBRARIES) + +endif (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS) + diff --git a/cmake/modules/FindSQLite3.cmake b/cmake/modules/FindSQLite3.cmake new file mode 100644 index 000000000..f135c5d64 --- /dev/null +++ b/cmake/modules/FindSQLite3.cmake @@ -0,0 +1,68 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindSQLite3 +----------- + +.. versionadded:: 3.14 + +Find the SQLite libraries, v3 + +IMPORTED targets +^^^^^^^^^^^^^^^^ + +This module defines the following :prop_tgt:`IMPORTED` target: + +``SQLite::SQLite3`` + +Result variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables if found: + +``SQLite3_INCLUDE_DIRS`` + where to find sqlite3.h, etc. +``SQLite3_LIBRARIES`` + the libraries to link against to use SQLite3. +``SQLite3_VERSION`` + version of the SQLite3 library found +``SQLite3_FOUND`` + TRUE if found + +#]=======================================================================] + +# Look for the necessary header +find_path(SQLite3_INCLUDE_DIR NAMES sqlite3.h) +mark_as_advanced(SQLite3_INCLUDE_DIR) + +# Look for the necessary library +find_library(SQLite3_LIBRARY NAMES sqlite3 sqlite) +mark_as_advanced(SQLite3_LIBRARY) + +# Extract version information from the header file +if(SQLite3_INCLUDE_DIR) + file(STRINGS ${SQLite3_INCLUDE_DIR}/sqlite3.h _ver_line + REGEX "^#define SQLITE_VERSION *\"[0-9]+\\.[0-9]+\\.[0-9]+\"" + LIMIT_COUNT 1) + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" + SQLite3_VERSION "${_ver_line}") + unset(_ver_line) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SQLite3 + REQUIRED_VARS SQLite3_INCLUDE_DIR SQLite3_LIBRARY + VERSION_VAR SQLite3_VERSION) + +# Create the imported target +if(SQLite3_FOUND) + set(SQLite3_INCLUDE_DIRS ${SQLite3_INCLUDE_DIR}) + set(SQLite3_LIBRARIES ${SQLite3_LIBRARY}) + if(NOT TARGET SQLite::SQLite3) + add_library(SQLite::SQLite3 UNKNOWN IMPORTED) + set_target_properties(SQLite::SQLite3 PROPERTIES + IMPORTED_LOCATION "${SQLite3_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIR}") + endif() +endif() diff --git a/cmake/modules/FindSharedMimeInfo.cmake b/cmake/modules/FindSharedMimeInfo.cmake new file mode 100644 index 000000000..0b8dec9c0 --- /dev/null +++ b/cmake/modules/FindSharedMimeInfo.cmake @@ -0,0 +1,93 @@ +#.rst: +# FindSharedMimeInfo +# ------------------ +# +# Try to find the shared-mime-info package. +# +# This will define the following variables: +# +# ``SharedMimeInfo_FOUND`` +# True if system has the shared-mime-info package +# ``UPDATE_MIME_DATABASE_EXECUTABLE`` +# The update-mime-database executable +# +# and the following imported targets: +# +# ``SharedMimeInfo::UpdateMimeDatabase`` +# The update-mime-database executable +# +# The follow macro is available:: +# +# update_xdg_mimetypes() +# +# Updates the XDG mime database at install time (unless the ``$DESTDIR`` +# environment variable is set, in which case it is up to package managers to +# perform this task). +# +# Since pre-1.0.0. + +#============================================================================= +# SPDX-FileCopyrightText: 2013-2014 Alex Merry +# SPDX-FileCopyrightText: 2007 Pino Toscano +# +# SPDX-License-Identifier: BSD-3-Clause +#============================================================================= + +include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake) + +ecm_find_package_version_check(SharedMimeInfo) + +find_program (UPDATE_MIME_DATABASE_EXECUTABLE NAMES update-mime-database) + +if (UPDATE_MIME_DATABASE_EXECUTABLE) + execute_process( + COMMAND "${UPDATE_MIME_DATABASE_EXECUTABLE}" -v + OUTPUT_VARIABLE _smiVersionRaw + ERROR_VARIABLE _smiVersionRaw) + + string(REGEX REPLACE "update-mime-database \\([a-zA-Z\\-]+\\) ([0-9]\\.[0-9]+).*" + "\\1" SharedMimeInfo_VERSION_STRING "${_smiVersionRaw}") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SharedMimeInfo + FOUND_VAR + SharedMimeInfo_FOUND + REQUIRED_VARS + UPDATE_MIME_DATABASE_EXECUTABLE + VERSION_VAR + SharedMimeInfo_VERSION_STRING) + +if(SharedMimeInfo_FOUND AND NOT TARGET SharedMimeInfo::UpdateMimeDatabase) + add_executable(SharedMimeInfo::UpdateMimeDatabase IMPORTED) + set_target_properties(SharedMimeInfo::UpdateMimeDatabase PROPERTIES + IMPORTED_LOCATION "${UPDATE_MIME_DATABASE_EXECUTABLE}" + ) +endif() + +mark_as_advanced(UPDATE_MIME_DATABASE_EXECUTABLE) + +function(UPDATE_XDG_MIMETYPES _path) + get_filename_component(_xdgmimeDir "${_path}" NAME) + if("${_xdgmimeDir}" STREQUAL packages ) + get_filename_component(_xdgmimeDir "${_path}" PATH) + else() + set(_xdgmimeDir "${_path}") + endif() + + # Note that targets and most variables are not available to install code + install(CODE " +set(DESTDIR_VALUE \"\$ENV{DESTDIR}\") +if (NOT DESTDIR_VALUE) + # under Windows relative paths are used, that's why it runs from CMAKE_INSTALL_PREFIX + message(STATUS \"Updating MIME database at \${CMAKE_INSTALL_PREFIX}/${_xdgmimeDir}\") + execute_process(COMMAND \"${UPDATE_MIME_DATABASE_EXECUTABLE}\" -n \"${_xdgmimeDir}\" + WORKING_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}\") +endif (NOT DESTDIR_VALUE) +") +endfunction() + +include(FeatureSummary) +set_package_properties(SharedMimeInfo PROPERTIES + URL https://freedesktop.org/wiki/Software/shared-mime-info/ + DESCRIPTION "A database of common MIME types") diff --git a/cmake/modules/FindSparkle.cmake b/cmake/modules/FindSparkle.cmake new file mode 100644 index 000000000..2b0c75b95 --- /dev/null +++ b/cmake/modules/FindSparkle.cmake @@ -0,0 +1,21 @@ +# Find Sparkle.framework +# +# Once done this will define +# SPARKLE_FOUND - system has Sparkle +# SPARKLE_LIBRARY - The framework needed to use Sparkle +# Copyright (c) 2009, Vittorio Giovara +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. + +include(FindPackageHandleStandardArgs) + +find_library(SPARKLE_LIBRARY NAMES Sparkle) + +find_package_handle_standard_args(Sparkle DEFAULT_MSG SPARKLE_LIBRARY) +mark_as_advanced(SPARKLE_LIBRARY) + diff --git a/cmake/modules/FindSphinx.cmake b/cmake/modules/FindSphinx.cmake new file mode 100644 index 000000000..953f626a5 --- /dev/null +++ b/cmake/modules/FindSphinx.cmake @@ -0,0 +1,20 @@ +# (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. + +find_program(SPHINX_EXECUTABLE NAMES sphinx-build + HINTS + $ENV{SPHINX_DIR} + PATH_SUFFIXES bin + DOC "Sphinx documentation generator" +) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Sphinx DEFAULT_MSG + SPHINX_EXECUTABLE +) + +mark_as_advanced( + SPHINX_EXECUTABLE +) diff --git a/cmake/modules/GenerateIconsUtils.cmake b/cmake/modules/GenerateIconsUtils.cmake new file mode 100644 index 000000000..e37b04cfe --- /dev/null +++ b/cmake/modules/GenerateIconsUtils.cmake @@ -0,0 +1,58 @@ +# UPSTREAM our ECMAddAppIcon.cmake then require that version here +# find_package(ECM 1.7.0 REQUIRED NO_MODULE) +# list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) +include(ECMAddAppIcon) + +find_program(SVG_CONVERTER + NAMES inkscape inkscape.exe rsvg-convert + REQUIRED + HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV SVG_CONVERTER_DIR) +# REQUIRED keyword is only supported on CMake 3.18 and above +if (NOT SVG_CONVERTER) + message(FATAL_ERROR "Could not find a suitable svg converter. Set SVG_CONVERTER_DIR to the path of either the inkscape or rsvg-convert executable.") +endif() + +function(generate_sized_png_from_svg icon_path size) + set(options) + set(oneValueArgs OUTPUT_ICON_NAME OUTPUT_ICON_FULL_NAME_WLE OUTPUT_ICON_PATH) + set(multiValueArgs) + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + get_filename_component(icon_name_dir ${icon_path} DIRECTORY) + get_filename_component(icon_name_wle ${icon_path} NAME_WLE) + + if (ARG_OUTPUT_ICON_NAME) + set(icon_name_wle ${ARG_OUTPUT_ICON_NAME}) + endif () + + if (ARG_OUTPUT_ICON_PATH) + set(icon_name_dir ${ARG_OUTPUT_ICON_PATH}) + endif () + + set(output_icon_full_name_wle "${size}-${icon_name_wle}") + + if (ARG_OUTPUT_ICON_FULL_NAME_WLE) + set(output_icon_full_name_wle ${ARG_OUTPUT_ICON_FULL_NAME_WLE}) + endif () + + if (EXISTS "${icon_name_dir}/${output_icon_full_name_wle}.png") + return() + endif() + + set(icon_output_name "${output_icon_full_name_wle}.png") + message(STATUS "Generate ${icon_output_name}") + execute_process(COMMAND + "${SVG_CONVERTER}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}" + WORKING_DIRECTORY "${icon_name_dir}" + RESULT_VARIABLE + SVG_CONVERTER_SIDEBAR_ERROR + OUTPUT_QUIET + ERROR_QUIET) + + if (SVG_CONVERTER_SIDEBAR_ERROR) + message(FATAL_ERROR + "${SVG_CONVERTER} could not generate icon: ${SVG_CONVERTER_SIDEBAR_ERROR}") + else() + endif() +endfunction() diff --git a/cmake/modules/GetGitRevisionDescription.cmake b/cmake/modules/GetGitRevisionDescription.cmake new file mode 100644 index 000000000..1f9005b69 --- /dev/null +++ b/cmake/modules/GetGitRevisionDescription.cmake @@ -0,0 +1,116 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_DIR "${PROJECT_SOURCE_DIR}/.git") + if (NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/GetGitRevisionDescription.cmake.in b/cmake/modules/GetGitRevisionDescription.cmake.in new file mode 100644 index 000000000..888ce13aa --- /dev/null +++ b/cmake/modules/GetGitRevisionDescription.cmake.in @@ -0,0 +1,38 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") + configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + set(HEAD_HASH "${HEAD_REF}") + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in new file mode 100644 index 000000000..4e79cc740 --- /dev/null +++ b/cmake/modules/MacOSXBundleInfo.plist.in @@ -0,0 +1,92 @@ + + + + + NSPrincipalClass + NSApplication + LSMinimumSystemVersion + 11.0 + LSUIElement + + CFBundleDevelopmentRegion + English + CFBundleExecutable + @APPLICATION_NAME@ + CFBundleIconFile + @APPLICATION_ICON_NAME@.icns + CFBundleIdentifier + @APPLICATION_REV_DOMAIN@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + @APPLICATION_NAME_XML_ESCAPED@ @MIRALL_VERSION_STRING@ + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + @MIRALL_VERSION_FULL@ + CFBundleShortVersionString + @MIRALL_VERSION_STRING@ + NSHumanReadableCopyright + (C) 2014-2024 @APPLICATION_VENDOR_XML_ESCAPED@ + NSSupportsAutomaticGraphicsSwitching + + NSRequiresAquaSystemAppearance + + SUShowReleaseNotes + + SUPublicDSAKeyFile + dsa_pub.pem + SUPublicEDKey + c3RcfDWDayvsYSZW8FhZN1UOJhvPVN30zleb4zOqbtU= + +UTExportedTypeDeclarations + + + UTTypeIdentifier + @APPLICATION_REV_DOMAIN@.VIRTUALFILE + UTTypeTagSpecification + + public.filename-extension + @APPLICATION_VIRTUALFILE_SUFFIX@ + public.mime-type + application/octet-stream + + UTTypeConformsTo + + public.data + + + + +CFBundleDocumentTypes + + + CFBundleTypeName + @APPLICATION_EXECUTABLE@ Download Virtual File + CFBundleTypeRole + Editor + LSHandlerRank + Owner + LSItemContentTypes + + @APPLICATION_REV_DOMAIN@.VIRTUALFILE + + + + +CFBundleURLTypes + + + CFBundleURLName + @APPLICATION_NAME@ Edit Locally + CFBundleURLSchemes + + @APPLICATION_URI_HANDLER_SCHEME@ + + + + + + diff --git a/cmake/modules/MacroAddCompileFlags.cmake b/cmake/modules/MacroAddCompileFlags.cmake new file mode 100644 index 000000000..8c5129609 --- /dev/null +++ b/cmake/modules/MacroAddCompileFlags.cmake @@ -0,0 +1,21 @@ +# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN) + +# Copyright (c) 2006, Oswald Buddenhagen, +# Copyright (c) 2006, Andreas Schneider, +# +# 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_COMPILE_FLAGS _target) + + get_target_property(_flags ${_target} COMPILE_FLAGS) + if (_flags) + set(_flags ${_flags} ${ARGN}) + else (_flags) + set(_flags ${ARGN}) + endif (_flags) + + set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags}) + +endmacro (MACRO_ADD_COMPILE_FLAGS) diff --git a/cmake/modules/MacroAddLinkFlags.cmake b/cmake/modules/MacroAddLinkFlags.cmake new file mode 100644 index 000000000..eaef15401 --- /dev/null +++ b/cmake/modules/MacroAddLinkFlags.cmake @@ -0,0 +1,20 @@ +# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN) + +# Copyright (c) 2006, Oswald Buddenhagen, +# Copyright (c) 2006, Andreas Schneider, +# +# 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_LINK_FLAGS _target) + + get_target_property(_flags ${_target} LINK_FLAGS) + if (_flags) + set(_flags "${_flags} ${ARGN}") + else (_flags) + set(_flags "${ARGN}") + endif (_flags) + + set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}") + +endmacro (MACRO_ADD_LINK_FLAGS) diff --git a/cmake/modules/MacroEnsureOutOfSourceBuild.cmake b/cmake/modules/MacroEnsureOutOfSourceBuild.cmake new file mode 100644 index 000000000..a2e948099 --- /dev/null +++ b/cmake/modules/MacroEnsureOutOfSourceBuild.cmake @@ -0,0 +1,17 @@ +# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() +# MACRO_ENSURE_OUT_OF_SOURCE_BUILD() + +# Copyright (c) 2006, Alexander Neundorf, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) + + string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) + if (_insource) + message(SEND_ERROR "${_errorMessage}") + message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") + endif (_insource) + +endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) diff --git a/cmake/modules/MacroLogFeature.cmake b/cmake/modules/MacroLogFeature.cmake new file mode 100644 index 000000000..631c7ac02 --- /dev/null +++ b/cmake/modules/MacroLogFeature.cmake @@ -0,0 +1,157 @@ +# This file defines the Feature Logging macros. +# +# MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]]) +# Logs the information so that it can be displayed at the end +# of the configure run +# VAR : TRUE or FALSE, indicating whether the feature is supported +# FEATURE: name of the feature, e.g. "libjpeg" +# DESCRIPTION: description what this feature provides +# URL: home page +# REQUIRED: TRUE or FALSE, indicating whether the feature is required +# MIN_VERSION: minimum version number. empty string if unneeded +# COMMENTS: More info you may want to provide. empty string if unnecessary +# +# MACRO_DISPLAY_FEATURE_LOG() +# Call this to display the collected results. +# Exits CMake with a FATAL error message if a required feature is missing +# +# Example: +# +# INCLUDE(MacroLogFeature) +# +# FIND_PACKAGE(JPEG) +# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "") +# ... +# MACRO_DISPLAY_FEATURE_LOG() + +# Copyright (c) 2006, Alexander Neundorf, +# Copyright (c) 2006, Allen Winter, +# Copyright (c) 2009, Sebastian Trueg, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (NOT _macroLogFeatureAlreadyIncluded) + SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_macroLogFeatureAlreadyIncluded TRUE) + + INCLUDE(FeatureSummary) + +ENDIF (NOT _macroLogFeatureAlreadyIncluded) + + +MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments) + + STRING(TOUPPER "${ARGV4}" _required) + SET(_minvers "${ARGV5}") + SET(_comments "${ARGV6}") + + IF (${_var}) + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + ELSE (${_var}) + IF ("${_required}" STREQUAL "TRUE") + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + ELSE ("${_required}" STREQUAL "TRUE") + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + ENDIF ("${_required}" STREQUAL "TRUE") + ENDIF (${_var}) + + SET(_logtext " * ${_package}") + + IF (NOT ${_var}) + IF (${_minvers} MATCHES ".*") + SET(_logtext "${_logtext} (${_minvers} or higher)") + ENDIF (${_minvers} MATCHES ".*") + SET(_logtext "${_logtext} <${_url}>\n ") + ELSE (NOT ${_var}) + SET(_logtext "${_logtext} - ") + ENDIF (NOT ${_var}) + + SET(_logtext "${_logtext}${_description}") + + IF (NOT ${_var}) + IF (${_comments} MATCHES ".*") + SET(_logtext "${_logtext}\n ${_comments}") + ENDIF (${_comments} MATCHES ".*") +# SET(_logtext "${_logtext}\n") #double-space missing features? + ENDIF (NOT ${_var}) + + FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n") + + IF(COMMAND SET_PACKAGE_INFO) # in FeatureSummary.cmake since CMake 2.8.3 + SET_PACKAGE_INFO("${_package}" "\"${_description}\"" "${_url}" "\"${_comments}\"") + ENDIF(COMMAND SET_PACKAGE_INFO) + +ENDMACRO(MACRO_LOG_FEATURE) + + +MACRO(MACRO_DISPLAY_FEATURE_LOG) + IF(COMMAND FEATURE_SUMMARY) # in FeatureSummary.cmake since CMake 2.8.3 + FEATURE_SUMMARY(FILENAME ${CMAKE_CURRENT_BINARY_DIR}/FindPackageLog.txt + WHAT ALL) + ENDIF(COMMAND FEATURE_SUMMARY) + + SET(_missingFile ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + SET(_enabledFile ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + SET(_disabledFile ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + + IF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile}) + SET(_printSummary TRUE) + ENDIF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile}) + + IF(_printSummary) + SET(_missingDeps 0) + IF (EXISTS ${_enabledFile}) + FILE(READ ${_enabledFile} _enabled) + FILE(REMOVE ${_enabledFile}) + SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n-----------------------------------------------------------------------------\n${_enabled}") + ENDIF (EXISTS ${_enabledFile}) + + + IF (EXISTS ${_disabledFile}) + SET(_missingDeps 1) + FILE(READ ${_disabledFile} _disabled) + FILE(REMOVE ${_disabledFile}) + SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n-----------------------------------------------------------------------------\n${_disabled}") + ENDIF (EXISTS ${_disabledFile}) + + + IF (EXISTS ${_missingFile}) + SET(_missingDeps 1) + FILE(READ ${_missingFile} _requirements) + SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- You must install these packages before continuing.\n-----------------------------------------------------------------------------\n${_requirements}") + FILE(REMOVE ${_missingFile}) + SET(_haveMissingReq 1) + ENDIF (EXISTS ${_missingFile}) + + + IF (NOT ${_missingDeps}) + SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- Congratulations! All external packages have been found.") + ENDIF (NOT ${_missingDeps}) + + + MESSAGE(${_summary}) + MESSAGE("-----------------------------------------------------------------------------\n") + + + IF(_haveMissingReq) + MESSAGE(FATAL_ERROR "Exiting: Missing Requirements") + ENDIF(_haveMissingReq) + + ENDIF(_printSummary) + +ENDMACRO(MACRO_DISPLAY_FEATURE_LOG) diff --git a/cmake/modules/MacroOptionalFindPackage.cmake b/cmake/modules/MacroOptionalFindPackage.cmake new file mode 100644 index 000000000..a066bc781 --- /dev/null +++ b/cmake/modules/MacroOptionalFindPackage.cmake @@ -0,0 +1,47 @@ +# - MACRO_OPTIONAL_FIND_PACKAGE() combines FIND_PACKAGE() with an OPTION() +# MACRO_OPTIONAL_FIND_PACKAGE( [QUIT] ) +# This macro is a combination of OPTION() and FIND_PACKAGE(), it +# works like FIND_PACKAGE(), but additionally it automatically creates +# an option name WITH_, which can be disabled via the cmake GUI. +# or via -DWITH_=OFF +# The standard _FOUND variables can be used in the same way +# as when using the normal FIND_PACKAGE() + +# Copyright (c) 2006-2010 Alexander Neundorf, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +# This is just a helper macro to set a bunch of variables empty. +# We don't know whether the package uses UPPERCASENAME or CamelCaseName, so we try both: +macro(_MOFP_SET_EMPTY_IF_DEFINED _name _var) + if(DEFINED ${_name}_${_var}) + set(${_name}_${_var} "") + endif(DEFINED ${_name}_${_var}) + + string(TOUPPER ${_name} _nameUpper) + if(DEFINED ${_nameUpper}_${_var}) + set(${_nameUpper}_${_var} "") + endif(DEFINED ${_nameUpper}_${_var}) +endmacro(_MOFP_SET_EMPTY_IF_DEFINED _package _var) + + +macro (MACRO_OPTIONAL_FIND_PACKAGE _name ) + option(WITH_${_name} "Search for ${_name} package" ON) + if (WITH_${_name}) + find_package(${_name} ${ARGN}) + else (WITH_${_name}) + string(TOUPPER ${_name} _nameUpper) + set(${_name}_FOUND FALSE) + set(${_nameUpper}_FOUND FALSE) + + _mofp_set_empty_if_defined(${_name} INCLUDE_DIRS) + _mofp_set_empty_if_defined(${_name} INCLUDE_DIR) + _mofp_set_empty_if_defined(${_name} INCLUDES) + _mofp_set_empty_if_defined(${_name} LIBRARY) + _mofp_set_empty_if_defined(${_name} LIBRARIES) + _mofp_set_empty_if_defined(${_name} LIBS) + _mofp_set_empty_if_defined(${_name} FLAGS) + _mofp_set_empty_if_defined(${_name} DEFINITIONS) + endif (WITH_${_name}) +endmacro (MACRO_OPTIONAL_FIND_PACKAGE) diff --git a/cmake/modules/NSIS.InstallOptions.ini.in b/cmake/modules/NSIS.InstallOptions.ini.in new file mode 100644 index 000000000..566c0b47d --- /dev/null +++ b/cmake/modules/NSIS.InstallOptions.ini.in @@ -0,0 +1,24 @@ +[Settings] +NumFields=3 + +[Field 1] +Type=Label +Left=0 +Right=-1 +Top=0 +Bottom=24 + +[Field 2] +Type=RadioButton +Left=30 +Right=-1 +Top=50 +Bottom=58 +State=1 + +[Field 3] +Type=RadioButton +Left=30 +Right=-1 +Top=70 +Bottom=78 diff --git a/cmake/modules/NSIS.template.in b/cmake/modules/NSIS.template.in new file mode 100644 index 000000000..6a02525f8 --- /dev/null +++ b/cmake/modules/NSIS.template.in @@ -0,0 +1,881 @@ +;ownCloud installer script. + +!define APPLICATION_SHORTNAME "@APPLICATION_EXECUTABLE@" +!define APPLICATION_NAME "@APPLICATION_NAME@" +!define APPLICATION_VENDOR "@APPLICATION_VENDOR@" +!define APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@.exe" +!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@" + +;----------------------------------------------------------------------------- +; Some installer script options (comment-out options not required) +;----------------------------------------------------------------------------- +!if "@APPLICATION_LICENSE@" != "" + !define OPTION_LICENSE_AGREEMENT +!endif +!define OPTION_UAC_PLUGIN_ENHANCED +!define OPTION_SECTION_SC_SHELL_EXT +!define OPTION_SECTION_SC_START_MENU +!define OPTION_SECTION_SC_DESKTOP +!define OPTION_SECTION_SC_QUICK_LAUNCH +!define OPTION_FINISHPAGE +!define OPTION_FINISHPAGE_LAUNCHER +; !define OPTION_FINISHPAGE_RELEASE_NOTES + +;----------------------------------------------------------------------------- +; Some paths. +;----------------------------------------------------------------------------- +!ifndef MING_PATH + !define MING_PATH "/usr/i686-w64-mingw32/sys-root/mingw" +!endif +!define MING_BIN "${MING_PATH}/bin" +!define MING_LIB "${MING_PATH}/lib" +!define MING_SHARE "${MING_PATH}/share" +!define BUILD_PATH "@CMAKE_BINARY_DIR@" +!define SOURCE_PATH "@CMAKE_SOURCE_DIR@" +!define QT_DLL_PATH "${MING_BIN}" +!define ACCESSIBLE_DLL_PATH "${MING_LIB}/qt5/plugins/accessible" +!define SQLITE_DLL_PATH "${MING_LIB}/qt5/plugins/sqldrivers" +!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt5/plugins/imageformats" +!define PLATFORMS_DLL_PATH "${MING_LIB}/qt5/plugins/platforms" + +!define CSYNC_LIBRARY_DIR "@CSYNC_LIBRARY_DIR@" +!define CSYNC_CONFIG_DIR "@CSYNC_CONFIG_DIR@" + +!define NSI_PATH "${source_path}/admin/win/nsi" + +;----------------------------------------------------------------------------- +; Installer version +;----------------------------------------------------------------------------- + +!define VER_MAJOR "@CPACK_PACKAGE_VERSION_MAJOR@" +!define VER_MINOR "@CPACK_PACKAGE_VERSION_MINOR@" +!define VER_PATCH "@CPACK_PACKAGE_VERSION_PATCH@" +!define VER_BUILD "@CPACK_PACKAGE_VERSION_BUILD@" +!define VERSION "@CPACK_PACKAGE_VERSION@" + +Var InstallRunIfSilent +Var NoAutomaticUpdates + +;----------------------------------------------------------------------------- +; Installer build timestamp. +;----------------------------------------------------------------------------- +!define /date BUILD_TIME "built on %Y/%m/%d at %I:%M %p" + +;----------------------------------------------------------------------------- +; Initial installer setup and definitions. +;----------------------------------------------------------------------------- +Name "@CPACK_NSIS_PACKAGE_NAME@" +BrandingText "${APPLICATION_NAME} ${VERSION} -- ${BUILD_TIME}" +OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" +InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@" +InstallDirRegKey HKCU "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "" +InstType Standard +InstType Full +InstType Minimal +CRCCheck On +SetCompressor @CPACK_NSIS_COMPRESSOR@ +RequestExecutionLevel user ;Now using the UAC plugin. +ReserveFile NSIS.InstallOptions.ini +ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll" + +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +;----------------------------------------------------------------------------- +; Include some required header files. +;----------------------------------------------------------------------------- +!include LogicLib.nsh ;Used by APPDATA uninstaller. +!include MUI2.nsh ;Used by APPDATA uninstaller. +!include InstallOptions.nsh ;Required by MUI2 to support old MUI_INSTALLOPTIONS. +!include Memento.nsh ;Remember user selections. +!include WinVer.nsh ;Windows version detection. +!include WordFunc.nsh ;Used by VersionCompare macro function. +!include FileFunc.nsh ;Used to read out parameters +!include UAC.nsh ;Used by the UAC elevation to install as user or admin. +!include nsProcess.nsh ;Used to kill the running process +!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. +;----------------------------------------------------------------------------- +!define MEMENTO_REGISTRY_ROOT HKLM +!define MEMENTO_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_NAME}" + +;----------------------------------------------------------------------------- +; Modern User Interface (MUI) definitions and setup. +;----------------------------------------------------------------------------- +!define MUI_ABORTWARNING +!define MUI_ICON ${NSI_PATH}\installer.ico +!define MUI_UNICON ${NSI_PATH}\installer.ico +!define MUI_WELCOMEFINISHPAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/welcome.bmp +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp +!define MUI_COMPONENTSPAGE_SMALLDESC +; We removed this, h1 issue 191687 +;!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}" +;!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}" +!define MUI_FINISHPAGE_NOREBOOTSUPPORT +!ifdef OPTION_FINISHPAGE_RELEASE_NOTES + !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED + !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\NOTES.txt" + !define MUI_FINISHPAGE_SHOWREADME_TEXT $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING +!endif +!ifdef OPTION_FINISHPAGE_LAUNCHER + !define MUI_FINISHPAGE_NOAUTOCLOSE + !define MUI_FINISHPAGE_RUN + !define MUI_FINISHPAGE_RUN_FUNCTION "LaunchApplication" +!endif + +;----------------------------------------------------------------------------- +; Page macros. +;----------------------------------------------------------------------------- +!insertmacro MUI_PAGE_WELCOME +!ifdef OPTION_LICENSE_AGREEMENT + !insertmacro MUI_PAGE_LICENSE "${APPLICATION_LICENSE}" +!endif +Page custom PageReinstall PageLeaveReinstall +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!ifdef OPTION_FINISHPAGE + !insertmacro MUI_PAGE_FINISH +!endif +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +;----------------------------------------------------------------------------- +; Other MUI macros. +;----------------------------------------------------------------------------- +!insertmacro MUI_LANGUAGE "English" + +!include ${source_path}/admin/win/nsi/l10n/languages.nsh +!include ${source_path}/admin/win/nsi/l10n/declarations.nsh + +; Set version strings with english locale +VIProductVersion "${VERSION}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${APPLICATION_NAME}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "${APPLICATION_VENDOR}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION}" + +!macro SETLANG un + Function ${un}SetLang + # load the selected language file + !include "${source_path}/admin/win/nsi/l10n\English.nsh" + StrCmp $LANGUAGE ${LANG_GERMAN} German 0 + StrCmp $LANGUAGE ${LANG_DUTCH} Dutch 0 + StrCmp $LANGUAGE ${LANG_FINNISH} Finnish 0 + StrCmp $LANGUAGE ${LANG_JAPANESE} Japanese 0 + StrCmp $LANGUAGE ${LANG_SLOVENIAN} Slovenian 0 + StrCmp $LANGUAGE ${LANG_SPANISH} Spanish 0 + StrCmp $LANGUAGE ${LANG_ITALIAN} Italian 0 + StrCmp $LANGUAGE ${LANG_ESTONIAN} Estonian 0 + StrCmp $LANGUAGE ${LANG_GREEK} Greek 0 + StrCmp $LANGUAGE ${LANG_BASQUE} Basque 0 + StrCmp $LANGUAGE ${LANG_GALICIAN} Galician 0 + StrCmp $LANGUAGE ${LANG_POLISH} Polish 0 + StrCmp $LANGUAGE ${LANG_TURKISH} Turkish 0 + StrCmp $LANGUAGE ${LANG_NORWEGIAN} Norwegian 0 + StrCmp $LANGUAGE ${LANG_PORTUGUESEBR} Brazilian EndLanguageCmp + German: + !include "${source_path}/admin/win/nsi/l10n\German.nsh" + Goto EndLanguageCmp + Dutch: + !include "${source_path}/admin/win/nsi/l10n\Dutch.nsh" + Goto EndLanguageCmp + Finnish: + !include "${source_path}/admin/win/nsi/l10n\Finnish.nsh" + Goto EndLanguageCmp + Japanese: + !include "${source_path}/admin/win/nsi/l10n\Japanese.nsh" + Goto EndLanguageCmp + Slovenian: + !include "${source_path}/admin/win/nsi/l10n\Slovenian.nsh" + Goto EndLanguageCmp + Spanish: + !include "${source_path}/admin/win/nsi/l10n\Spanish.nsh" + Goto EndLanguageCmp + Italian: + !include "${source_path}/admin/win/nsi/l10n\Italian.nsh" + Goto EndLanguageCmp + Estonian: + !include "${source_path}/admin/win/nsi/l10n\Estonian.nsh" + Goto EndLanguageCmp + Greek: + !include "${source_path}/admin/win/nsi/l10n\Greek.nsh" + Goto EndLanguageCmp + Basque: + !include "${source_path}/admin/win/nsi/l10n\Basque.nsh" + Goto EndLanguageCmp + Galician: + !include "${source_path}/admin/win/nsi/l10n\Galician.nsh" + Goto EndLanguageCmp + Polish: + !include "${source_path}/admin/win/nsi/l10n\Polish.nsh" + Goto EndLanguageCmp + Turkish: + !include "${source_path}/admin/win/nsi/l10n\Turkish.nsh" + Goto EndLanguageCmp + Brazilian: + !include "${source_path}/admin/win/nsi/l10n\PortugueseBR.nsh" + Goto EndLanguageCmp + Norwegian: + !include "${source_path}/admin/win/nsi/l10n\Norwegian.nsh" + EndLanguageCmp: + + FunctionEnd +!macroend + +!insertmacro SETLANG "" +!insertmacro SETLANG "un." + +; Usage: ${If} ${HasSection} SectionName +!macro _HasSection _a _b _t _f + ReadRegDWORD $_LOGICLIB_TEMP "${MEMENTO_REGISTRY_ROOT}" "${MEMENTO_REGISTRY_KEY}" "MementoSection_${_b}" + IntCmpU $_LOGICLIB_TEMP 0 ${_f} ${_t} +!macroend +!define HasSection `"" HasSection` + +############################################################################## +# # +# FINISH PAGE LAUNCHER FUNCTIONS # +# # +############################################################################## + +Function LaunchApplication + !insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\${APPLICATION_EXECUTABLE}" "" "" "" +FunctionEnd + +############################################################################## +# # +# PROCESS HANDLING FUNCTIONS AND MACROS # +# # +############################################################################## + +!macro CheckForProcess processName gotoWhenFound gotoWhenNotFound + ${nsProcess::FindProcess} ${processName} $R0 + StrCmp $R0 0 ${gotoWhenFound} ${gotoWhenNotFound} +!macroend + +!macro ConfirmEndProcess processName + MessageBox MB_YESNO|MB_ICONEXCLAMATION \ + $ConfirmEndProcess_MESSAGEBOX_TEXT \ + /SD IDYES IDYES process_${processName}_kill IDNO process_${processName}_ended + process_${processName}_kill: + DetailPrint $ConfirmEndProcess_KILLING_PROCESSES_TEXT + ${nsProcess::KillProcess} ${processName} $R0 + Sleep 1500 + StrCmp $R0 "1" process_${processName}_ended + DetailPrint $ConfirmEndProcess_KILL_NOT_FOUND_TEXT + process_${processName}_ended: +!macroend + +!macro CheckAndConfirmEndProcess processName + !insertmacro CheckForProcess ${processName} 0 no_process_${processName}_to_end + !insertmacro ConfirmEndProcess ${processName} + no_process_${processName}_to_end: +!macroend + +Function EnsureOwncloudShutdown + !insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}" +FunctionEnd + +Function InstallRedistributables + ${If} ${RunningX64} + ExecWait '"$OUTDIR\vcredist_x64.exe" /install /quiet' + ${Else} + ExecWait '"$OUTDIR\vcredist_x86.exe" /install /quiet' + ${EndIf} + Delete "$OUTDIR\vcredist_x86.exe" + Delete "$OUTDIR\vcredist_x64.exe" +FunctionEnd + +############################################################################## +# # +# RE-INSTALLER FUNCTIONS # +# # +############################################################################## + +Function PageReinstall + ReadRegStr $R0 HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "" + StrCmp $R0 "" 0 +2 + Abort + + ;Detect version + ReadRegDWORD $R0 HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMajor" + IntCmp $R0 ${VER_MAJOR} minor_check new_version older_version + minor_check: + ReadRegDWORD $R0 HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMinor" + IntCmp $R0 ${VER_MINOR} rev_check new_version older_version + rev_check: + ReadRegDWORD $R0 HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionRevision" + IntCmp $R0 ${VER_PATCH} build_check new_version older_version + build_check: + ReadRegDWORD $R0 HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionBuild" + IntCmp $R0 ${VER_BUILD} same_version new_version older_version + + new_version: + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" $PageReinstall_NEW_Field_1 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" $PageReinstall_NEW_Field_2 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" $PageReinstall_NEW_Field_3 + !insertmacro MUI_HEADER_TEXT $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE + StrCpy $R0 "1" + Goto reinst_start + + older_version: + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" $PageReinstall_OLD_Field_1 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" $PageReinstall_NEW_Field_2 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" $PageReinstall_NEW_Field_3 + !insertmacro MUI_HEADER_TEXT $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE + StrCpy $R0 "1" + Goto reinst_start + + same_version: + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" $PageReinstall_SAME_Field_1 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" $PageReinstall_SAME_Field_2 + !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" $PageReinstall_SAME_Field_3 + !insertmacro MUI_HEADER_TEXT $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE + StrCpy $R0 "2" + + reinst_start: + !insertmacro INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" +FunctionEnd + +Function PageLeaveReinstall + !insertmacro INSTALLOPTIONS_READ $R1 "NSIS.InstallOptions.ini" "Field 2" "State" + StrCmp $R0 "1" 0 +2 + StrCmp $R1 "1" reinst_uninstall reinst_done + StrCmp $R0 "2" 0 +3 + StrCmp $R1 "1" reinst_done reinst_uninstall + reinst_uninstall: + ReadRegStr $R1 ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "UninstallString" + HideWindow + ClearErrors + ExecWait '$R1 _?=$INSTDIR' + IfErrors no_remove_uninstaller + IfFileExists "$INSTDIR\${APPLICATION_EXECUTABLE}" no_remove_uninstaller + Delete $R1 + RMDir $INSTDIR + no_remove_uninstaller: + StrCmp $R0 "2" 0 +3 + Quit + BringToFront + reinst_done: +FunctionEnd + +############################################################################## +# # +# INSTALLER SECTIONS # +# # +############################################################################## +Section "${APPLICATION_NAME}" SEC_APPLICATION + SectionIn 1 2 3 RO + SetDetailsPrint listonly + + SetDetailsPrint textonly + DetailPrint $SEC_APPLICATION_DETAILS + SetDetailsPrint listonly + SetOutPath "$INSTDIR" + + ;Main executable & csync + File "${BUILD_PATH}\bin\${APPLICATION_EXECUTABLE}" + File "${BUILD_PATH}\bin\${APPLICATION_CMD_EXECUTABLE}" + File "${BUILD_PATH}\bin\lib${APPLICATION_SHORTNAME}sync.dll" + File "${BUILD_PATH}\bin\lib${APPLICATION_SHORTNAME}_csync.dll" + + File "${BUILD_PATH}\src\gui\client*.qm" + ; Make sure only to copy qt, not qt_help, etc + File "${MING_SHARE}\qt5\translations\qt_??.qm" + File "${MING_SHARE}\qt5\translations\qt_??_??.qm" + File "${MING_SHARE}\qt5\translations\qtbase_*.qm" + File "${MING_SHARE}\qt5\translations\qtkeychain_*.qm" + + ;Add crash reporter if it was built + File /nonfatal "${BUILD_PATH}/bin/${CRASHREPORTER_EXECUTABLE}.exe" + + SetOutPath "$INSTDIR\platforms" + File "${PLATFORMS_DLL_PATH}\qwindows.dll" + SetOutPath "$INSTDIR\imageformats" + 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" + + SetOutPath "$INSTDIR" + ;License & release notes. + File "@CPACK_RESOURCE_FILE_LICENSE@" + ;File /oname=NOTES.txt ${NSI_PATH}\RELEASE_NOTES.txt + + ;Qt config: + File "${NSI_PATH}\qt.conf" + + ;Qt stuff: + File "${QT_DLL_PATH}\Qt5Core.dll" + 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" + File "${QT_DLL_PATH}\Qt5WebKitWidgets.dll" + File "${QT_DLL_PATH}\Qt5Widgets.dll" + File "${QT_DLL_PATH}\Qt5Xml.dll" + + ;QtWebKit dependencies + File "${QT_DLL_PATH}\Qt5Multimedia.dll" + File "${QT_DLL_PATH}\Qt5MultimediaWidgets.dll" + File "${QT_DLL_PATH}\Qt5Sensors.dll" + + ;Qt deps + File "${MING_BIN}\libpng16-16.dll" + File "${MING_BIN}\icudata56.dll" + File "${MING_BIN}\icui18n56.dll" + File "${MING_BIN}\icuuc56.dll" + File "${MING_BIN}\libEGL.dll" + File "${MING_BIN}\libGLESv2.dll" + File "${MING_BIN}\libjpeg-8.dll" + File "${MING_BIN}\libpcre16-0.dll" + File "${MING_BIN}\libsqlite3-0.dll" + File "${MING_BIN}\libcrypto-10.dll" + File "${MING_BIN}\libssl-10.dll" + File "${MING_BIN}\libstdc++-6.dll" + File "${MING_BIN}\libwebp-5.dll" + File "${MING_BIN}\libxslt-1.dll" + File "${MING_BIN}\libxml2-2.dll" + File "${MING_BIN}\zlib1.dll" + File "${MING_BIN}\libharfbuzz-0.dll" + File "${MING_BIN}\libfreetype-6.dll" + File "${MING_BIN}\libglib-2.0-0.dll" + File "${MING_BIN}\libintl-8.dll" + + ;QtKeyChain stuff + File "${MING_BIN}\libqt5keychain.dll" + + ;MinGW stuff + 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 + ${MementoSection} $OPTION_SECTION_SC_SHELL_EXT_SECTION SEC_SHELL_EXT + SectionIn 1 2 + SetDetailsPrint textonly + DetailPrint $OPTION_SECTION_SC_SHELL_EXT_DetailPrint + File "${BUILD_PATH}\vcredist_x86.exe" + File "${BUILD_PATH}\vcredist_x64.exe" + Call InstallRedistributables + !define LIBRARY_COM + !define LIBRARY_SHELL_EXTENSION + !define LIBRARY_IGNORE_VERSION + ${If} ${RunningX64} + !define LIBRARY_X64 + !insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCUtil_x64.dll" "$INSTDIR\OCUtil_x64.dll" "$INSTDIR" + !insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCOverlays_x64.dll" "$INSTDIR\OCOverlays_x64.dll" "$INSTDIR" + !insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCContextMenu_x64.dll" "$INSTDIR\OCContextMenu_x64.dll" "$INSTDIR" + !undef LIBRARY_X64 + ${Else} + !insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCUtil_x86.dll" "$INSTDIR\OCUtil_x86.dll" "$INSTDIR" + !insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCOverlays_x86.dll" "$INSTDIR\OCOverlays_x86.dll" "$INSTDIR" + !insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCContextMenu_x86.dll" "$INSTDIR\OCContextMenu_x86.dll" "$INSTDIR" + ${Endif} + !undef LIBRARY_COM + !undef LIBRARY_SHELL_EXTENSION + !undef LIBRARY_IGNORE_VERSION + ${MementoSectionEnd} +!endif + +SectionGroup $SectionGroup_Shortcuts + +!ifdef OPTION_SECTION_SC_START_MENU + ${MementoSection} $OPTION_SECTION_SC_START_MENU_SECTION SEC_START_MENU + SectionIn 1 2 3 + SetDetailsPrint textonly + DetailPrint $OPTION_SECTION_SC_START_MENU_DetailPrint + SetDetailsPrint listonly + SetShellVarContext all + CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}" + SetShellVarContext current + ${MementoSectionEnd} +!endif + +!ifdef OPTION_SECTION_SC_DESKTOP + ${MementoSection} $OPTION_SECTION_SC_DESKTOP_SECTION SEC_DESKTOP + SectionIn 1 2 + SetDetailsPrint textonly + DetailPrint $OPTION_SECTION_SC_DESKTOP_DetailPrint + SetDetailsPrint listonly + SetShellVarContext all + CreateShortCut "$DESKTOP\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}" + SetShellVarContext current + ${MementoSectionEnd} +!endif + +!ifdef OPTION_SECTION_SC_QUICK_LAUNCH + ${MementoSection} $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION SEC_QUICK_LAUNCH + SectionIn 1 2 + SetDetailsPrint textonly + DetailPrint $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint + SetShellVarContext all + SetDetailsPrint listonly + CreateShortCut "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}" + SetShellVarContext current + ${MementoSectionEnd} +!endif + +SectionGroupEnd + +${MementoSectionDone} + +; Installer section descriptions +;-------------------------------- +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN +!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APPLICATION} $OPTION_SECTION_SC_APPLICATION_Desc +!insertmacro MUI_DESCRIPTION_TEXT ${SEC_START_MENU} $OPTION_SECTION_SC_START_MENU_Desc +!insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKTOP} $OPTION_SECTION_SC_DESKTOP_Desc +!insertmacro MUI_DESCRIPTION_TEXT ${SEC_QUICK_LAUNCH} $OPTION_SECTION_SC_QUICK_LAUNCH_Desc +!insertmacro MUI_FUNCTION_DESCRIPTION_END + + +Section -post + + ;Uninstaller file. + SetDetailsPrint textonly + DetailPrint $UNINSTALLER_FILE_Detail + SetDetailsPrint listonly + WriteUninstaller $INSTDIR\uninstall.exe + + ;Registry keys required for installer version handling and uninstaller. + SetDetailsPrint textonly + DetailPrint $UNINSTALLER_REGISTRY_Detail + SetDetailsPrint listonly + + ;Version numbers used to detect existing installation version for comparison. + WriteRegStr HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "" $INSTDIR + WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMajor" "${VER_MAJOR}" + WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMinor" "${VER_MINOR}" + WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionRevision" "${VER_PATCH}" + WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionBuild" "${VER_BUILD}" + + ;Add or Remove Programs entry. + WriteRegExpandStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "UninstallString" '"$INSTDIR\Uninstall.exe"' + WriteRegExpandStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "InstallLocation" "$INSTDIR" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "DisplayName" "${APPLICATION_NAME}" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "Publisher" "${APPLICATION_VENDOR}" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "DisplayIcon" "$INSTDIR\Uninstall.exe,0" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "DisplayVersion" "${VERSION}" + WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "VersionMajor" "${VER_MAJOR}" + WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "VersionMinor" "${VER_MINOR}.${VER_PATCH}.${VER_BUILD}" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "URLInfoAbout" "http://${APPLICATION_DOMAIN}/" + WriteRegStr ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "HelpLink" "http://${APPLICATION_DOMAIN}/" + WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "NoModify" "1" + WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "NoRepair" "1" + + + SetDetailsPrint textonly + DetailPrint $UNINSTALLER_FINISHED_Detail +SectionEnd + +############################################################################## +# # +# UNINSTALLER SECTION # +# # +############################################################################## + +Function un.EnsureOwncloudShutdown + !insertmacro CheckAndConfirmEndProcess "${APPLICATION_EXECUTABLE}" +FunctionEnd + +Section Uninstall + IfFileExists "$INSTDIR\${APPLICATION_EXECUTABLE}" owncloud_installed + MessageBox MB_YESNO $UNINSTALL_MESSAGEBOX /SD IDYES IDYES owncloud_installed + 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" + DeleteRegValue HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionMinor" + DeleteRegValue HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "VersionRevision" + DeleteRegValue HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "" + DeleteRegKey HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" + + 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 + !define LIBRARY_SHELL_EXTENSION + !define LIBRARY_IGNORE_VERSION + ${If} ${HasSection} SEC_SHELL_EXT + DetailPrint "Uninstalling x64 overlay DLLs" + !define LIBRARY_X64 + !insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCContextMenu_x64.dll" + !insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCOverlays_x64.dll" + !insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCUtil_x64.dll" + !undef LIBRARY_X64 + DetailPrint "Uninstalling x86 overlay DLLs" + !insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCContextMenu_x86.dll" + !insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCOverlays_x86.dll" + !insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\OCUtil_x86.dll" + ${EndIf} + !undef LIBRARY_COM + !undef LIBRARY_SHELL_EXTENSION + !undef LIBRARY_IGNORE_VERSION + !endif + + ;Start menu shortcut + !ifdef OPTION_SECTION_SC_START_MENU + SetShellVarContext all + ${If} ${HasSection} SEC_START_MENU + Delete "$SMPROGRAMS\${APPLICATION_NAME}.lnk" + ${EndIf} + SetShellVarContext current + !endif + + ;Desktop shortcut. + !ifdef OPTION_SECTION_SC_DESKTOP + ${If} ${HasSection} SEC_DESKTOP + SetShellVarContext all + ${If} ${FileExists} "$DESKTOP\${APPLICATION_NAME}.lnk" + Delete "$DESKTOP\${APPLICATION_NAME}.lnk" + ${EndIf} + SetShellVarContext current + ${EndIf} + !endif + + ;Quick Launch shortcut. + !ifdef OPTION_SECTION_SC_QUICK_LAUNCH + ${If} ${HasSection} SEC_QUICK_LAUNCH + SetShellVarContext all + ${If} ${FileExists} "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" + Delete "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" + ${EndIf} + SetShellVarContext current + ${EndIf} + !endif + + ;Remove all the Program Files. + RMDir /r $INSTDIR + + DeleteRegKey ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" + + SetDetailsPrint textonly + DetailPrint $UNINSTALLER_FINISHED_Detail +SectionEnd + +############################################################################## +# # +# NSIS Installer Event Handler Functions # +# # +############################################################################## + +Function .onInit + SetOutPath $INSTDIR + + ${GetParameters} $R0 + ${GetOptions} $R0 "/launch" $R0 + ${IfNot} ${Errors} + StrCpy $InstallRunIfSilent "yes" + ${EndIf} + + ${GetParameters} $R0 + ${GetOptions} $R0 "/noautoupdate" $R0 + ${IfNot} ${Errors} + StrCpy $NoAutomaticUpdates "yes" + ${EndIf} + + + !insertmacro INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" + + ; uncomment this line if you want to see the language selection + ;!insertmacro MUI_LANGDLL_DISPLAY + + Call SetLang + + ; Remove Quick Launch option from Windows 7, as no longer applicable - usually. + ${IfNot} ${AtMostWinVista} + SectionSetText ${SEC_QUICK_LAUNCH} $INIT_NO_QUICK_LAUNCH + SectionSetFlags ${SEC_QUICK_LAUNCH} ${SF_RO} + SectionSetInstTypes ${SEC_QUICK_LAUNCH} 0 + ${EndIf} + + ; Some people might have a shortcut called 'ownCloud' pointing elsewhere, see #356 + ; Unselect item and adjust text + ${If} ${FileExists} "$DESKTOP\${APPLICATION_NAME}.lnk" + SectionSetText ${SEC_DESKTOP} $INIT_NO_DESKTOP + Push $0 + SectionSetFlags ${SEC_DESKTOP} 0 + SectionSetInstTypes ${SEC_DESKTOP} 0 + Pop $0 + ${EndIf} + + ${MementoSectionRestore} + + UAC_TryAgain: + !insertmacro UAC_RunElevated + ${Switch} $0 + ${Case} 0 + ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done + ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on + ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user + MessageBox mb_YesNo|mb_ICONEXCLAMATION|MB_TOPMOST|MB_SETFOREGROUND $UAC_INSTALLER_REQUIRE_ADMIN /SD IDNO IDYES UAC_TryAgain IDNO 0 + ${EndIf} + ;fall-through and die + ${Case} 1223 + MessageBox MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND $UAC_INSTALLER_REQUIRE_ADMIN + Quit + ${Case} 1062 + MessageBox MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND $UAC_ERROR_LOGON_SERVICE + Quit + ${Default} + MessageBox MB_ICONSTOP "$UAC_ERROR_ELEVATE $0" + Abort + Quit + ${EndSwitch} + + ;Prevent multiple instances. + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${APPLICATION_SHORTNAME}Installer") i .r1 ?e' + Pop $R0 + StrCmp $R0 0 +3 + MessageBox MB_OK|MB_ICONEXCLAMATION $INIT_INSTALLER_RUNNING + Abort + + ;Use available InstallLocation when possible. This is useful in the uninstaller + ;via re-install, which would otherwise use a default location - a bug. + ReadRegStr $R0 ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "InstallLocation" + StrCmp $R0 "" SkipSetInstDir + StrCpy $INSTDIR $R0 + SkipSetInstDir: + + ;Shutdown ${APPLICATION_NAME} in case Add/Remove re-installer option used. + Call EnsureOwncloudShutdown + + ReadRegStr $R0 ${MEMENTO_REGISTRY_ROOT} "${MEMENTO_REGISTRY_KEY}" "InstallLocation" + ${If} ${Silent} + ${AndIf} $R0 != "" + ExecWait '"$R0\Uninstall.exe" /S _?=$R0' + ${EndIf} +FunctionEnd + +Function .onInstSuccess + ${MementoSectionSave} + + ${If} $NoAutomaticUpdates == "yes" + WriteRegDWORD HKLM "Software\${APPLICATION_VENDOR}\${APPLICATION_NAME}" "skipUpdateCheck" "1" + ${EndIf} + + ; TODO: Only needed to when updating from 2.1.{0,1}. Remove in due time. + Delete /REBOOTOK $INSTDIR\bearer\qgenericbearer.dll + Delete /REBOOTOK $INSTDIR\bearer\qnativewifibearer.dll + RMDir /REBOOTOK $INSTDIR\bearer + + ${If} ${Silent} + ${AndIf} $InstallRunIfSilent == "yes" + Call LaunchApplication + ${EndIf} +FunctionEnd + +Function .onInstFailed +FunctionEnd + +############################################################################## +# # +# NSIS Uninstaller Event Handler Functions # +# # +############################################################################## + +Function un.onInit + Call un.SetLang + + UAC_TryAgain: + !insertmacro UAC_RunElevated + ${Switch} $0 + ${Case} 0 + ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done + ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on + ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user + MessageBox mb_YesNo|mb_ICONEXCLAMATION|MB_TOPMOST|MB_SETFOREGROUND $UAC_UNINSTALLER_REQUIRE_ADMIN /SD IDNO IDYES UAC_TryAgain IDNO 0 + ${EndIf} + ;fall-through and die + ${Case} 1223 + MessageBox MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND $UAC_UNINSTALLER_REQUIRE_ADMIN + Quit + ${Case} 1062 + MessageBox MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND $UAC_ERROR_LOGON_SERVICE + Quit + ${Default} + MessageBox MB_ICONSTOP "$UAC_ERROR_ELEVATE $0" + Abort + Quit + ${EndSwitch} + + ;Prevent multiple instances. + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${APPLICATION_SHORTNAME}Uninstaller") i .r1 ?e' + Pop $R0 + StrCmp $R0 0 +3 + MessageBox MB_OK|MB_ICONEXCLAMATION $INIT_UNINSTALLER_RUNNING + Abort + + ;Shutdown ${APPLICATION_NAME} in order to remove locked files. + Call un.EnsureOwncloudShutdown +FunctionEnd + +Function un.onUnInstSuccess +FunctionEnd + +Function un.onUnInstFailed +FunctionEnd diff --git a/cmake/modules/UseDoxygen.cmake b/cmake/modules/UseDoxygen.cmake new file mode 100644 index 000000000..86622f61c --- /dev/null +++ b/cmake/modules/UseDoxygen.cmake @@ -0,0 +1,131 @@ +# (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. + +# -helper macro to add a "doc" target with CMake build system. +# and configure doxy.config.in to doxy.config +# +# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux +# Creates .chm windows help file if MS HTML help workshop +# (available from http://msdn.microsoft.com/workshop/author/htmlhelp) +# is installed with its DLLs in PATH. +# +# +# Please note, that the tools, e.g.: +# doxygen, dot, latex, dvips, makeindex, gswin32, etc. +# must be in path. +# +# Note about Visual Studio Projects: +# MSVS has its own path environment which may differ from the shell. +# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1 +# +# author Jan Woetzel 2004-2006 +# www.mip.informatik.uni-kiel.de/~jw + + +FIND_PACKAGE(Doxygen) + +IF (DOXYGEN_FOUND) + + # click+jump in Emacs and Visual Studio (for doxy.config) (jw) + IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") + SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"") + ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") + SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"") + ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") + + # we need latex for doxygen because of the formulas + FIND_PACKAGE(LATEX) + IF (NOT LATEX_COMPILER) + MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user interaction on doxy run.") + ENDIF (NOT LATEX_COMPILER) + IF (NOT MAKEINDEX_COMPILER) + MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.") + ENDIF (NOT MAKEINDEX_COMPILER) + IF (NOT DVIPS_CONVERTER) + MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.") + ENDIF (NOT DVIPS_CONVERTER) + FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot) + IF (DOXYGEN_DOT_EXECUTABLE_PATH) + SET(DOXYGEN_DOT_FOUND "YES") + ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH) + + IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in") + MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in") + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in + ${CMAKE_CURRENT_BINARY_DIR}/doxy.config + @ONLY ) + # use (configured) doxy.config from (out of place) BUILD tree: + SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config") + ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in") + # use static hand-edited doxy.config from SOURCE tree: + SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config") + IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config") + MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.") + ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config") + IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in") + # using template doxy.config.in + MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in") + CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in + ${CMAKE_CURRENT_BINARY_DIR}/doxy.config + @ONLY ) + SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config") + ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in") + # failed completely... + MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)") + ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in") + + ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config") + ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in") + + ADD_CUSTOM_TARGET(csync_doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config) + + # create a windows help .chm file using hhc.exe + # HTMLHelp DLL must be in path! + # fallback: use hhw.exe interactively + IF (WIN32) + FIND_PACKAGE(HTMLHelp) + IF (HTML_HELP_COMPILER) + SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp") + STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} ) + # MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}") + ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE}) + ADD_DEPENDENCIES (winhelp doc) + + IF (NOT TARGET_DOC_SKIP_INSTALL) + # install windows help? + # determine useful name for output file + # should be project and version unique to allow installing + # multiple projects into one global directory + IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm") + IF (PROJECT_NAME) + SET(OUT "${PROJECT_NAME}") + ELSE (PROJECT_NAME) + SET(OUT "Documentation") # default + ENDIF(PROJECT_NAME) + IF (${PROJECT_NAME}_VERSION_MAJOR) + SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}") + IF (${PROJECT_NAME}_VERSION_MINOR) + SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}") + IF (${PROJECT_NAME}_VERSION_PATCH) + SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}") + ENDIF(${PROJECT_NAME}_VERSION_PATCH) + ENDIF(${PROJECT_NAME}_VERSION_MINOR) + ENDIF(${PROJECT_NAME}_VERSION_MAJOR) + # keep suffix + SET(OUT "${OUT}.chm") + + #MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}") + # create target used by install and package commands + INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm" + DESTINATION "doc" + RENAME "${OUT}" + ) + ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm") + ENDIF(NOT TARGET_DOC_SKIP_INSTALL) + + ENDIF(HTML_HELP_COMPILER) + # MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}") + ENDIF (WIN32) +ENDIF(DOXYGEN_FOUND) + diff --git a/cmake/modules/Warnings.cmake b/cmake/modules/Warnings.cmake new file mode 100644 index 000000000..371e7bcd0 --- /dev/null +++ b/cmake/modules/Warnings.cmake @@ -0,0 +1,30 @@ +# (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. + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + + # Use this only for Clang + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments") + endif() + + # Fix sqlite compilation on macOS + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers") + + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # Fix sqlite compilation on MinGW + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-discarded-qualifiers") + + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") + endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") + endif() + +endif() diff --git a/cmake/scripts/generate_findpackage_file b/cmake/scripts/generate_findpackage_file new file mode 100644 index 000000000..a29d2d8e0 --- /dev/null +++ b/cmake/scripts/generate_findpackage_file @@ -0,0 +1,154 @@ +#!/usr/bin/env ruby + +# Simple script to generate simple cmake modules for finding +# libraries (packages) +# +# usage: generate_findpackage_file +# then you will be prompted to enter the required parameters +# +##################################################################### +# +# Copyright (c) 2006 Alexander Neundorf +# Copyright (c) 2006 Andreas Schneider +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + +require 'readline' + +package=Readline.readline("Name of package: ") + +name=Readline.readline("\nYour Name (for copyright): ") + +email=Readline.readline("\nYour mail (for copyright): ") + +pkgconfig=Readline.readline("\npkgconfig package name (e.g. \"libxml-2.0\", leave empty to skip pkgconfig): ") + +header=Readline.readline("\nLook for header (e.g. \"jpeglib.h\" or \"libxml/xpath.h\"): ") + +incSubDir=Readline.readline("\nLook for header subdir (e.g. \"libxml2\", empty to skip ): ") + +libs=Readline.readline("\nLook for library (e.g. \"xml2\" or \"avcodec avutil\"): ") + +t = Time.now + +cmakeIncDirName=package.upcase+"_INCLUDE_DIR" +cmakeIncDirNames=package.upcase+"_INCLUDE_DIRS" +cmakeLibNames=package.upcase+"_LIBRARIES" +cmakeDefsName=package.upcase+"_DEFINITIONS" +cmakeFoundName=package.upcase+"_FOUND" +cmakeQuietName=package+"_FIND_QUIETLY" +cmakeRequiredName=package+"_FIND_REQUIRED" + +file=File.new("Find#{package}.cmake", "w+") + + +file.printf("# - Try to find #{package}\n") +file.printf("# Once done this will define\n") +file.printf("#\n") +file.printf("# #{cmakeFoundName} - system has #{package}\n") +file.printf("# #{cmakeIncDirNames} - the #{package} include directory\n") +file.printf("# #{cmakeLibNames} - Link these to use #{package}\n") +file.printf("# #{cmakeDefsName} - Compiler switches required for using #{package}\n") +file.printf("#\n") +file.printf("# Copyright (c) #{t.year} #{name} <#{email}>\n") +file.printf("#\n") +file.printf("# Redistribution and use is allowed according to the terms of the New\n") +file.printf("# BSD license.\n") +file.printf("# For details see the accompanying COPYING-CMAKE-SCRIPTS file.\n") +file.printf("#\n") + +file.printf("\n") +file.printf("\n") + +file.printf("if (#{cmakeLibNames} AND #{cmakeIncDirNames})\n") +file.printf(" # in cache already\n") +file.printf(" set(#{cmakeFoundName} TRUE)\n") +file.printf("else (#{cmakeLibNames} AND #{cmakeIncDirNames})\n") + +if not pkgconfig.empty? + file.printf(" find_package(PkgConfig)\n") + file.printf(" if (PKG_CONFIG_FOUND)\n") + file.printf(" pkg_check_modules(_#{package.upcase} #{pkgconfig})\n") + file.printf(" endif (PKG_CONFIG_FOUND)\n") +end + +file.printf("\n") + +file.printf(" find_path(#{cmakeIncDirName}\n") +file.printf(" NAMES\n") +file.printf(" #{header}\n") +file.printf(" PATHS\n") +if not pkgconfig.empty? + file.printf(" ${_#{package.upcase}_INCLUDEDIR}\n") +end +file.printf(" /usr/include\n") +file.printf(" /usr/local/include\n") +file.printf(" /opt/local/include\n") +file.printf(" /sw/include\n") + +if not incSubDir.empty? + file.printf(" PATH_SUFFIXES\n") + file.printf(" #{incSubDir}\n") +end +file.printf(" )\n") + +file.printf("\n") + +libs.split(" ").each do |lib| + file.printf(" find_library(#{lib.upcase}_LIBRARY\n") + file.printf(" NAMES\n") + file.printf(" #{lib}\n") + file.printf(" PATHS\n") + if not pkgconfig.empty? + file.printf(" ${_#{package.upcase}_LIBDIR}\n") + end + file.printf(" /usr/lib\n") + file.printf(" /usr/local/lib\n") + file.printf(" /opt/local/lib\n") + file.printf(" /sw/lib\n") + file.printf(" )\n") + file.printf("\n") +end + +file.printf(" set(#{cmakeIncDirNames}\n") +file.printf(" ${#{cmakeIncDirName}}\n") +file.printf(" )\n") + +file.printf("\n") + +libs.split(" ").each do |lib| + file.printf(" if (#{lib.upcase}_LIBRARY)\n") + file.printf(" set(#{cmakeLibNames}\n") + file.printf(" ${#{cmakeLibNames}}\n") + file.printf(" ${#{lib.upcase}_LIBRARY}\n") + file.printf(" )\n") + file.printf(" endif (#{lib.upcase}_LIBRARY)\n") + file.printf("\n") +end + +file.printf(" include(FindPackageHandleStandardArgs)\n") +file.printf(" find_package_handle_standard_args(#{package} DEFAULT_MSG #{cmakeLibNames} #{cmakeIncDirNames})\n") + +file.printf("\n") + +file.printf(" # show the #{cmakeIncDirNames} and #{cmakeLibNames} variables only in the advanced view\n") +file.printf(" mark_as_advanced(#{cmakeIncDirNames} #{cmakeLibNames})\n\n") + +file.printf("endif (#{cmakeLibNames} AND #{cmakeIncDirNames})\n\n") + +printf("Done, generated Find#{package}.cmake\n") + diff --git a/cmake/scripts/generate_lib_file b/cmake/scripts/generate_lib_file new file mode 100644 index 000000000..8fee25703 --- /dev/null +++ b/cmake/scripts/generate_lib_file @@ -0,0 +1,135 @@ +#!/usr/bin/env ruby + +# simple script to generate CMakeLists.txt for wengophone libs +# +# usage: generate_lib_file +# then you will be prompted to enter the required parameters +# +##################################################################### +# +# Copyright (c) 2006 Andreas Schneider +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + +print("Name of project: ") +project=gets.chomp + +printf("\n") + +print("Other projects to include (e.g. \"owutil tinyxml\", leave empty to skip): ") +otherprojects=gets.chomp + +printf("\n") + +print("Definitions (leave empty to skip): ") +definitions=gets.chomp + +cmakePublicIncDirName = project.upcase+"_PUBLIC_INCLUDE_DIRS" +cmakePrivateIncDirName = project.upcase+"_PRIVATE_INCLUDE_DIRS" +cmakeLibName = project.upcase+"_LIBRARY" +cmakeLibNames = project.upcase+"_LINK_LIBRARIES" +cmakePublicDefsName = project.upcase+"_PUBLIC_DEFINITIONS" +cmakePrivateDefsName = project.upcase+"_PRIVATE_DEFINITIONS" + +file=File.new("CMakeLists.txt", "w+") + +file.printf("project(#{project})\n") +file.printf("\n") +file.printf("# needed include directories to build #{project}\n") +file.printf("# saves the variable in internal cache for later use\n") +file.printf("set(#{cmakePublicIncDirName}\n") +file.printf(" ${CMAKE_CURRENT_SOURCE_DIR}\n") +file.printf(" ${CMAKE_CURRENT_SOURCE_DIR}/include\n") +file.printf(" CACHE INTERNAL \"#{project} public include directories\"\n") +file.printf(")\n") + +file.printf("\n") + +file.printf("set(#{cmakePrivateIncDirName}\n") +otherprojects.split(" ").each do |otherproject| + file.printf(" ${#{otherproject.upcase}_PUBLIC_INCLUDE_DIRS}\n") +end +file.printf(" ${CMAKE_CURRENT_BINARY_DIR}\n") +file.printf(")\n") + +file.printf("\n") + +file.printf("set(#{cmakeLibName}\n") +file.printf(" #{project}\n") +file.printf(" CACHE INTERNAL \"#{project} library\"\n") +file.printf(")\n") + +file.printf("\n") + +file.printf("# #{project} lib and dependencies\n") +file.printf("set(#{cmakeLibNames}\n") +file.printf(" #{cmakeLibName}\n") +otherprojects.split(" ").each do |otherproject| + file.printf(" ${#{otherproject.upcase}_LIBRARIES}\n") +end +file.printf(")\n") + +file.printf("\n") + +if not definitions.empty? + file.printf("set(#{cmakePublicDefsName}\n") + file.printf(" #{definitions}\n") + file.printf(" CACHE INTERNAL \"#{project} public definitions\"\n") + file.printf(")\n") + + file.printf("\n") + + file.printf("set(#{cmakePrivateDefsName}\n") + file.printf(" #{definitions}\n") + file.printf(")\n") + + file.printf("\n") +end + +file.printf("set(#{project}_SRCS\n") +file.printf(" files.c\n") +file.printf(")\n") + +file.printf("\n") + +file.printf("include_directories(\n") +file.printf(" ${#{cmakePublicIncDirName}}\n") +file.printf(" ${#{cmakePrivateIncDirName}}\n") +file.printf(")\n") + +file.printf("\n") + +if not definitions.empty? + file.printf("add_definitions(\n") + file.printf(" ${#{cmakePublicDefsName}}\n") + file.printf(" ${#{cmakePrivateDefsName}}\n") + file.printf(")\n") + + file.printf("\n") +end + +file.printf("\n") + +file.printf("add_library(${#{cmakeLibName}} STATIC ${#{project}_SRCS})\n") + +file.printf("\n") + +file.printf("target_link_libraries(${#{cmakeLibNames}})\n") + +file.printf("\n") + +printf("Generated CMakeLists.txt for #{project}\n") + diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..159e2f00e --- /dev/null +++ b/codecov.yml @@ -0,0 +1,25 @@ +codecov: + branch: master + ci: + - "!drone.nextcloud.com" + - "!appveyor" + +coverage: + precision: 2 + round: down + range: "70...100" + status: + project: + default: + threshold: 0.5 + +comment: + layout: "header, diff, changes, uncovered, tree" + behavior: default + +github_checks: + annotations: false + +ignore: + - "src/3rdparty" + diff --git a/config.h.in b/config.h.in new file mode 100644 index 000000000..0e3f0eae9 --- /dev/null +++ b/config.h.in @@ -0,0 +1,74 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#cmakedefine USE_INOTIFY 1 +#cmakedefine WITH_QTKEYCHAIN 1 +#cmakedefine WITH_CRASHREPORTER +#cmakedefine BUILD_FILE_PROVIDER_MODULE "@BUILD_FILE_PROVIDER_MODULE@" +#cmakedefine WITH_PROVIDERS "@WITH_PROVIDERS@" +#cmakedefine CRASHREPORTER_EXECUTABLE "@CRASHREPORTER_EXECUTABLE@" +#define SOCKETAPI_TEAM_IDENTIFIER_PREFIX "@SOCKETAPI_TEAM_IDENTIFIER_PREFIX@" + +#cmakedefine THEME_CLASS @THEME_CLASS@ +#cmakedefine THEME_INCLUDE @THEME_INCLUDE@ + +#cmakedefine APPLICATION_NAME "@APPLICATION_NAME@" +#cmakedefine APPLICATION_VENDOR "@APPLICATION_VENDOR@" +#cmakedefine APPLICATION_DOMAIN "@APPLICATION_DOMAIN@" +#cmakedefine APPLICATION_REV_DOMAIN "@APPLICATION_REV_DOMAIN@" +#cmakedefine APPLICATION_SHORTNAME "@APPLICATION_SHORTNAME@" +#cmakedefine APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@" +#cmakedefine APPLICATION_CONFIG_NAME "@APPLICATION_CONFIG_NAME@" +#cmakedefine APPLICATION_UPDATE_URL "@APPLICATION_UPDATE_URL@" +#cmakedefine APPLICATION_HELP_URL "@APPLICATION_HELP_URL@" +#cmakedefine APPLICATION_ICON_NAME "@APPLICATION_ICON_NAME@" +#cmakedefine APPLICATION_ICON_SET "@APPLICATION_ICON_SET@" +#cmakedefine APPLICATION_SERVER_URL R"(@APPLICATION_SERVER_URL@)" +#cmakedefine APPLICATION_SERVER_URL_ENFORCE "@APPLICATION_SERVER_URL_ENFORCE@" +#cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@" +#cmakedefine APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "@APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR@" +#cmakedefine NEXTCLOUD_BACKGROUND_COLOR "@NEXTCLOUD_BACKGROUND_COLOR@" +#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@" +#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@" +#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@" +#cmakedefine APPLICATION_OCSP_STAPLING_ENABLED "@APPLICATION_OCSP_STAPLING_ENABLED@" +#cmakedefine APPLICATION_FORBID_BAD_SSL "@APPLICATION_FORBID_BAD_SSL@" +#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX +#define APPLICATION_URI_HANDLER_SCHEME "@APPLICATION_URI_HANDLER_SCHEME@" +#cmakedefine01 ENFORCE_VIRTUAL_FILES_SYNC_FOLDER +#cmakedefine01 DISABLE_VIRTUAL_FILES_SYNC_FOLDER +#cmakedefine DO_NOT_USE_PROXY "@DO_NOT_USE_PROXY@" +#cmakedefine ENFORCE_SINGLE_ACCOUNT "@ENFORCE_SINGLE_ACCOUNT@" +#cmakedefine01 APPLICATION_DISPLAY_LEGACY_IMPORT_DIALOG + +#cmakedefine ZLIB_FOUND @ZLIB_FOUND@ + +#cmakedefine SYSCONFDIR "@SYSCONFDIR@" +#cmakedefine SHAREDIR "@SHAREDIR@" + +#cmakedefine01 GUI_TESTING + +#cmakedefine BUILD_UPDATER "@BUILD_UPDATER@" + +#cmakedefine CFAPI_SHELLEXT_APPID_REG "@CFAPI_SHELLEXT_APPID_REG@" +#cmakedefine CFAPI_SHELLEXT_APPID_DISPLAY_NAME "@CFAPI_SHELLEXT_APPID_DISPLAY_NAME@" + +#cmakedefine CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID "@CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID@" +#cmakedefine CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID_REG "@CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_CLASS_ID_REG@" +#cmakedefine CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_DISPLAY_NAME "@CFAPI_SHELLEXT_CUSTOM_STATE_HANDLER_DISPLAY_NAME@" + +#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID@" +#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG@" +#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME@" + +#cmakedefine CFAPI_SHELL_EXTENSIONS_LIB_NAME "@CFAPI_SHELL_EXTENSIONS_LIB_NAME@" + +#cmakedefine01 NEXTCLOUD_DEV + +#cmakedefine WITH_WEBENGINE + +#cmakedefine01 CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN + +#cmakedefine ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH "@ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH@" + +#endif diff --git a/craftmaster.ini b/craftmaster.ini new file mode 100644 index 000000000..d9f2073ee --- /dev/null +++ b/craftmaster.ini @@ -0,0 +1,64 @@ +[General] +Branch = master +ShallowClone = True +# CraftUrl = https://github.com/allexzander/craft.git + +# Variables defined here override the default value +# The variable names are casesensitive +[Variables] +#Values need to be overwritten to create a cache +UseCache = True +CreateCache = False + +# Settings applicable for all Crafts matrices +# Settings are Category/key=value +# Category is case sensitive +[GeneralSettings] + +General/MacDeploymentTarget = 11.0 + +Compile/BuildType = RelWithDebInfo + +Compile/UseNinja = True + +ShortPath/Enabled = False +ShortPath/EnableJunctions = False + +Packager/CacheVersion = 25.01 +ContinuousIntegration/Enabled = True + +Packager/UseCache = ${Variables:UseCache} +Packager/CreateCache = ${Variables:CreateCache} +Packager/CacheDir = ${Variables:Root}\cache + +[BlueprintSettings] +nextcloud-client.buildTests = True +binary/mysql.useMariaDB = False +libs/qt6.version = 6.8.2 + +[windows-msvc2022_64-cl] +Packager/PackageType = NullsoftInstallerPackager +QtSDK/Compiler = msvc2022_64 +General/ABI = windows-msvc2022_64-cl +Paths/Python = C:\Python312-x64 + +[macos-64-clang] +General/ABI = macos-64-clang + +Packager/RepositoryUrl = https://download.nextcloud.com/desktop/development/craftCache/ +Packager/CacheVersion = 25.03-nc + +[macos-clang-arm64] +General/ABI = macos-clang-arm64 +Paths/Python = /Users/runner/hostedtoolcache/Python/3.12.3/arm64 + +Packager/RepositoryUrl = https://download.nextcloud.com/desktop/development/craftCache/ +Packager/CacheVersion = 25.03-nc + +[Env] +CRAFT_CODESIGN_CERTIFICATE = +SIGN_PACKAGE = False + +[Custom_Variables_for_Brander] +qtPath = /opt/qt +dockerImage = ghcr.io/nextcloud/continuous-integration-client-appimage-qt6:client-appimage-el8-6.8.2-1 diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 000000000..4e9b6386b --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,93 @@ +if(SPHINX_FOUND) + + # Sphinx cache with pickled ReST documents + set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees") + # HTML output directory + set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html") + set(SPHINX_PDF_DIR "${CMAKE_CURRENT_BINARY_DIR}/latex") + set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp") + set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp") + set(MSHTML_COMPILER wine 'C:\\Program Files\\HTML Help Workshop\\hhc.exe') + # assets + set(LATEX_LOGO "${CMAKE_CURRENT_SOURCE_DIR}/logo-blue.pdf") + + set(APPLICATION_DOC_DIR "${CMAKE_INSTALL_DOCDIR}/${PACKAGE}") + install(DIRECTORY ${SPHINX_HTML_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL) + install(DIRECTORY ${SPHINX_PDF_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL) + install(DIRECTORY ${SPHINX_QCH_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL) + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/conf.py" conf.py COPYONLY) + + if(WITH_DOC) + add_custom_target(doc ALL DEPENDS doc-html COMMENT "Building documentation...") + else(WITH_DOC) + add_custom_target(doc DEPENDS doc-html COMMENT "Building documentation...") + endif(WITH_DOC) + + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ocdoc/_shared_assets") + add_dependencies(doc doc-html-org) + add_dependencies(doc doc-html-com) + endif() + + if(PDFLATEX_FOUND) + # if this still fails on Debian/Ubuntu, run + # apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended + add_custom_target(doc-latex ${SPHINX_EXECUTABLE} + -q -c . -b latex + -d ${SPHINX_CACHE_DIR}/latex + -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 + DEPENDS doc-latex ) + add_dependencies(doc doc-pdf) + endif(PDFLATEX_FOUND) + if (EXISTS ${QT_QCOLLECTIONGENERATOR_EXECUTABLE}) + add_custom_target( doc-qch-sphinx ${SPHINX_EXECUTABLE} + -q -c . -b qthelp + -d ${SPHINX_CACHE_DIR}/qthelp + ${CMAKE_CURRENT_SOURCE_DIR} + ${SPHINX_QCH_DIR} ) + add_custom_target( doc-qch ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} + ${SPHINX_QCH_DIR}/*.qhcp + DEPENDS doc-qch-sphinx ) + add_dependencies(doc doc-qch) + endif() + add_custom_target( doc-html ${SPHINX_EXECUTABLE} + -q -c . -b html + -d ${SPHINX_CACHE_DIR}/html + ${CMAKE_CURRENT_SOURCE_DIR} + ${SPHINX_HTML_DIR}/unthemed ) + add_custom_target( doc-html-org ${SPHINX_EXECUTABLE} + -q -c . -b html + -d ${SPHINX_CACHE_DIR}/html + -D html_theme=owncloud_org + ${CMAKE_CURRENT_SOURCE_DIR} + ${SPHINX_HTML_DIR}/org ) + add_custom_target( doc-html-com ${SPHINX_EXECUTABLE} + -q -c . -b html + -d ${SPHINX_CACHE_DIR}/html + -D html_theme=owncloud_com + ${CMAKE_CURRENT_SOURCE_DIR} + ${SPHINX_HTML_DIR}/com ) + + ## Building CHM files requires HTML Help Workshop. Since it requires wine + ## with special dependencies, it's impossible to write a cmake check for it. + ## This is why doc-chm is not a dependency for doc. Instead, run + ## doc/scripts/htmlhelp.exe to install them and run this target + ## explicitly. + add_custom_target( doc-chm-sphinx ${SPHINX_EXECUTABLE} + -q -c . -b htmlhelp + -D html_theme=basic + -d ${SPHINX_CACHE_DIR}/htmlhelp + ${CMAKE_CURRENT_SOURCE_DIR} + ${SPHINX_HTMLHELP_DIR} ) + add_custom_target( doc-chm pushd ${SPHINX_HTMLHELP_DIR}; ${MSHTML_COMPILER} *.hhp; popd + DEPENDS doc-chm-sphinx ) +endif(SPHINX_FOUND) \ No newline at end of file diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000..7932760b0 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,169 @@ + +# 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 ' where 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-com + +html-all: html-release html-com + +html-release: + $(SPHINXBUILD) -b html -D html_theme='nextcloud_release' $(ALLSPHINXOPTS) $(BUILDDIR)/html/release + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html/release." + +html-com: + $(SPHINXBUILD) -b html -D html_theme='nextcloud_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." diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 000000000..69d828a99 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,35 @@ +# Desktop client documentation + +The main nextcloud Documentation is found at https://github.com/nextcloud/documentation + +The rst files from the current stable branch will be parsed with sphinx to be used at https://docs.nextcloud.com/desktop/latest/ + +## Dependencies + +You will need to have [Sphinx](https://www.sphinx-doc.org), which comes packaged with Python 3. + +In addition, run the following to install PdfLatex and Doxygen. + +- On Linux: +``` +$ sudo apt install doxygen python texlive-latex-base texlive-latex-extra +``` +> Note: You may use something other than `apt` depending on your distribution. + +- On macOS (via [Homebrew](https://brew.sh/)): +``` +% brew install basictex doxygen python +``` + +## How to build the documentation + +In your repositories directory: + +``` +$ git clone https://github.com/nextcloud/desktop.git +$ cd desktop +$ cd doc +$ sphinx-build -b html -D html_theme='nextcloud_com' -d _build/doctrees . _build/html/com +``` + +The documentation html files will be at ```desktop/docs/_build/html/com```. diff --git a/doc/_shared_assets/static/logo-blue.pdf b/doc/_shared_assets/static/logo-blue.pdf new file mode 100644 index 0000000000000000000000000000000000000000..10429b550d884ac69a9de0d25c971cd6b02d2a30 GIT binary patch literal 8943 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 HEyMo@0-wql literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/diaspora.svg b/doc/_shared_assets/static/social/diaspora.svg new file mode 100644 index 000000000..d8c200a06 --- /dev/null +++ b/doc/_shared_assets/static/social/diaspora.svg @@ -0,0 +1,57 @@ + +image/svg+xml \ No newline at end of file diff --git a/doc/_shared_assets/static/social/diasporaround.png b/doc/_shared_assets/static/social/diasporaround.png new file mode 100644 index 0000000000000000000000000000000000000000..31bb1fe07113588222c47fbcdc0e212bed252f43 GIT binary patch literal 2601 zcmV+^3fA?BP)ba_ujq0^8E*9 z?>*<9?>WEU@BDth^H6XE9`b7b6LGX7fiCoG6#9}tN7@>^9-@p=u5cP3`#C1d>UTs75J|@e2n81dn96iK zhK)ByA-h?xxZ0Lj8k-5aX ztd>D*2Ea6t>S{$V=CgqIG&K&fj6L@awBsWpX0U=}nghj))m-B>J(BiAq_XzG$UUjOfWfNNfc}dQ&KUBPiAr ztr&p$JW6YT%G;t(zL9994^i@H=UmLHXYCc|$gEd>6sk4D%7e^^>f&EK5q*d(o^`Vk=hZ7WeTkogYiNNDoE&0DySz z%02w-=W|X`Nv!EcXaot;ozXl^3LR>^*RBj@m-X~bH+s2fM<1)@g7oLxwQ)ckNhI+C zC&}Rug_JjN-W$d#u_Q8>@r-I*>XMRt1(S(LnpM-G; zcR9#T^0{ti)w}@_>tzT~#Cfvm&sfILpZExu83Wv=fL-jN7{%tYjLU{N)~LM31^&(k z+@z6(u(_b(=Ku#eNeKbe2=X5;D(x0kP*4d_$XPbild()`JEKWR)Rt&#UD*vugcxPpeup%p%rt2k6q8#Kp)PI0CNU|~Mg(q^sL>HQ#V=_%{AxdNcnxj-yZcyeFjV>%QJ-
J1WUQ-qQ zm}l^;khKQQ9m?y@h*v2W)x0Y5Bkz#*{Mx{czQ?lt^!|iAu_Q_W2V8g)BFJql>$~8G}p}%h*VSd$$$#-HajCR zy50Ddfzd5xIb|q7EIE8?P{R|v9O;PUfSLiY!G0aFETzA}v%hh=jw|>_E*ZQxo1u{? zeSX3*P!9u2E@$o45oChln)X3Hspm-*^Oix((2>P-urFTgc4!`Az(XjYq%y*ewTfpY zopqmm!y<0ibLnF!LN!QSbmulcd*NBBw#a|u5-Q~33$odc=};(VIfXh;D*1pb4T4XV zbsW=udmS6>gsK4hl)`i#Y^vGK8GEjpkGX7Z@cTA)>-KLsZ#D3U{QQ#l3D|Y$v(+je zHCuuNGT^SXw?M6OhrN{IsiW2>SVB;@VJg?S#uIf&`dGkGTT2oETx4Nh1^0>g0e1m2 ztmn9D4F{4zbO+!T%eZ7H?<(i%SCh-HU@a>twJTHrzmdD{Yajp_!6>Scz}_# z7Q7_?Sy%UJF@nMn%edQ0Xk^!=QE!)NF&989Tt8BvfRCiuB5flQP)$ zn;GFlZN1O(qPd+5UXYBV)XSSZ?eO85i+rH2$+fl098n@ec$vxMMmIQ`K`Hy$#5Q@O zI-k>wL~1UjQi*3IFEfz@+a&T?$5sldk_;fx=CxrCZ3PkC$mA)~=}R|LTiG;9xy%Xn zvm@cy4$b~`R1OmX@Dhrr6K)2PMz1h6-=TnGT;ww4G5}88cLx6l;)uTyn^^&}00000 LNkvXXu0mjfNovz? literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/facebook.png b/doc/_shared_assets/static/social/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..6b257be758e0f9c7b78cd8bd41c0c0d13da74753 GIT binary patch literal 2493 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 Hu0mjf#2|i$ literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/googleplus.png b/doc/_shared_assets/static/social/googleplus.png new file mode 100644 index 0000000000000000000000000000000000000000..7e12bce4485e381976c70699db83f01e067c4b6f GIT binary patch literal 4334 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 literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/mail.png b/doc/_shared_assets/static/social/mail.png new file mode 100644 index 0000000000000000000000000000000000000000..62157ad36b6e0c266f32b7d80dbae3de49a18bd2 GIT binary patch literal 4230 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

+jgE37?c7 z5`TUD&jo{ec0JTnNtXWc(G7+u)ysq#)YbM61Erv?Wsa?ff1A4ogSawoGUVMW<%dki zBIi!E@c!(5WSH-UQ3}y5Iom5;FCO}B?khu;CCdpcKU{ip{H*A2c|ChC%QFFT$Q&uS zt( z?o?8b;K-VL7O~8F&HZs*aeMZ;KY!)5t0p zXpG!KRzv)KVn-)L2Q@p}#lyDi!rmigHT$u>*z1wvJ|AwASEq#rC8{#iMkbB(W9F)~ zjBa!6-pWTfarVgeHk6I4;G4l#_1jbS-N zfF*uZq&g64BrMTU_s^LRhzbG~sTGv85tdjXQk&$)Wzi*8iFQ=BH@IspUkN`H7ax#+ c*Nsg4KVuNaLEA}RjQ{`u07*qoM6N<$f)r;cCjbBd literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/mail.svg b/doc/_shared_assets/static/social/mail.svg new file mode 100644 index 000000000..299613d7a --- /dev/null +++ b/doc/_shared_assets/static/social/mail.svg @@ -0,0 +1,77 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/doc/_shared_assets/static/social/rss.png b/doc/_shared_assets/static/social/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..8192f1cee37eb88dd56ca9c3314916edefdb3c92 GIT binary patch literal 4400 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 +image/svg+xml \ No newline at end of file diff --git a/doc/_shared_assets/static/social/twitter.svg b/doc/_shared_assets/static/social/twitter.svg new file mode 100644 index 000000000..640529878 --- /dev/null +++ b/doc/_shared_assets/static/social/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/_shared_assets/static/social/twitterround.png b/doc/_shared_assets/static/social/twitterround.png new file mode 100644 index 0000000000000000000000000000000000000000..f7db3093391655683db94babe939d0e620a71d77 GIT binary patch literal 3719 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 literal 0 HcmV?d00001 diff --git a/doc/_shared_assets/static/social/youtube.svg b/doc/_shared_assets/static/social/youtube.svg new file mode 100644 index 000000000..de5c7af01 --- /dev/null +++ b/doc/_shared_assets/static/social/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/_shared_assets/themes/bootstrap/globaltoc.html b/doc/_shared_assets/themes/bootstrap/globaltoc.html new file mode 100644 index 000000000..cb9f38fb6 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/globaltoc.html @@ -0,0 +1,4 @@ +

diff --git a/doc/_shared_assets/themes/bootstrap/layout.html b/doc/_shared_assets/themes/bootstrap/layout.html new file mode 100644 index 000000000..c3febbe48 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/layout.html @@ -0,0 +1,134 @@ +{% extends "basic/layout.html" %} +{% set script_files = script_files + ['_static/bootstrap.js'] %} +{% set css_files = ['_static/bootstrap.css', '_static/bootstrap-sphinx.css'] + css_files %} + +{# Sidebar: Rework into our Bootstrap nav section. #} +{% macro navBar() %} + + +{% endmacro %} + +{%- block extrahead %} + +{% endblock %} + +{% block header %}{{ navBar() }}{% endblock %} + +{# Silence the sidebar's, relbar's #} +{% block sidebar1 %}{% endblock %} +{% block sidebar2 %}{% endblock %} +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} + +{%- block content %} +
+ {% block body %} {% endblock %} +
+{%- endblock %} + +{%- block footer %} +
+
+

Back to top

+

+ {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
+ {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
+ {%- endif %} + {%- endif %} + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+ {%- endif %} + {%- if show_sphinx %} + {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %}
+ {%- endif %} +

+
+
+{%- endblock %} + diff --git a/doc/_shared_assets/themes/bootstrap/localtoc.html b/doc/_shared_assets/themes/bootstrap/localtoc.html new file mode 100644 index 000000000..c47d98801 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/localtoc.html @@ -0,0 +1,5 @@ + diff --git a/doc/_shared_assets/themes/bootstrap/relations.html b/doc/_shared_assets/themes/bootstrap/relations.html new file mode 100644 index 000000000..b3df68e3b --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/relations.html @@ -0,0 +1,8 @@ +{%- if prev %} +
  • {{ "«"|safe }} {{ prev.title }}
  • +{%- endif %} +{%- if next %} +
  • {{ next.title }} {{ "»"|safe }}
  • +{%- endif %} diff --git a/doc/_shared_assets/themes/bootstrap/searchbox.html b/doc/_shared_assets/themes/bootstrap/searchbox.html new file mode 100644 index 000000000..67852e6f8 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/searchbox.html @@ -0,0 +1,7 @@ +{%- if pagename != "search" %} + +{%- endif %} diff --git a/doc/_shared_assets/themes/bootstrap/sourcelink.html b/doc/_shared_assets/themes/bootstrap/sourcelink.html new file mode 100644 index 000000000..21ae2d8fe --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/sourcelink.html @@ -0,0 +1,4 @@ +{%- if show_source and has_source and sourcename %} +
  • {{ _('Source') }}
  • +{%- endif %} diff --git a/doc/_shared_assets/themes/bootstrap/static/bootstrap-responsive.css b/doc/_shared_assets/themes/bootstrap/static/bootstrap-responsive.css new file mode 100644 index 000000000..dd134a1bd --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/static/bootstrap-responsive.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.0.3 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}@media(max-width:767px){.visible-phone{display:inherit!important}.hidden-phone{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(min-width:768px) and (max-width:979px){.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:18px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{position:absolute;top:10px;right:10px;left:10px;width:auto;margin:0}.modal.fade.in{top:auto}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.762430939%;*margin-left:2.709239449638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.999999993%;*width:99.9468085036383%}.row-fluid .span11{width:91.436464082%;*width:91.38327259263829%}.row-fluid .span10{width:82.87292817100001%;*width:82.8197366816383%}.row-fluid .span9{width:74.30939226%;*width:74.25620077063829%}.row-fluid .span8{width:65.74585634900001%;*width:65.6926648596383%}.row-fluid .span7{width:57.182320438000005%;*width:57.129128948638304%}.row-fluid .span6{width:48.618784527%;*width:48.5655930376383%}.row-fluid .span5{width:40.055248616%;*width:40.0020571266383%}.row-fluid .span4{width:31.491712705%;*width:31.4385212156383%}.row-fluid .span3{width:22.928176794%;*width:22.874985304638297%}.row-fluid .span2{width:14.364640883%;*width:14.311449393638298%}.row-fluid .span1{width:5.801104972%;*width:5.747913482638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:714px}input.span11,textarea.span11,.uneditable-input.span11{width:652px}input.span10,textarea.span10,.uneditable-input.span10{width:590px}input.span9,textarea.span9,.uneditable-input.span9{width:528px}input.span8,textarea.span8,.uneditable-input.span8{width:466px}input.span7,textarea.span7,.uneditable-input.span7{width:404px}input.span6,textarea.span6,.uneditable-input.span6{width:342px}input.span5,textarea.span5,.uneditable-input.span5{width:280px}input.span4,textarea.span4,.uneditable-input.span4{width:218px}input.span3,textarea.span3,.uneditable-input.span3{width:156px}input.span2,textarea.span2,.uneditable-input.span2{width:94px}input.span1,textarea.span1,.uneditable-input.span1{width:32px}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.564102564%;*margin-left:2.510911074638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145300001%;*width:91.3997999636383%}.row-fluid .span10{width:82.905982906%;*width:82.8527914166383%}.row-fluid .span9{width:74.358974359%;*width:74.30578286963829%}.row-fluid .span8{width:65.81196581200001%;*width:65.7587743226383%}.row-fluid .span7{width:57.264957265%;*width:57.2117657756383%}.row-fluid .span6{width:48.717948718%;*width:48.6647572286383%}.row-fluid .span5{width:40.170940171000005%;*width:40.117748681638304%}.row-fluid .span4{width:31.623931624%;*width:31.5707401346383%}.row-fluid .span3{width:23.076923077%;*width:23.0237315876383%}.row-fluid .span2{width:14.529914530000001%;*width:14.4767230406383%}.row-fluid .span1{width:5.982905983%;*width:5.929714493638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:1160px}input.span11,textarea.span11,.uneditable-input.span11{width:1060px}input.span10,textarea.span10,.uneditable-input.span10{width:960px}input.span9,textarea.span9,.uneditable-input.span9{width:860px}input.span8,textarea.span8,.uneditable-input.span8{width:760px}input.span7,textarea.span7,.uneditable-input.span7{width:660px}input.span6,textarea.span6,.uneditable-input.span6{width:560px}input.span5,textarea.span5,.uneditable-input.span5{width:460px}input.span4,textarea.span4,.uneditable-input.span4{width:360px}input.span3,textarea.span3,.uneditable-input.span3{width:260px}input.span2,textarea.span2,.uneditable-input.span2{width:160px}input.span1,textarea.span1,.uneditable-input.span1{width:60px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top{position:static;margin-bottom:18px}.navbar-fixed-top .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 9px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#999;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#222}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222;border-bottom:1px solid #222;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/doc/_shared_assets/themes/bootstrap/static/bootstrap-sphinx.css_t b/doc/_shared_assets/themes/bootstrap/static/bootstrap-sphinx.css_t new file mode 100644 index 000000000..965aa9ecf --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/static/bootstrap-sphinx.css_t @@ -0,0 +1,24 @@ +/* +* bootstrap-sphinx.css +* ~~~~~~~~~~~~~~~~~~~~ +* +* Sphinx stylesheet -- Twitter Bootstrap theme. +*/ + +body { + padding-top: 52px; +} + +.navbar .brand { + color: #FFF; + text-shadow: #777 2px 2px 3px; +} + +{%- block sidebarlogo %} + {%- if logo %} +.navbar h3 a, .navbar .brand { + background: transparent url("{{ logo }}") no-repeat 22px 3px; + padding-left: 62px; +} + {%- endif %} +{%- endblock %} diff --git a/doc/_shared_assets/themes/bootstrap/static/bootstrap.css b/doc/_shared_assets/themes/bootstrap/static/bootstrap.css new file mode 100644 index 000000000..1c75d0c07 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/static/bootstrap.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.0.3 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.127659574%;*margin-left:2.0744680846382977%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%}.row-fluid .span11{width:91.489361693%;*width:91.4361702036383%}.row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%}.row-fluid .span9{width:74.468085099%;*width:74.4148936096383%}.row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%}.row-fluid .span7{width:57.446808505%;*width:57.3936170156383%}.row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%}.row-fluid .span5{width:40.425531911%;*width:40.3723404216383%}.row-fluid .span4{width:31.914893614%;*width:31.8617021246383%}.row-fluid .span3{width:23.404255317%;*width:23.3510638276383%}.row-fluid .span2{width:14.89361702%;*width:14.8404255306383%}.row-fluid .span1{width:6.382978723%;*width:6.329787233638298%}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;content:""}.container-fluid:after{clear:both}p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px}p small{font-size:11px;color:#999}.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px}h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999}h1{font-size:30px;line-height:36px}h1 small{font-size:18px}h2{font-size:24px;line-height:36px}h2 small{font-size:18px}h3{font-size:18px;line-height:27px}h3 small{font-size:14px}h4,h5,h6{line-height:18px}h4{font-size:14px}h4 small{font-size:12px}h5{font-size:12px}h6{font-size:11px;color:#999;text-transform:uppercase}.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eee}.page-header h1{line-height:1}ul,ol{padding:0;margin:0 0 9px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}ul{list-style:disc}ol{list-style:decimal}li{line-height:18px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}dl{margin-bottom:18px}dt,dd{line-height:18px}dt{font-weight:bold;line-height:17px}dd{margin-left:9px}.dl-horizontal dt{float:left;width:120px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:130px}hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}strong{font-weight:bold}em{font-style:italic}.muted{color:#999}abbr[title]{cursor:help;border-bottom:1px dotted #ddd}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px}blockquote small{display:block;line-height:18px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:18px;font-style:normal;line-height:18px}small{font-size:100%}cite{font-style:normal}code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:18px}pre code{padding:0;color:inherit;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 18px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333;border:0;border-bottom:1px solid #eee}legend small{font-size:13.5px;color:#999}label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:18px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px;color:#333}input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.uneditable-textarea{width:auto;height:auto}label input,label textarea,label select{display:block}input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer;background-color:transparent;border:0 \9;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}input[type="image"]{border:0}input[type="file"]{width:auto;padding:initial;line-height:initial;background-color:#fff;background-color:initial;border:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto}select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px}input[type="file"]{line-height:18px \9}select{width:220px;background-color:#fff}select[multiple],select[size]{height:auto}input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}textarea{height:auto}input[type="hidden"]{display:none}.radio,.checkbox{min-height:18px;padding-left:18px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}input:focus,textarea:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus,select:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:930px}input.span11,textarea.span11,.uneditable-input.span11{width:850px}input.span10,textarea.span10,.uneditable-input.span10{width:770px}input.span9,textarea.span9,.uneditable-input.span9{width:690px}input.span8,textarea.span8,.uneditable-input.span8{width:610px}input.span7,textarea.span7,.uneditable-input.span7{width:530px}input.span6,textarea.span6,.uneditable-input.span6{width:450px}input.span5,textarea.span5,.uneditable-input.span5{width:370px}input.span4,textarea.span4,.uneditable-input.span4{width:290px}input.span3,textarea.span3,.uneditable-input.span3{width:210px}input.span2,textarea.span2,.uneditable-input.span2{width:130px}input.span1,textarea.span1,.uneditable-input.span1{width:50px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee;border-color:#ddd}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;*zoom:1}.form-actions:before,.form-actions:after{display:table;content:""}.form-actions:after{clear:both}.uneditable-input{overflow:hidden;white-space:nowrap;cursor:not-allowed;background-color:#fff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}:-moz-placeholder{color:#999}::-webkit-input-placeholder{color:#999}.help-block,.help-inline{color:#555}.help-block{display:block;margin-bottom:9px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-prepend,.input-append{margin-bottom:5px}.input-prepend input,.input-append input,.input-prepend select,.input-append select,.input-prepend .uneditable-input,.input-append .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:middle;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend input:focus,.input-append input:focus,.input-prepend select:focus,.input-append select:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{z-index:2}.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc}.input-prepend .add-on,.input-append .add-on{display:inline-block;width:auto;height:18px;min-width:16px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc}.input-prepend .add-on,.input-append .add-on,.input-prepend .btn,.input-append .btn{margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append .uneditable-input{border-right-color:#ccc;border-left-color:#eee}.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:9px}legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:18px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:160px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:160px}.form-horizontal .help-block{margin-top:9px;margin-bottom:0}.form-horizontal .form-actions{padding-left:160px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:18px}.table th,.table td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}.table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5}table .span1{float:none;width:44px;margin-left:0}table .span2{float:none;width:124px;margin-left:0}table .span3{float:none;width:204px;margin-left:0}table .span4{float:none;width:284px;margin-left:0}table .span5{float:none;width:364px;margin-left:0}table .span6{float:none;width:444px;margin-left:0}table .span7{float:none;width:524px;margin-left:0}table .span8{float:none;width:604px;margin-left:0}table .span9{float:none;width:684px;margin-left:0}table .span10{float:none;width:764px;margin-left:0}table .span11{float:none;width:844px;margin-left:0}table .span12{float:none;width:924px;margin-left:0}table .span13{float:none;width:1004px;margin-left:0}table .span14{float:none;width:1084px;margin-left:0}table .span15{float:none;width:1164px;margin-left:0}table .span16{float:none;width:1244px;margin-left:0}table .span17{float:none;width:1324px;margin-left:0}table .span18{float:none;width:1404px;margin-left:0}table .span19{float:none;width:1484px;margin-left:0}table .span20{float:none;width:1564px;margin-left:0}table .span21{float:none;width:1644px;margin-left:0}table .span22{float:none;width:1724px;margin-left:0}table .span23{float:none;width:1804px;margin-left:0}table .span24{float:none;width:1884px;margin-left:0}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0}.icon-white{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";opacity:.3;filter:alpha(opacity=30)}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown:hover .caret,.open .caret{opacity:1;filter:alpha(opacity=100)}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:4px 0;margin:1px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#08c}.open{*z-index:1000}.open .dropdown-menu{display:block}.pull-right .dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:"\2191"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0,0,0,0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1;filter:alpha(opacity=100)}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-ms-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 10px 4px;margin-bottom:0;*margin-left:.3em;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.btn-large [class^="icon-"]{margin-top:1px}.btn-small{padding:5px 9px;font-size:11px;line-height:16px}.btn-small [class^="icon-"]{margin-top:-1px}.btn-mini{padding:2px 6px;font-size:11px;line-height:14px}.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn-primary{background-color:#0074cc;*background-color:#05c;background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:-moz-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;border-color:#05c #05c #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#05c;*background-color:#004ab3}.btn-primary:active,.btn-primary.active{background-color:#004099 \9}.btn-warning{background-color:#faa732;*background-color:#f89406;background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{background-color:#da4f49;*background-color:#bd362f;background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{background-color:#5bb75b;*background-color:#51a351;background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{background-color:#49afcd;*background-color:#2f96b4;background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{background-color:#414141;*background-color:#222;background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:-moz-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-group{position:relative;*margin-left:.3em;*zoom:1}.btn-group:before,.btn-group:after{display:table;content:""}.btn-group:after{clear:both}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:9px;margin-bottom:9px}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}.btn-group>.btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.dropdown-toggle{*padding-top:4px;padding-right:8px;*padding-bottom:4px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini.dropdown-toggle{padding-right:5px;padding-left:5px}.btn-group>.btn-small.dropdown-toggle{*padding-top:4px;*padding-bottom:4px}.btn-group>.btn-large.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#05c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:7px;margin-left:0}.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100)}.btn-mini .caret{margin-top:5px}.btn-small .caret{margin-top:6px}.btn-large .caret{margin-top:6px;border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-top:0;border-bottom:5px solid #000}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:.75;filter:alpha(opacity=75)}.alert{padding:8px 35px 8px 14px;margin-bottom:18px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert-heading{color:inherit}.alert .close{position:relative;top:-2px;right:-21px;line-height:18px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:18px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>.pull-right{float:right}.nav .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:18px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:18px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px}.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333;border-bottom-color:#333}.nav>.dropdown.active>a:hover{color:#000;cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.navbar{*position:relative;*z-index:2;margin-bottom:18px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top,#333,#222);background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1)}.navbar .container{width:auto}.nav-collapse.collapse{height:auto}.navbar{color:#999}.navbar .brand:hover{text-decoration:none}.navbar .brand{display:block;float:left;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#999}.navbar .navbar-text{margin-bottom:0;line-height:40px}.navbar .navbar-link{color:#999}.navbar .navbar-link:hover{color:#fff}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn{margin:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#fff;background-color:#626262;border:1px solid #151515;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-bottom{bottom:0}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right}.navbar .nav>li{display:block;float:left}.navbar .nav>li>a{float:none;padding:9px 10px 11px;line-height:19px;color:#999;text-decoration:none;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar .btn{display:inline-block;padding:4px 10px 4px;margin:5px 5px 6px;line-height:18px}.navbar .btn-group{padding:5px 5px 6px;margin:0}.navbar .nav>li>a:hover{color:#fff;text-decoration:none;background-color:transparent}.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#fff;text-decoration:none;background-color:#222}.navbar .divider-vertical{width:1px;height:40px;margin:0 9px;overflow:hidden;background-color:#222;border-right:1px solid #333}.navbar .nav.pull-right{margin-right:0;margin-left:10px}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;background-color:#2c2c2c;*background-color:#222;background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-image:-moz-linear-gradient(top,#333,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{background-color:#222;*background-color:#151515}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#080808 \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown .dropdown-toggle .caret,.navbar .nav li.dropdown.open .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar .nav li.dropdown.active .caret{opacity:1;filter:alpha(opacity=100)}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:transparent}.navbar .nav li.dropdown.active>.dropdown-toggle:hover{color:#fff}.navbar .pull-right .dropdown-menu,.navbar .dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right .dropdown-menu:before,.navbar .dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right .dropdown-menu:after,.navbar .dropdown-menu.pull-right:after{right:13px;left:auto}.breadcrumb{padding:7px 14px;margin:0 0 18px;list-style:none;background-color:#fbfbfb;background-image:-moz-linear-gradient(top,#fff,#f5f5f5);background-image:-ms-linear-gradient(top,#fff,#f5f5f5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#fff,#f5f5f5);background-image:-o-linear-gradient(top,#fff,#f5f5f5);background-image:linear-gradient(top,#fff,#f5f5f5);background-repeat:repeat-x;border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#f5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.breadcrumb li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb .divider{padding:0 5px;color:#999}.breadcrumb .active a{color:#333}.pagination{height:36px;margin:18px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination li{display:inline}.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0}.pagination a:hover,.pagination .active a{background-color:#f5f5f5}.pagination .active a{color:#999;cursor:default}.pagination .disabled span,.pagination .disabled a,.pagination .disabled a:hover{color:#999;cursor:default;background-color:transparent}.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pager{margin-bottom:18px;margin-left:0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;content:""}.pager:after{clear:both}.pager li{display:inline}.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next a{float:right}.pager .previous a{float:left}.pager .disabled a,.pager .disabled a:hover{color:#999;cursor:default;background-color:#fff}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2070}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:50%;left:50%;z-index:1050;width:560px;margin:-250px 0 0 -280px;overflow:auto;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-ms-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:50%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-body{max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.tooltip{position:absolute;z-index:1020;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-2px}.tooltip.right{margin-left:2px}.tooltip.bottom{margin-top:2px}.tooltip.left{margin-left:-2px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px}.popover.top{margin-top:-5px}.popover.right{margin-left:5px}.popover.bottom{margin-top:5px}.popover.left{margin-left:-5px}.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.popover .arrow{position:absolute;width:0;height:0}.popover-inner{width:280px;padding:3px;overflow:hidden;background:#000;background:rgba(0,0,0,0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3)}.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:18px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:0 1px 1px rgba(0,0,0,0.075);box-shadow:0 1px 1px rgba(0,0,0,0.075)}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px}.label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:18px;margin-bottom:18px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-ms-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(top,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5',endColorstr='#f9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{width:0;height:18px;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(top,#149bdf,#0480be);background-image:-ms-linear-gradient(top,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf',endColorstr='#0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-ms-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .bar{background-color:#149bdf;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-ms-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(top,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35',GradientType=0)}.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-ms-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(top,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#57a957',GradientType=0)}.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-ms-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(top,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#339bb9',GradientType=0)}.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0)}.progress-warning.progress-striped .bar{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:18px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:18px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel .item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-ms-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel .item>img{display:block;line-height:1}.carousel .active,.carousel .next,.carousel .prev{display:block}.carousel .active{left:0}.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}.carousel .next{left:100%}.carousel .prev{left:-100%}.carousel .next.left,.carousel .prev.right{left:0}.carousel .active.left{left:-100%}.carousel .active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:10px 15px 5px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{color:#fff}.hero-unit{padding:60px;margin-bottom:30px;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit p{font-size:18px;font-weight:200;line-height:27px;color:inherit}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden} diff --git a/doc/_shared_assets/themes/bootstrap/static/bootstrap.js b/doc/_shared_assets/themes/bootstrap/static/bootstrap.js new file mode 100644 index 000000000..1f87730a3 --- /dev/null +++ b/doc/_shared_assets/themes/bootstrap/static/bootstrap.js @@ -0,0 +1,6 @@ +/*! +* Bootstrap.js by @fat & @mdo +* Copyright 2012 Twitter, Inc. +* http://www.apache.org/licenses/LICENSE-2.0.txt +*/ +!function(a){a(function(){"use strict",a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=c,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},to:function(b){var c=this.$element.find(".active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(a){return a||(this.paused=!0),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j=a.Event("slide");this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h]();if(e.hasClass("active"))return;if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c);e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):typeof c=="string"||(c=f.slide)?e[c]():f.interval&&e.cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning)return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning)return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){a(b).parent().removeClass("open")}"use strict";var b='[data-toggle="dropdown"]',c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),e,f,g;if(c.is(".disabled, :disabled"))return;return f=c.attr("data-target"),f||(f=c.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,"")),e=a(f),e.length||(e=c.parent()),g=e.hasClass("open"),d(),g||e.toggleClass("open"),!1}},a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a(function(){a("html").on("click.dropdown.data-api",d),a("body").on("click.dropdown",".dropdown form",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle)})}(window.jQuery),!function(a){function c(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),d.call(b)},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),d.call(b)})}function d(a){this.$element.hide().trigger("hidden"),e.call(this)}function e(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('