├── .gitignore ├── .gitmodules ├── 3rdparty └── build_android_openssl.sh ├── CHANGELOG ├── CMakeLists.txt ├── LICENSE.GPL ├── LICENSE.LGPL ├── README.md ├── TODO ├── click ├── click.pro ├── ghostcloud.png ├── harbour-owncloud.accounts ├── harbour-owncloud.apparmor ├── harbour-owncloud.desktop ├── manifest.json.in ├── run-daemon.sh └── run.sh ├── clickable-ut-photo-backup.json ├── clickable.json ├── harbour-owncloud.pro ├── misc ├── notes │ └── multi_account_transfer.txt └── readme │ ├── cover.png │ ├── filebrowser.png │ ├── filedetails.png │ ├── mediapreview.png │ └── userinfo.png ├── rpm ├── harbour-owncloud.changes.in ├── harbour-owncloud.spec └── harbour-owncloud.yaml ├── snap ├── gui │ ├── harbour-owncloud.desktop │ └── harbour-owncloud.png └── snapcraft.yaml ├── src ├── CMakeLists.txt ├── app │ ├── CMakeLists.txt │ ├── android │ │ ├── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── res │ │ │ ├── drawable-ldpi │ │ │ │ └── icon.png │ │ │ ├── drawable-mdpi │ │ │ │ └── icon.png │ │ │ └── values │ │ │ │ └── libs.xml │ │ └── src │ │ │ └── me │ │ │ └── fredl │ │ │ └── ghostcloud │ │ │ └── ShareUtil.java │ ├── app.pro │ ├── harbour-owncloud.desktop │ ├── icons.qrc │ ├── icons │ │ ├── 108x108 │ │ │ └── harbour-owncloud.png │ │ ├── 128x128 │ │ │ └── harbour-owncloud.png │ │ ├── 172x172 │ │ │ └── harbour-owncloud.png │ │ ├── 86x86 │ │ │ └── harbour-owncloud.png │ │ ├── banner.png │ │ ├── harbour-owncloud.svg │ │ ├── harbour-owncloud_512.png │ │ ├── icon_gray.svg │ │ └── theme │ ├── ios │ │ └── Info.plist │ ├── macos │ │ └── Info.plist │ ├── qml-sfos.qrc │ ├── qml.qrc │ ├── qml │ │ ├── dummy │ │ │ └── FileSelectionDialog.qml │ │ ├── qqc │ │ │ ├── BrowserCommandPageFlow.qml │ │ │ ├── CommandPageFlow.qml │ │ │ ├── controls │ │ │ │ └── GCButton.qml │ │ │ ├── dialogs │ │ │ │ ├── RemoteDirSelectDialog.qml │ │ │ │ ├── SSLErrorDialog.qml │ │ │ │ ├── WebDavAccountDialog.qml │ │ │ │ └── fileselect │ │ │ │ │ ├── QQDFilePicker.qml │ │ │ │ │ ├── UbuntuContentHubOpener.qml │ │ │ │ │ └── UbuntuContentPicker.qml │ │ │ ├── main.qml │ │ │ └── pages │ │ │ │ ├── About.qml │ │ │ │ ├── AccountSelection.qml │ │ │ │ ├── SettingsPage.qml │ │ │ │ ├── TransferPage.qml │ │ │ │ └── browser │ │ │ │ ├── FileBrowser.qml │ │ │ │ └── FileDetails.qml │ │ └── sfos │ │ │ ├── OcsUserInfo.qml │ │ │ ├── cover │ │ │ ├── CoverDetailItem.qml │ │ │ └── CoverPage.qml │ │ │ ├── harbour-owncloud.qml │ │ │ ├── js │ │ │ └── TransferUtil.js │ │ │ ├── navigation │ │ │ ├── BrowserCommandPageFlow.qml │ │ │ └── CommandPageFlow.qml │ │ │ └── pages │ │ │ ├── About.qml │ │ │ ├── AccountEntrance.qml │ │ │ ├── SettingsPage.qml │ │ │ ├── TransferPage.qml │ │ │ ├── browser │ │ │ ├── FileBrowser.qml │ │ │ ├── FileDetails.qml │ │ │ ├── RemoteDirSelectDialog.qml │ │ │ └── controls │ │ │ │ └── FileOperationsContextMenu.qml │ │ │ └── login │ │ │ ├── AccountSelection.qml │ │ │ ├── BasicAuthentication.qml │ │ │ ├── Entrance.qml │ │ │ ├── FlowAuthentication.qml │ │ │ └── SSLErrorDialog.qml │ ├── qtquickcontrols2.conf │ ├── src │ │ ├── daemonctrl │ │ │ ├── daemoncontrol.cpp │ │ │ ├── daemoncontrol.h │ │ │ ├── dummydaemonctrl.cpp │ │ │ └── dummydaemonctrl.h │ │ ├── directorycontentmodel.cpp │ │ ├── directorycontentmodel.h │ │ ├── main.cpp │ │ ├── ocsnetaccessfactory.cpp │ │ ├── ocsnetaccessfactory.h │ │ ├── os │ │ │ ├── android │ │ │ │ ├── intentfileselector.cpp │ │ │ │ ├── intentfileselector.h │ │ │ │ ├── intentfileselectorreceiver.cpp │ │ │ │ └── intentfileselectorreceiver.h │ │ │ └── dummy │ │ │ │ ├── dummyintentfileselector.cpp │ │ │ │ └── dummyintentfileselector.h │ │ ├── webdavmediafeeder.cpp │ │ └── webdavmediafeeder.h │ ├── theme.qrc │ └── translations │ │ ├── harbour-owncloud-de.ts │ │ ├── harbour-owncloud-fi.ts │ │ ├── harbour-owncloud-fr.ts │ │ ├── harbour-owncloud-nl.ts │ │ ├── harbour-owncloud-sl.ts │ │ ├── harbour-owncloud-sv.ts │ │ ├── harbour-owncloud-zh_CN.ts │ │ └── harbour-owncloud.ts ├── common │ ├── CMakeLists.txt │ ├── common.pri │ ├── common.pro │ └── src │ │ ├── accountworkergenerator.cpp │ │ ├── accountworkergenerator.h │ │ ├── accountworkers.cpp │ │ ├── accountworkers.h │ │ ├── auth │ │ ├── authenticationexaminer.cpp │ │ ├── authenticationexaminer.h │ │ ├── authenticator.cpp │ │ ├── authenticator.h │ │ ├── flowloginauthenticator.cpp │ │ ├── flowloginauthenticator.h │ │ ├── qwebdavauthenticator.cpp │ │ └── qwebdavauthenticator.h │ │ ├── cacheprovider.cpp │ │ ├── cacheprovider.h │ │ ├── commands │ │ ├── http │ │ │ ├── httpcommandentity.cpp │ │ │ ├── httpcommandentity.h │ │ │ ├── httpgetcommandentity.cpp │ │ │ └── httpgetcommandentity.h │ │ ├── nopcommandentity.cpp │ │ ├── nopcommandentity.h │ │ ├── ocs │ │ │ ├── ocscommandentity.cpp │ │ │ ├── ocscommandentity.h │ │ │ ├── ocssharelistcommandentity.cpp │ │ │ ├── ocssharelistcommandentity.h │ │ │ ├── ocsuserinfocommandentity.cpp │ │ │ └── ocsuserinfocommandentity.h │ │ ├── sync │ │ │ ├── ncdirtreecommandunit.cpp │ │ │ ├── ncdirtreecommandunit.h │ │ │ ├── ncsynccommandunit.cpp │ │ │ └── ncsynccommandunit.h │ │ ├── ubuntutouch │ │ │ ├── utfiledownloadcommandentity.cpp │ │ │ ├── utfiledownloadcommandentity.h │ │ │ ├── utfileuploadcommandentity.cpp │ │ │ └── utfileuploadcommandentity.h │ │ └── webdav │ │ │ ├── davcopycommandentity.cpp │ │ │ ├── davcopycommandentity.h │ │ │ ├── davlistcommandentity.cpp │ │ │ ├── davlistcommandentity.h │ │ │ ├── davmovecommandentity.cpp │ │ │ ├── davmovecommandentity.h │ │ │ ├── davproppatchcommandentity.cpp │ │ │ ├── davproppatchcommandentity.h │ │ │ ├── davrmcommandentity.cpp │ │ │ ├── davrmcommandentity.h │ │ │ ├── filedownloadcommandentity.cpp │ │ │ ├── filedownloadcommandentity.h │ │ │ ├── fileuploadcommandentity.cpp │ │ │ ├── fileuploadcommandentity.h │ │ │ ├── mkdavdircommandentity.cpp │ │ │ ├── mkdavdircommandentity.h │ │ │ ├── webdavcommandentity.cpp │ │ │ └── webdavcommandentity.h │ │ ├── net │ │ ├── abstractfetcher.cpp │ │ ├── abstractfetcher.h │ │ ├── avatarfetcher.cpp │ │ ├── avatarfetcher.h │ │ ├── thumbnailfetcher.cpp │ │ └── thumbnailfetcher.h │ │ ├── nextcloudendpointconsts.h │ │ ├── ownclouddbusconsts.h │ │ ├── provider │ │ ├── accountinfo │ │ │ ├── accountinfoprovider.cpp │ │ │ ├── accountinfoprovider.h │ │ │ ├── ocscommandqueue.cpp │ │ │ └── ocscommandqueue.h │ │ ├── settingsbackedcommandqueue.cpp │ │ ├── settingsbackedcommandqueue.h │ │ ├── sharing │ │ │ ├── ocssharingcommandqueue.cpp │ │ │ ├── ocssharingcommandqueue.h │ │ │ ├── sharingprovider.cpp │ │ │ └── sharingprovider.h │ │ └── storage │ │ │ ├── cloudstorageprovider.cpp │ │ │ ├── cloudstorageprovider.h │ │ │ ├── webdavcommandqueue.cpp │ │ │ └── webdavcommandqueue.h │ │ ├── settings │ │ ├── db │ │ │ ├── accountdb.cpp │ │ │ ├── accountdb.h │ │ │ ├── accountsdbinterface.h │ │ │ ├── syncdb.cpp │ │ │ ├── syncdb.h │ │ │ ├── utaccountsdb.cpp │ │ │ └── utaccountsdb.h │ │ ├── inifilesettings.cpp │ │ ├── inifilesettings.h │ │ ├── nextcloudsettingsbase.cpp │ │ ├── nextcloudsettingsbase.h │ │ ├── permittedsettings.cpp │ │ └── permittedsettings.h │ │ ├── sharedstatecontroller.cpp │ │ ├── sharedstatecontroller.h │ │ └── util │ │ ├── commandutil.cpp │ │ ├── commandutil.h │ │ ├── filepathutil.cpp │ │ ├── filepathutil.h │ │ ├── providerutils.cpp │ │ ├── providerutils.h │ │ ├── qappprepareutil.h │ │ ├── shellcommand.cpp │ │ ├── shellcommand.h │ │ ├── webdav_utils.cpp │ │ └── webdav_utils.h ├── daemon │ ├── daemon.pro │ ├── dbushandler.cpp │ ├── dbushandler.h │ ├── filesystem.cpp │ ├── filesystem.h │ ├── harbour-owncloud-daemon.service │ ├── main.cpp │ ├── networkmonitor.cpp │ ├── networkmonitor.h │ ├── uploader.cpp │ └── uploader.h ├── permission-agent │ ├── PermissionsDialog.qml │ ├── dbushandler.cpp │ ├── dbushandler.h │ ├── dialogview.cpp │ ├── dialogview.h │ ├── harbour-owncloud-permission-agent.service │ ├── main.cpp │ ├── permission-agent.pro │ ├── permissionrequestqueue.cpp │ ├── permissionrequestqueue.h │ └── qml.qrc ├── qmlcommon │ ├── qmlcommon.pri │ └── src │ │ ├── qmlmap.cpp │ │ └── qmlmap.h ├── qmlextension │ ├── harbourowncloudqmlplugin.cpp │ ├── harbourowncloudqmlplugin.h │ ├── qmldir │ └── qmlextension.pro ├── sharing │ ├── GhostCloudShareUI.qml │ ├── ghostcloudconsts.h │ ├── ghostcloudplugininfo.cpp │ ├── ghostcloudplugininfo.h │ ├── ghostcloudshareplugin.cpp │ ├── ghostcloudshareplugin.h │ ├── ghostclouduploader.cpp │ ├── ghostclouduploader.h │ ├── icons │ │ ├── z1.0 │ │ │ └── icon-m-share-harbour-owncloud.png │ │ ├── z1.25 │ │ │ └── icon-m-share-harbour-owncloud.png │ │ ├── z1.5-large │ │ │ └── icon-m-share-harbour-owncloud.png │ │ └── z1.75 │ │ │ └── icon-m-share-harbour-owncloud.png │ └── sharing.pro ├── src.pro └── ut-photobackup │ ├── icons.qrc │ ├── icons │ └── icon_gray.svg │ ├── qml.qrc │ ├── qml │ └── main.qml │ ├── src │ ├── daemoncontrol.cpp │ ├── daemoncontrol.h │ ├── main.cpp │ ├── servicecreator.cpp │ └── servicecreator.h │ └── ut-photobackup.pro └── utphotobackup ├── ghostcloud.png ├── harbour-owncloud-photobackup.accounts ├── harbour-owncloud-photobackup.apparmor ├── harbour-owncloud-photobackup.desktop ├── manifest.json.in ├── run.sh └── utphotobackup.pro /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user* 2 | build-* 3 | build/ 4 | moc* 5 | *.o 6 | rpm/harbour-owncloud.spec.* 7 | parts/ 8 | stage/ 9 | prime/ 10 | *.tar.gz 11 | *.tar.gz.* 12 | openssl-*.*.* 13 | .DS_Store 14 | .clickable/ 15 | CMakeLists.txt.user 16 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "qwebdavlib"] 2 | path = 3rdparty/qwebdavlib 3 | url = https://github.com/beidl/qwebdavlib 4 | [submodule "nemo-qml-plugin-notifications"] 5 | path = 3rdparty/nemo-qml-plugin-notifications 6 | url = https://github.com/nemomobile/nemo-qml-plugin-notifications 7 | [submodule "sailfish-ui-set"] 8 | path = 3rdparty/sailfish-ui-set 9 | url = https://github.com/beidl/sailfish-ui-set 10 | [submodule "3rdparty/qtdropbox2"] 11 | path = 3rdparty/qtdropbox2 12 | url = https://github.com/beidl/QtDropbox2 13 | [submodule "src/app/icons/breeze-icons"] 14 | path = src/app/icons/breeze-icons 15 | url = https://github.com/KDE/breeze-icons 16 | [submodule "3rdparty/qml-ui-set"] 17 | path = 3rdparty/qml-ui-set 18 | url = https://github.com/fredldotme/qml-ui-set 19 | [submodule "3rdparty/libqtcommandqueue"] 20 | path = 3rdparty/libqtcommandqueue 21 | url = https://github.com/fredldotme/libqtcommandqueue 22 | [submodule "3rdparty/dropboxQt"] 23 | path = 3rdparty/dropboxQt 24 | url = https://github.com/osoftteam/dropboxQt.git 25 | -------------------------------------------------------------------------------- /3rdparty/build_android_openssl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then 4 | echo "Usage: $0 " 5 | echo "" 6 | echo "Make sure to have the ANDROID_NDK_HOME environment variable pointing" 7 | echo "to your Android NDK installation." 8 | echo "" 9 | echo "Examples:" 10 | echo "For arm: $0 1.0.2q arm" 11 | echo "For arm64: $0 1.0.2q arm64" 12 | exit 0 13 | fi 14 | 15 | if [ "$1" == "" ]; then 16 | echo "OpenSSL version not specified. Bailing..." 17 | exit 1 18 | fi 19 | 20 | if [ "$2" == "" ]; then 21 | echo "Android target architecture not specified. Bailing..." 22 | exit 2 23 | fi 24 | 25 | if [ "$ANDROID_NDK_HOME" == "" ]; then 26 | echo "ANDROID_NDK_HOME not specified" 27 | exit 3 28 | fi 29 | 30 | OPENSSL_VERSION=$1 31 | ANDROID_TARGET_ARCH=$2 32 | TOOLCHAIN_INSTALL_DIR="${ANDROID_NDK_HOME}/generated_toolchains" 33 | ANDROID_TARGET_API=21 34 | OPENSSL_DIR=openssl-${OPENSSL_VERSION} 35 | OPENSSL_FILE=${OPENSSL_DIR}.tar.gz 36 | 37 | if [ "$ANDROID_TARGET_ARCH" == "arm" ]; then 38 | ANDROID_BUILD_ARCH="arm" 39 | ABI=androideabi 40 | elif [ "$ANDROID_TARGET_ARCH" == "arm64" ]; then 41 | ANDROID_BUILD_ARCH="aarch64" 42 | ABI=android 43 | elif [ "$ANDROID_TARGET_ARCH" == "x86" ]; then 44 | ANDROID_BUILD_ARCH="i686" 45 | ABI=android 46 | elif [ "$ANDROID_TARGET_ARCH" == "x86_64" ]; then 47 | ANDROID_BUILD_ARCH="x86_64" 48 | ABI=android 49 | else 50 | echo "Failed to determine ANDROID_BUILD_ARCH. Bailing..." 51 | exit 4 52 | fi 53 | 54 | TOOLCHAIN_FULL_PATH=${TOOLCHAIN_INSTALL_DIR}/android-${ANDROID_TARGET_API}-${ANDROID_TARGET_ARCH} 55 | 56 | # Toolchain preparation 57 | $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py \ 58 | --arch ${ANDROID_TARGET_ARCH} \ 59 | --api ${ANDROID_TARGET_API} \ 60 | --install-dir ${TOOLCHAIN_FULL_PATH} 61 | 62 | # Fetch and unpack 63 | if [ ! -f ${OPENSSL_FILE} ]; then 64 | wget https://www.openssl.org/source/${OPENSSL_FILE} 65 | fi 66 | tar xvf ${OPENSSL_FILE} 67 | cd ${OPENSSL_DIR} 68 | 69 | # Building 70 | find . -type f -print0 | xargs -0 sed -i 's/-mandroid//g' 71 | 72 | CROSS_COMPILE=${TOOLCHAIN_FULL_PATH}/bin/${ANDROID_BUILD_ARCH}-linux-${ABI}- ./Configure android shared 73 | make ANDROID_DEV=${TOOLCHAIN_FULL_PATH}/sysroot/usr CALC_VERSIONS="SHLIB_COMPAT=; SHLIB_SOVER=" build_libs 74 | 75 | if [ ! -f "libcrypto.so" ]; then 76 | echo "libcrypto.so doesn't exist. Bailing..." 77 | exit 5 78 | fi 79 | 80 | if [ ! -f "libssl.so" ]; then 81 | echo "libssl.so doesn't exist. Bailing..." 82 | exit 6 83 | fi 84 | 85 | cd .. 86 | 87 | if [ -d openssl ]; then 88 | rm -r openssl 89 | fi 90 | 91 | mv ${OPENSSL_DIR} openssl 92 | 93 | echo "Build successful!" 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(GhostCloud) 2 | 3 | add_subdirectory(src) 4 | 5 | #add_subdirectory(3rdparty/qwebdavlib/qwebdavlib) 6 | #add_subdirectory(src) 7 | #if(CONFIG___contains___click) 8 | # add_subdirectory(click) 9 | #endif() 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GhostCloud 2 | Nextcloud/ownCloud and WebDav client for SailfishOS 3 | 4 | ![Login](/misc/readme/cover.png) ![File browser](/misc/readme/filebrowser.png) ![User info](/misc/readme/userinfo.png) ![File details](/misc/readme/filedetails.png) ![Media preview](/misc/readme/mediapreview.png) 5 | 6 | 7 | ## Description 8 | Allows you to easily access your ownCloud, NextCloud and WebDav instances with a native Free Software application. 9 | 10 | For automatic camera photo backup and upload from within other apps (i.e. Gallery) take a look at the "Nextcloud/ownCloud additionals" over at OpenRepos. 11 | 12 | Current qmake build configurations: 13 | - SailfishOS: CONFIG+=sailfish_build 14 | - GNU/Linux desktop: CONFIG+=noadditionals CONFIG+=quickcontrols 15 | - Ubuntu Touch: CONFIG+=noadditionals CONFIG+=quickcontrols CONFIG+=click 16 | - Android: CONFIG+=noadditionals CONFIG+=quickcontrols 17 | - macOS/iOS: CONFIG+=noadditionals CONFIG+=quickcontrols 18 | 19 | 20 | ## Licenses 21 | 22 | - The core common shared code (in `src/common`) is licensed under LGPLv2.1. 23 | - The applications, permission agents and daemons for Android, SailfishOS, Linux & Ubuntu Touch are licensed under GPLv2. 24 | 25 | 26 | ## Donations 27 | 28 | You can donate to the project through: 29 | 30 | PayPal: dev.beidl@gmail.com 31 | 32 | Flattr: @beidl 33 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Proper securing of credentials 2 | - Long term: investigate feasability of SailfishOS 3.0 "Secrets" feature 3 | * Fix double uploading of files 4 | * Offline support/syncing 5 | -------------------------------------------------------------------------------- /click/click.pro: -------------------------------------------------------------------------------- 1 | # This creates the manifest.json file, it is the description file for the 2 | # click package. 3 | 4 | TEMPLATE = aux 5 | 6 | # figure out the current build architecture 7 | CLICK_ARCH=$$system(dpkg-architecture -qDEB_HOST_ARCH) 8 | 9 | # do not remove this line, it is required by the IDE even if you do 10 | # not substitute variables in the manifest file 11 | UBUNTU_MANIFEST_FILE = $$PWD/manifest.json.in 12 | 13 | 14 | # substitute the architecture in the manifest file 15 | manifest_file.output = manifest.json 16 | manifest_file.CONFIG += no_link \ 17 | add_inputs_as_makefile_deps\ 18 | target_predeps 19 | manifest_file.commands = sed s/@CLICK_ARCH@/$$CLICK_ARCH/g ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT} 20 | manifest_file.input = UBUNTU_MANIFEST_FILE 21 | QMAKE_EXTRA_COMPILERS += manifest_file 22 | 23 | # installation path of the manifest file 24 | mfile.CONFIG += no_check_exist 25 | mfile.files += $$OUT_PWD/manifest.json 26 | mfile.path = / 27 | 28 | # AppArmor profile 29 | apparmor.files += $$PWD/harbour-owncloud.apparmor 30 | apparmor.path = / 31 | 32 | # Desktop launcher icon 33 | desktopicon.files += $$PWD/ghostcloud.png 34 | desktopicon.path = / 35 | 36 | # Desktop launcher 37 | desktop.files += $$PWD/harbour-owncloud.desktop 38 | desktop.path = / 39 | 40 | # Accounts description 41 | accounts.files += $$PWD/harbour-owncloud.accounts 42 | accounts.path = / 43 | 44 | # Run script 45 | runscript.files += $$PWD/run.sh 46 | runscript.path = / 47 | 48 | INSTALLS += mfile apparmor runscript desktopicon desktop accounts 49 | -------------------------------------------------------------------------------- /click/ghostcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/click/ghostcloud.png -------------------------------------------------------------------------------- /click/harbour-owncloud.accounts: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "GhostCloud", 5 | "description": "Access your self-hosted cloud files", 6 | "provider": "nextcloud" 7 | }, 8 | { 9 | "name": "GhostCloud", 10 | "description": "Access your self-hosted cloud files", 11 | "provider": "owncloud" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /click/harbour-owncloud.apparmor: -------------------------------------------------------------------------------- 1 | { 2 | "policy_groups": [ 3 | "connectivity", 4 | "content_exchange", 5 | "content_exchange_source", 6 | "networking", 7 | "audio", 8 | "video", 9 | "accounts" 10 | ], 11 | "policy_version": 16.04 12 | } 13 | -------------------------------------------------------------------------------- /click/harbour-owncloud.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Icon=ghostcloud.png 4 | Exec=run.sh 5 | Name=GhostCloud 6 | X-Ubuntu-Touch=true 7 | X-Ubuntu-Splash-Color=#F5F5F5 8 | -------------------------------------------------------------------------------- /click/manifest.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "name": "me.fredl.ghostcloud", 3 | "title": "GhostCloud", 4 | "version": "0.9.9.4", 5 | "description": "A multi-platform client for ownCloud, NextCloud & WebDav", 6 | "architecture": "@CLICK_ARCH@", 7 | "framework": "ubuntu-sdk-16.04.5", 8 | "maintainer": "Alfred Neumayer ", 9 | "hooks": { 10 | "harbour-owncloud": { 11 | "apparmor": "harbour-owncloud.apparmor", 12 | "desktop": "harbour-owncloud.desktop", 13 | "accounts": "harbour-owncloud.accounts" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /click/run-daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LD_LIBRARY_PATH=$PWD/usr/lib:$LD_LIBRARY_PATH 4 | export QT_QUICK_CONTROLS_MOBILE=true 5 | export QT_QUICK_CONTROLS_STYLE=Material 6 | 7 | exec $PWD/usr/bin/harbour-owncloud-daemon \ 8 | --desktop_file_hint=${HOME}/.local/share/applications/${APP_ID}.desktop "$@" 9 | -------------------------------------------------------------------------------- /click/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LD_LIBRARY_PATH=$PWD/usr/lib:$LD_LIBRARY_PATH 4 | export QT_QUICK_CONTROLS_MOBILE=true 5 | export QT_QUICK_CONTROLS_STYLE=Suru 6 | 7 | exec $PWD/usr/bin/harbour-owncloud \ 8 | --desktop_file_hint=${HOME}/.local/share/applications/${APP_ID}.desktop "$@" 9 | -------------------------------------------------------------------------------- /clickable-ut-photo-backup.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "qmake", 3 | "default": "clean build click-build", 4 | "kill": "harbour-owncloud-photobackup", 5 | "dependencies_target": [ 6 | "liblomiri-download-manager-client-dev", 7 | "libonline-accounts-qt-dev" 8 | ], 9 | "build_args": [ 10 | "CONFIG+=noapp", 11 | "CONFIG+=nopermissionagent", 12 | "CONFIG+=noqmlextension", 13 | "CONFIG+=nosharing", 14 | "CONFIG+=clickphotobackup" 15 | ], 16 | "make_jobs": 4, 17 | "qt_version": "5.12", 18 | "framework": "ubuntu-sdk-20.04" 19 | } 20 | -------------------------------------------------------------------------------- /clickable.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "qmake", 3 | "framework": "ubuntu-sdk-20.04", 4 | "default": "clean build click-build", 5 | "kill": "harbour-owncloud", 6 | "dependencies_target": [ 7 | "liblomiri-download-manager-client-dev", 8 | "libonline-accounts-qt-dev", 9 | "libgles-dev" 10 | ], 11 | "build_args": [ 12 | "CONFIG+=nodaemon", 13 | "CONFIG+=nopermissionagent", 14 | "CONFIG+=noqmlextension", 15 | "CONFIG+=nosharing", 16 | "CONFIG+=quickcontrols", 17 | "CONFIG+=click" 18 | ], 19 | "make_jobs": 4, 20 | "qt_version": "5.12" 21 | } 22 | -------------------------------------------------------------------------------- /harbour-owncloud.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | CONFIG += ordered 3 | 4 | # Use shared libraries and dependencies on every platform 5 | !macx { 6 | SUBDIRS = 3rdparty/qwebdavlib/qwebdavlib src 7 | } 8 | # .. except macOS 9 | macx { 10 | SUBDIRS = src 11 | } 12 | 13 | # Android OpenSSL script requirement 14 | android { 15 | !exists($$OUT_PWD/3rdparty/build_android_openssl.sh): \ 16 | error(The Android OpenSSL build script is missing, please copy it\ 17 | to '$$OUT_PWD/3rdparty/build_android_openssl.sh'.) 18 | 19 | exists($$OUT_PWD/3rdparty/build_android_openssl.sh) { 20 | !exists ($$OUT_PWD/3rdparty/openssl) { 21 | warning(OpenSSL library missing) 22 | system($$OUT_PWD/3rdparty/build_android_openssl.sh --help) 23 | error(Change to the $$OUT_PWD/3rdparty directory \ 24 | and run the script manually) 25 | } 26 | } 27 | } 28 | 29 | # Ubuntu Touch click packaging 30 | contains(CONFIG,click) { 31 | SUBDIRS += click 32 | } 33 | contains(CONFIG,clickphotobackup) { 34 | SUBDIRS += utphotobackup 35 | } 36 | 37 | # SailfishOS rpm packaging 38 | OTHER_FILES += \ 39 | rpm/harbour-owncloud.changes.in \ 40 | rpm/harbour-owncloud.spec \ 41 | rpm/harbour-owncloud.yaml 42 | -------------------------------------------------------------------------------- /misc/notes/multi_account_transfer.txt: -------------------------------------------------------------------------------- 1 | Active accounts at runtime 2 | - Account 1 3 | - OSC 4 | - BrowserQueue 5 | - MiscQueue 6 | - Account 2 7 | - OSC 8 | - BrowserQueue 9 | - MiscQueue 10 | 11 | CommandQueue 12 | - SettingsBackedCommandQueue 13 | - CloudStorageProvider 14 | - WebDavCommandQueue 15 | - OscCommandQueue 16 | 17 | TransferQueue 18 | - TransferCommand 19 | - client + credentials 20 | 21 | Implementations: 22 | - FileDownloadCommand 23 | - string target (remote) 24 | - string destination (local) 25 | - transferImpl 26 | - FileUploadCommand 27 | - string target (local) 28 | - string destination (remote) 29 | - transferImpl 30 | Ideas for further improvements: 31 | - FileCopyCrossCommand 32 | - QFile target 33 | - QFile destination 34 | - FileMoveCrossCommand 35 | - QFile target 36 | - QFile destination 37 | 38 | 39 | Interesting additional features: 40 | - "ghost" file entry in the FileBrowser view 41 | - allowing further command enqueuing (rename after upload, etc) 42 | -------------------------------------------------------------------------------- /misc/readme/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/misc/readme/cover.png -------------------------------------------------------------------------------- /misc/readme/filebrowser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/misc/readme/filebrowser.png -------------------------------------------------------------------------------- /misc/readme/filedetails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/misc/readme/filedetails.png -------------------------------------------------------------------------------- /misc/readme/mediapreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/misc/readme/mediapreview.png -------------------------------------------------------------------------------- /misc/readme/userinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/misc/readme/userinfo.png -------------------------------------------------------------------------------- /rpm/harbour-owncloud.changes.in: -------------------------------------------------------------------------------- 1 | # Rename this file as harbour-owncloud.changes to include changelog 2 | # entries in your RPM file. 3 | # 4 | # Add new changelog entries following the format below. 5 | # Add newest entries to the top of the list. 6 | # Separate entries from eachother with a blank line. 7 | 8 | # * date Author's Name version-release 9 | # - Summary of changes 10 | 11 | * Sun Apr 13 2014 Jack Tar 0.0.1-1 12 | - Scrubbed the deck 13 | - Hoisted the sails 14 | 15 | 16 | -------------------------------------------------------------------------------- /rpm/harbour-owncloud.yaml: -------------------------------------------------------------------------------- 1 | Name: harbour-owncloud 2 | Summary: ownCloud 3 | Version: 0.9.5 4 | Release: 1 5 | # The contents of the Group field should be one of the groups listed here: 6 | # http://gitorious.org/meego-developer-tools/spectacle/blobs/master/data/GROUPS 7 | Group: Qt/Qt 8 | URL: https://github.com/fredldotme/harbour-owncloud 9 | License: GPLv2 10 | # This must be generated before uploading a package to a remote build service. 11 | # Usually this line does not need to be modified. 12 | Sources: 13 | - '%{name}-%{version}.tar.bz2' 14 | Description: | 15 | Unofficial ownCloud client for SailfishOS 16 | Configure: none 17 | # The qtc5 builder inserts macros to allow QtCreator to have fine 18 | # control over qmake/make execution 19 | Builder: qtc5 20 | 21 | # This section specifies build dependencies that are resolved using pkgconfig. 22 | # This is the preferred way of specifying build dependencies for your package. 23 | PkgConfigBR: 24 | - sailfishapp >= 1.0.2 25 | - Qt5Core 26 | - Qt5Qml 27 | - Qt5Quick 28 | - nemotransferengine-qt5 29 | 30 | # Build dependencies without a pkgconfig setup can be listed here 31 | # PkgBR: 32 | # - package-needed-to-build 33 | 34 | # Runtime dependencies which are not automatically detected 35 | Requires: 36 | - sailfishsilica-qt5 >= 0.10.9 37 | 38 | # All installed files 39 | Files: 40 | - '%{_bindir}/%{name}' 41 | - '%{_datadir}/%{name}' 42 | - '%{_datadir}/applications/%{name}.desktop' 43 | - '%{_datadir}/icons/hicolor/*/apps/%{name}.png' 44 | 45 | # For more information about yaml and what's supported in Sailfish OS 46 | # build system, please see https://wiki.merproject.org/wiki/Spectacle 47 | 48 | -------------------------------------------------------------------------------- /snap/gui/harbour-owncloud.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Icon=${SNAP}/meta/gui/harbour-owncloud.png 4 | Exec=ghostcloud.harbour-owncloud 5 | Name=GhostCloud 6 | -------------------------------------------------------------------------------- /snap/gui/harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/snap/gui/harbour-owncloud.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(widgetsapp) 2 | add_subdirectory(finderextension) 3 | -------------------------------------------------------------------------------- /src/app/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.0' 9 | } 10 | } 11 | 12 | repositories { 13 | google() 14 | jcenter() 15 | } 16 | 17 | apply plugin: 'com.android.application' 18 | 19 | dependencies { 20 | implementation fileTree(dir: 'libs', include: ['*.jar']) 21 | } 22 | 23 | android { 24 | /******************************************************* 25 | * The following variables: 26 | * - androidBuildToolsVersion, 27 | * - androidCompileSdkVersion 28 | * - qt5AndroidDir - holds the path to qt android files 29 | * needed to build any Qt application 30 | * on Android. 31 | * 32 | * are defined in gradle.properties file. This file is 33 | * updated by QtCreator and androiddeployqt tools. 34 | * Changing them manually might break the compilation! 35 | *******************************************************/ 36 | 37 | compileSdkVersion androidCompileSdkVersion.toInteger() 38 | 39 | buildToolsVersion androidBuildToolsVersion 40 | 41 | sourceSets { 42 | main { 43 | manifest.srcFile 'AndroidManifest.xml' 44 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] 45 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] 46 | res.srcDirs = [qt5AndroidDir + '/res', 'res'] 47 | resources.srcDirs = ['src'] 48 | renderscript.srcDirs = ['src'] 49 | assets.srcDirs = ['assets'] 50 | jniLibs.srcDirs = ['libs'] 51 | } 52 | } 53 | 54 | lintOptions { 55 | abortOnError false 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/app/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /src/app/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/app/android/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/android/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /src/app/android/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/android/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /src/app/android/res/values/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://download.qt.io/ministro/android/qt5/qt-5.9 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/app/harbour-owncloud.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | X-Nemo-Application-Type=silica-qt5 4 | Icon=harbour-owncloud 5 | Exec=harbour-owncloud 6 | Name=GhostCloud 7 | # translation example: 8 | # your app name in German locale (de) 9 | Name[de]=GhostCloud 10 | Name[sl]=GhostCloud 11 | -------------------------------------------------------------------------------- /src/app/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/icon_gray.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/icons/108x108/harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/108x108/harbour-owncloud.png -------------------------------------------------------------------------------- /src/app/icons/128x128/harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/128x128/harbour-owncloud.png -------------------------------------------------------------------------------- /src/app/icons/172x172/harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/172x172/harbour-owncloud.png -------------------------------------------------------------------------------- /src/app/icons/86x86/harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/86x86/harbour-owncloud.png -------------------------------------------------------------------------------- /src/app/icons/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/banner.png -------------------------------------------------------------------------------- /src/app/icons/harbour-owncloud_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/app/icons/harbour-owncloud_512.png -------------------------------------------------------------------------------- /src/app/icons/theme: -------------------------------------------------------------------------------- 1 | breeze-icons/icons -------------------------------------------------------------------------------- /src/app/ios/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | GhostCloud 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleGetInfoString 10 | Created by Qt/QMake 11 | CFBundleIconFile 12 | ${ASSETCATALOG_COMPILER_APPICON_NAME} 13 | CFBundleIdentifier 14 | ${PRODUCT_BUNDLE_IDENTIFIER} 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | ${QMAKE_SHORT_VERSION} 21 | CFBundleSignature 22 | ${QMAKE_PKGINFO_TYPEINFO} 23 | CFBundleVersion 24 | ${QMAKE_FULL_VERSION} 25 | LSRequiresIPhoneOS 26 | 27 | NSPhotoLibraryUsageDescription 28 | Access to the Photo Library 29 | MinimumOSVersion 30 | ${IPHONEOS_DEPLOYMENT_TARGET} 31 | NOTE 32 | This file was generated by Qt/QMake. 33 | UILaunchStoryboardName 34 | LaunchScreen 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/app/macos/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | harbour-owncloud 7 | CFBundleName 8 | GhostCloud 9 | CFBundleGetInfoString 10 | Created by Qt/QMake 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | me.fredl.ghostcloud 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | ???? 19 | LSMinimumSystemVersion 20 | 10.12 21 | NOTE 22 | This file was generated by Qt/QMake. 23 | NSPrincipalClass 24 | NSApplication 25 | NSSupportsAutomaticGraphicsSwitching 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/app/qml-sfos.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/sfos/harbour-owncloud.qml 4 | qml/sfos/cover/CoverPage.qml 5 | qml/sfos/pages/browser/FileBrowser.qml 6 | qml/sfos/pages/browser/FileDetails.qml 7 | qml/sfos/pages/login/BasicAuthentication.qml 8 | qml/sfos/pages/browser/RemoteDirSelectDialog.qml 9 | qml/sfos/pages/SettingsPage.qml 10 | qml/sfos/pages/login/SSLErrorDialog.qml 11 | qml/sfos/pages/TransferPage.qml 12 | qml/sfos/pages/login/FlowAuthentication.qml 13 | qml/sfos/pages/login/Entrance.qml 14 | qml/sfos/cover/CoverDetailItem.qml 15 | qml/sfos/pages/browser/controls/FileOperationsContextMenu.qml 16 | qml/sfos/OcsUserInfo.qml 17 | qml/sfos/navigation/CommandPageFlow.qml 18 | qml/sfos/navigation/BrowserCommandPageFlow.qml 19 | qml/sfos/pages/About.qml 20 | qml/sfos/pages/login/AccountSelection.qml 21 | qml/sfos/js/TransferUtil.js 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/app/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/qqc/main.qml 4 | qml/qqc/pages/AccountSelection.qml 5 | qml/qqc/BrowserCommandPageFlow.qml 6 | qml/qqc/CommandPageFlow.qml 7 | qml/qqc/pages/browser/FileBrowser.qml 8 | qml/qqc/pages/browser/FileDetails.qml 9 | qml/qqc/dialogs/WebDavAccountDialog.qml 10 | qml/qqc/pages/TransferPage.qml 11 | qml/qqc/dialogs/RemoteDirSelectDialog.qml 12 | qml/qqc/dialogs/SSLErrorDialog.qml 13 | qml/qqc/pages/SettingsPage.qml 14 | qml/qqc/pages/About.qml 15 | qml/qqc/controls/GCButton.qml 16 | qml/qqc/dialogs/fileselect/UbuntuContentPicker.qml 17 | qml/qqc/dialogs/fileselect/QQDFilePicker.qml 18 | qml/qqc/dialogs/fileselect/UbuntuContentHubOpener.qml 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/app/qml/dummy/FileSelectionDialog.qml: -------------------------------------------------------------------------------- 1 | // This file exists only to translate 2 | // qml-ui-set/ui/FileSelectionDialog.qml 3 | // For some reason the files are not included 4 | // for translation when generating the package... 5 | 6 | import QtQuick 2.0 7 | import Sailfish.Silica 1.0 8 | 9 | Item { 10 | ComboBox { 11 | id: storageSelection 12 | label: qsTr("Storage:") 13 | menu: ContextMenu { 14 | MenuItem { 15 | id: userDirMenuItem 16 | text: qsTr("Home directory") 17 | } 18 | MenuItem { 19 | id: sdCardMenuItem 20 | text: qsTr("External storage") 21 | } 22 | MenuItem { 23 | id: usbOtgMenuItem 24 | text: qsTr("External storage (2)") 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/qml/qqc/CommandPageFlow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | // Inheriting items are supposed to manually connect 5 | // a handler to the commandFinished signal provided by 6 | // the accountWorker's CommandQueues 7 | property var accountWorkers : null 8 | property var directoryContents : null 9 | 10 | signal notificationRequest(string summary, string body) 11 | signal transientNotificationRequest(string summary) 12 | signal userInfoUpdateRequest() 13 | signal avatarFetchRequest() 14 | } 15 | -------------------------------------------------------------------------------- /src/app/qml/qqc/controls/GCButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import QtGraphicalEffects 1.0 5 | 6 | AbstractButton { 7 | id: buttonRoot 8 | 9 | property alias textFont : label.font 10 | property alias detailText : detailLabel.text 11 | property alias detailTextFont : detailLabel.font 12 | property alias source : img.source 13 | property alias sourceSize : img.sourceSize 14 | property bool forcePressed : false 15 | property int radius : 0 16 | 17 | signal clicked() 18 | 19 | Layout.minimumWidth: width 20 | Layout.minimumHeight: height 21 | 22 | Rectangle { 23 | color: "lightgray" 24 | anchors.fill: parent 25 | visible: mouseArea.pressed || forcePressed 26 | enabled: buttonRoot.enabled 27 | } 28 | 29 | Row { 30 | anchors.fill: parent 31 | anchors.margins: paddingTiny 32 | spacing: paddingTiny 33 | 34 | Image { 35 | id: img 36 | height: parent.height 37 | width: height 38 | layer.enabled: buttonRoot.radius > 0 39 | layer.effect: OpacityMask { 40 | maskSource: Item { 41 | width: img.width 42 | height: img.height 43 | Rectangle { 44 | anchors.centerIn: parent 45 | width: parent.width 46 | height: parent.height 47 | radius: buttonRoot.radius 48 | } 49 | } 50 | } 51 | } 52 | Column { 53 | height: parent.height 54 | width: parent.width - img.width 55 | anchors.verticalCenter: parent.verticalCenter 56 | Label { 57 | id: label 58 | text: buttonRoot.text 59 | font.pixelSize: fontSizeSmall 60 | enabled: buttonRoot.enabled 61 | elide: Label.ElideRight 62 | width: parent.width 63 | } 64 | Label { 65 | id: detailLabel 66 | font.pixelSize: fontSizeTiny 67 | enabled: buttonRoot.enabled 68 | elide: Label.ElideRight 69 | width: parent.width 70 | } 71 | } 72 | } 73 | 74 | MouseArea { 75 | id: mouseArea 76 | anchors.fill: parent 77 | onClicked: { 78 | if (forcePressed || pressed) 79 | return; 80 | buttonRoot.clicked() 81 | } 82 | enabled: buttonRoot.enabled 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/app/qml/qqc/dialogs/RemoteDirSelectDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.2 3 | import harbour.owncloud 1.0 4 | import "qrc:/qml/qqc/controls" 5 | 6 | Dialog { 7 | id: dialogRoot 8 | standardButtons: Dialog.Ok | Dialog.Cancel 9 | height: 100 10 | 11 | property string remotePath : "/" 12 | property bool isLoadingDirectory : true 13 | property CloudStorageProvider browserCommandQueue : null 14 | property QmlMap directoryContents : rootWindow.dirContents 15 | 16 | // Prepend ".." in case remotePath !== "/" 17 | function mangledDirectoryList(dirs) { 18 | if (remotePath === "/") 19 | return dirs; 20 | return [{ name: "..", isDirectory: true }].concat(dirs) 21 | } 22 | 23 | function getDirectoryContent(path) { 24 | remotePath = FilePathUtil.getCanonicalPath(path) 25 | 26 | if (dialogRoot.directoryContents.contains(remotePath)) { 27 | listView.model = mangledDirectoryList(dialogRoot.directoryContents.value(remotePath)) 28 | isLoadingDirectory = false; 29 | return; 30 | } 31 | dialogRoot.browserCommandQueue.directoryListingRequest(remotePath, true) 32 | } 33 | 34 | Component.onCompleted: { 35 | getDirectoryContent(remotePath) 36 | 37 | console.debug("dialogRoot.directoryContents " + dialogRoot.directoryContents); 38 | } 39 | 40 | Connections { 41 | target: dialogRoot.directoryContents 42 | 43 | onInserted: { 44 | console.log("RemoteDirSelectDialog key:" + key + " remotePath:" + remotePath) 45 | if (key !== remotePath) 46 | return; 47 | 48 | listView.model = mangledDirectoryList(dialogRoot.directoryContents.value(key)) 49 | isLoadingDirectory = false; 50 | } 51 | } 52 | 53 | Item { 54 | anchors.fill: parent 55 | 56 | ListView { 57 | id: listView 58 | anchors.fill: parent 59 | enabled: !isLoadingDirectory 60 | ScrollBar.vertical: ScrollBar {} 61 | 62 | delegate: GCButton { 63 | id: icon 64 | visible: davInfo.isDirectory 65 | source: getFolderIcon("folder") 66 | text: davInfo.name 67 | width: listView.width 68 | height: 32 69 | 70 | property var davInfo : listView.model[index] 71 | 72 | onClicked: { 73 | if(!davInfo.isDirectory) 74 | return; 75 | 76 | var newTargetDir = FilePathUtil.getCanonicalPath(remotePath + "/" + 77 | davInfo.name + "/") 78 | console.log(newTargetDir) 79 | isLoadingDirectory = true; 80 | getDirectoryContent(newTargetDir) 81 | } 82 | } 83 | 84 | BusyIndicator { 85 | anchors.centerIn: parent 86 | running: isLoadingDirectory 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/app/qml/qqc/dialogs/SSLErrorDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.2 3 | 4 | Dialog { 5 | id: textEntryDialog 6 | standardButtons: Dialog.Ok | Dialog.Cancel 7 | 8 | property string md5Fingerprint : "" 9 | property string sha1Fingerprint : "" 10 | 11 | Column { 12 | anchors.fill: parent 13 | anchors.margins: fontSizeSmall 14 | spacing: paddingTiny 15 | 16 | Label { 17 | text: qsTr("Would you like to accept the certificate?") 18 | font.pixelSize: fontSizeMedium 19 | width: parent.width 20 | wrapMode: Label.WrapAtWordBoundaryOrAnywhere 21 | } 22 | Label { 23 | text: qsTr("MD5: %1").arg(md5Fingerprint) 24 | width: parent.width 25 | wrapMode: Label.WrapAtWordBoundaryOrAnywhere 26 | } 27 | Label { 28 | text: qsTr("SHA1: %1").arg(sha1Fingerprint) 29 | width: parent.width 30 | wrapMode: Label.WrapAtWordBoundaryOrAnywhere 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/app/qml/qqc/dialogs/fileselect/QQDFilePicker.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Dialogs 1.2 3 | 4 | FileDialog { 5 | id: openFileDialog 6 | selectMultiple: true 7 | folder: !osIsIOS ? 8 | shortcuts.home : 9 | shortcuts.pictures 10 | } 11 | -------------------------------------------------------------------------------- /src/app/qml/qqc/dialogs/fileselect/UbuntuContentHubOpener.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 2.1 3 | import Lomiri.Content 1.3 4 | 5 | Dialog { 6 | id: pageRoot 7 | title: qsTr("Open '%1' with").arg(fileName) 8 | standardButtons: Dialog.Cancel 9 | 10 | readonly property bool destroyable : true 11 | 12 | property string fileUri : null 13 | readonly property string fileName : fileUri.substring(fileUri.lastIndexOf('/') + 1) 14 | 15 | property var activeTransfer 16 | Connections { 17 | target: pageRoot.activeTransfer 18 | onStateChanged: { 19 | exportContent(pageRoot.fileUri) 20 | } 21 | } 22 | 23 | Component { 24 | id: resultComponent 25 | ContentItem {} 26 | } 27 | 28 | function exportContent(url) { 29 | if (pageRoot.activeTransfer.state !== ContentTransfer.InProgress) 30 | return; 31 | 32 | pageRoot.activeTransfer.items = [ resultComponent.createObject(pageRoot, 33 | {"url": url})]; 34 | pageRoot.activeTransfer.state = ContentTransfer.Charged; 35 | } 36 | 37 | ContentPeerPicker { 38 | id: peerPicker 39 | showTitle: false 40 | 41 | handler: ContentHandler.Destination 42 | contentType: ContentType.All 43 | 44 | onPeerSelected: { 45 | pageRoot.activeTransfer = peer.request(); 46 | exportContent(pageRoot.fileUri) 47 | pageRoot.close() 48 | } 49 | 50 | onCancelPressed: { 51 | pageRoot.close() 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/qml/qqc/dialogs/fileselect/UbuntuContentPicker.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Lomiri.Components 1.1 3 | import Lomiri.Content 1.1 4 | 5 | Item { 6 | id: dialogRoot 7 | anchors.fill: parent 8 | visible: false 9 | 10 | property list importItems 11 | property var activeTransfer 12 | property var fileUrls : new Array 13 | 14 | onImportItemsChanged: { 15 | if (importItems.length > 0) { 16 | fileUrls = new Array 17 | 18 | for (var i = 0; i < importItems.length; i++) { 19 | const url = importItems[i].url 20 | console.log("URL: " + url) 21 | if (fileUrls.indexOf(url) == -1) { 22 | fileUrls.push(url) 23 | } 24 | } 25 | 26 | dialogRoot.accepted() 27 | dialogRoot.visible = false 28 | } 29 | } 30 | 31 | signal accepted() 32 | 33 | function open() { 34 | dialogRoot.visible = true 35 | } 36 | 37 | ContentPeerPicker { 38 | id: contentPeer 39 | anchors.fill: parent 40 | contentType: ContentType.Documents 41 | handler: ContentHandler.Source 42 | onPeerSelected: { activeTransfer = peer.request() } 43 | onCancelPressed: { dialogRoot.visible = false } 44 | } 45 | 46 | ContentTransferHint { 47 | id: importHint 48 | anchors.fill: parent 49 | activeTransfer: dialogRoot.activeTransfer 50 | } 51 | 52 | Connections { 53 | target: dialogRoot.activeTransfer 54 | onStateChanged: { 55 | if (dialogRoot.activeTransfer.state === ContentTransfer.Charged) { 56 | importItems = dialogRoot.activeTransfer.items; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/app/qml/sfos/OcsUserInfo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import harbour.owncloud 1.0 3 | import SailfishUiSet 1.0 4 | 5 | Item { 6 | property CommandQueue commandQueue : null 7 | 8 | property bool userInfoEnabled : false 9 | property string displayName : "" 10 | property string emailAddress : "" 11 | property string usedBytes : "" 12 | property string freeBytes : "" 13 | property string totalBytes : "" 14 | 15 | readonly property string hrDisplayName : 16 | displayName.length < 20 ? 17 | displayName : 18 | displayName.substring(0, 20) + ".." 19 | readonly property string hrMailAddress : 20 | emailAddress.length < 20 ? 21 | emailAddress : 22 | emailAddress.substring(0, 20) + ".." 23 | readonly property string hrUsedBytes : 24 | usedBytes.length < 15 ? 25 | usedBytes : 26 | usedBytes.substring(0, 15) + ".." 27 | readonly property string hrFreeBytes : 28 | freeBytes.length < 15 ? 29 | freeBytes : 30 | freeBytes.substring(0, 15) + ".." 31 | readonly property string hrTotalBytes : 32 | totalBytes.length < 15 ? 33 | totalBytes : 34 | totalBytes.substring(0, 15) + ".." 35 | 36 | function reset() { 37 | userInfoEnabled = false 38 | displayName = "" 39 | emailAddress = "" 40 | usedBytes = "" 41 | totalBytes = "" 42 | } 43 | 44 | FileDetailsHelper { 45 | id: fileDetailsHelper 46 | } 47 | 48 | Connections { 49 | target: commandQueue 50 | onCommandFinished: { 51 | var ocsType = receipt.info.property("type") 52 | if (ocsType !== "userInfo") 53 | return; 54 | 55 | if (receipt.result === undefined) 56 | return; 57 | if (receipt.result.enabled === undefined) 58 | return; 59 | 60 | ocsUserInfo.userInfoEnabled = receipt.result.enabled; 61 | ocsUserInfo.displayName = receipt.result.displayName; 62 | ocsUserInfo.emailAddress = receipt.result.email; 63 | ocsUserInfo.usedBytes = fileDetailsHelper.getHRSizeFromString( 64 | receipt.result.usedBytes); 65 | ocsUserInfo.freeBytes = fileDetailsHelper.getHRSizeFromString( 66 | receipt.result.freeBytes); 67 | ocsUserInfo.totalBytes = fileDetailsHelper.getHRSizeFromString( 68 | receipt.result.totalBytes); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/app/qml/sfos/cover/CoverDetailItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | 4 | Item { 5 | id: detailItem 6 | width: parent.width 7 | height: Math.max(labelText.height, valueText.height) + 2*Theme.paddingSmall 8 | 9 | property alias label: labelText.text 10 | property alias value: valueText.text 11 | property real leftMargin: Theme.paddingMedium 12 | property real rightMargin: Theme.paddingMedium 13 | 14 | Text { 15 | id: labelText 16 | 17 | y: Theme.paddingSmall 18 | anchors { 19 | left: parent.left 20 | right: parent.horizontalCenter 21 | rightMargin: Theme.paddingSmall 22 | leftMargin: detailItem.leftMargin 23 | } 24 | horizontalAlignment: Text.AlignRight 25 | color: Theme.primaryColor 26 | font.pixelSize: Theme.fontSizeSmall 27 | //font.bold: true 28 | textFormat: Text.PlainText 29 | wrapMode: Text.WrapAnywhere 30 | } 31 | 32 | Text { 33 | id: valueText 34 | 35 | y: Theme.paddingSmall 36 | anchors { 37 | left: parent.horizontalCenter 38 | right: parent.right 39 | leftMargin: Theme.paddingSmall 40 | rightMargin: detailItem.rightMargin 41 | } 42 | horizontalAlignment: Text.AlignLeft 43 | color: Theme.highlightColor 44 | font.pixelSize: Theme.fontSizeSmall 45 | //font.bold: true 46 | textFormat: Text.PlainText 47 | wrapMode: Text.WrapAnywhere 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/qml/sfos/cover/CoverPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import SailfishUiSet 1.0 4 | 5 | CoverBackground { 6 | id: coverRoot 7 | anchors.fill: parent 8 | 9 | Image { 10 | readonly property int __positioningOffset : 64 11 | id: icon 12 | source: "qrc:/icons/icon_gray.svg" 13 | anchors.top: parent.top 14 | anchors.topMargin: -__positioningOffset 15 | anchors.right: parent.right 16 | anchors.rightMargin: -__positioningOffset 17 | anchors.left: parent.left 18 | anchors.leftMargin: __positioningOffset 19 | anchors.bottom: parent.verticalCenter 20 | anchors.bottomMargin: __positioningOffset 21 | fillMode: Image.PreserveAspectFit 22 | scale: 2 23 | sourceSize.width: width 24 | sourceSize.height: height 25 | visible: true 26 | } 27 | 28 | Column { 29 | visible: ocsUserInfo.userInfoEnabled 30 | anchors.centerIn: coverRoot 31 | width: coverRoot.width 32 | 33 | CoverDetailItem { 34 | width: parent.width 35 | label: qsTr("User:") 36 | value: ocsUserInfo.hrDisplayName 37 | visible: value.length > 0 38 | } 39 | CoverDetailItem { 40 | width: parent.width 41 | label: qsTr("Usage:") 42 | value: ocsUserInfo.hrUsedBytes 43 | visible: value.length > 0 44 | } 45 | CoverDetailItem { 46 | width: parent.width 47 | label: qsTr("Total:") 48 | value: ocsUserInfo.hrTotalBytes 49 | visible: value.length > 0 50 | } 51 | } 52 | 53 | BusyIndicator { 54 | anchors.centerIn: coverRoot 55 | size: BusyIndicatorSize.Large 56 | visible: isTransfering 57 | running: isTransfering 58 | } 59 | 60 | function findTransfers(page) { 61 | if(page.objectName === "TransferPage") { 62 | return true 63 | } 64 | return false 65 | } 66 | 67 | /*CoverActionList { 68 | enabled: isTransfering 69 | 70 | CoverAction { 71 | iconSource: "image://theme/icon-cover-transfers" 72 | onTriggered: { 73 | if (!pageStack.find(findTransfers)) { 74 | pageStack.push(transferPageComponent, {}, PageStackAction.Immediate); 75 | } 76 | 77 | if (!applicationWindow.applicationActive) { 78 | applicationWindow.activate() 79 | } 80 | } 81 | } 82 | }*/ 83 | } 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/app/qml/sfos/js/TransferUtil.js: -------------------------------------------------------------------------------- 1 | function isTransferEnqueued(remoteFilePath, accountWorkers) { 2 | for(var i = 0; i < accountWorkers.transferCommandQueue.queue.length; i++) { 3 | var info = accountWorkers.transferCommandQueue.queue[i].info; 4 | if (info.property("remoteFile") === remoteFilePath) { 5 | return true; 6 | } 7 | } 8 | return false; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/qml/sfos/navigation/CommandPageFlow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | // Inheriting items are supposed to manually connect 5 | // a handler to the commandFinished signal provided by 6 | // the accountWorker's CommandQueues 7 | property var accountWorkers : null 8 | property var directoryContents : null 9 | 10 | signal notificationRequest(string summary, string body) 11 | signal transientNotificationRequest(string summary) 12 | signal userInfoUpdateRequest() 13 | signal avatarFetchRequest() 14 | } 15 | -------------------------------------------------------------------------------- /src/app/qml/sfos/pages/AccountEntrance.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import "qrc:/qml/sfos/pages/browser" 4 | 5 | Item { 6 | Component.onCompleted: { 7 | pageStack.push(browserMain) 8 | } 9 | 10 | FileBrowser { 11 | id: browserMain 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/app/qml/sfos/pages/SettingsPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import harbour.owncloud 1.0 4 | 5 | Page { 6 | id: pageRoot 7 | 8 | property var accountWorkers : null 9 | property AccountDb accountDb : null 10 | 11 | onStatusChanged: { 12 | if (status === PageStatus.Deactivating) { 13 | if (_navigation === PageNavigation.Back) { 14 | accountDb.updateAccount(accountWorkers.account) 15 | daemonCtrl.reloadConfig() 16 | } 17 | } 18 | } 19 | 20 | SilicaFlickable { 21 | anchors.fill: parent 22 | 23 | PageHeader { 24 | id: pageHeader 25 | title: qsTr("Settings") 26 | } 27 | 28 | Column { 29 | spacing: Theme.paddingSmall 30 | anchors { 31 | top: pageHeader.bottom 32 | left: pageHeader.left 33 | right: pageHeader.right 34 | bottom: pageHeader.bottom 35 | } 36 | 37 | TextSwitch { 38 | id: cameraUploadSwitch 39 | text: qsTr("Camera photo backups") 40 | description: qsTr("Automatically save camera photos to your ownCloud instance when on WiFi", "Camera photo backups escription") 41 | visible: daemonCtrl.daemonInstalled 42 | checked: accountWorkers.account.uploadAutomatically 43 | onClicked: accountWorkers.account.uploadAutomatically = checked 44 | } 45 | 46 | TextSwitch { 47 | id: mobileCameraUploadSwitch 48 | text: qsTr("Photo backups via mobile internet connection") 49 | description: qsTr("Also automatically backup camera photos when connected via 2G, 3G or LTE", "hoto backups via mobile internet connection description") 50 | visible: daemonCtrl.daemonInstalled 51 | enabled: cameraUploadSwitch.checked 52 | checked: accountWorkers.account.mobileUpload 53 | onClicked: accountWorkers.account.mobileUpload = checked 54 | } 55 | 56 | Row { 57 | anchors.horizontalCenter: parent.horizontalCenter 58 | spacing: Theme.paddingLarge 59 | Button { 60 | text: qsTr("Clear cache") 61 | onClicked: accountWorkers.cacheProvider.clearCache() 62 | } 63 | 64 | Button { 65 | text: qsTr("Clear downloads") 66 | onClicked: accountWorkers.cacheProvider.clearDownloads() 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/app/qml/sfos/pages/login/FlowAuthentication.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import QtWebKit 3.0 4 | //import QtWebKit.experimental 1.0 5 | import harbour.owncloud 1.0 6 | 7 | Page { 8 | id: pageRoot 9 | // anchors.fill: parent 10 | 11 | FlowLoginAuthenticator { 12 | id: authenticator 13 | settings: persistentSettings 14 | onAuthenticationSuccessful: { 15 | pageStack.completeAnimation() 16 | pageStack.replace(browserComponent) 17 | } 18 | onAuthenticationFailed: { 19 | pageStack.completeAnimation() 20 | pageStack.replace(basicAuthenticationComponent) 21 | } 22 | onUrlChanged: { 23 | console.log("FlowLoginAuthenticator url: " + authenticator.url) 24 | } 25 | } 26 | 27 | SilicaFlickable { 28 | anchors.fill: parent 29 | 30 | SilicaWebView { 31 | id: webView 32 | anchors.fill: parent 33 | url: authenticator.url 34 | 35 | /*experimental.userAgent: "Nextcloud/OwnCloud Client for Sailfish" 36 | experimental.preferences.webGLEnabled: false 37 | experimental.preferences.localStorageEnabled: false 38 | experimental.preferences.webAudioEnabled: false 39 | experimental.preferences.developerExtrasEnabled: false*/ 40 | 41 | onNavigationRequested: { 42 | if (request.url.toString().indexOf("nc://") == 0) { 43 | request.action = WebView.IgnoreRequest; 44 | authenticator.validateFlowResponse(request.url) 45 | return; 46 | } 47 | request.action = WebView.AcceptRequest; 48 | console.log("loadRequest.url: " + request.url) 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/app/qml/sfos/pages/login/SSLErrorDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import harbour.owncloud 1.0 4 | 5 | Dialog { 6 | property AccountBase settings : null 7 | 8 | id: sslDialog 9 | anchors.fill: parent 10 | property string md5Digest; 11 | property string sha1Digest; 12 | 13 | SilicaListView { 14 | anchors.fill: parent 15 | 16 | DialogHeader { 17 | id: header 18 | } 19 | 20 | Label { 21 | id: hintLabel 22 | text: qsTr("Do you want to accept this certificate?") 23 | font.pixelSize: Theme.fontSizeExtraLarge 24 | color: Theme.highlightColor 25 | anchors.top: header.bottom 26 | anchors.topMargin: Theme.paddingLarge 27 | anchors.left: parent.left 28 | anchors.right: parent.right 29 | anchors.leftMargin: Theme.paddingMedium 30 | anchors.rightMargin: Theme.paddingMedium 31 | horizontalAlignment: Text.AlignHCenter 32 | wrapMode: Text.WrapAtWordBoundaryOrAnywhere 33 | } 34 | 35 | Label { 36 | id: md5Hint 37 | anchors.top: hintLabel.bottom 38 | anchors.topMargin: Theme.paddingLarge 39 | anchors.left: parent.left 40 | anchors.leftMargin: Theme.paddingMedium 41 | text: qsTr("MD5 fingerprint:") 42 | } 43 | 44 | Label { 45 | id: md5Label 46 | text: md5Digest 47 | font.pixelSize: Theme.fontSizeMedium 48 | wrapMode: Text.WrapAnywhere 49 | width: parent.width 50 | anchors.top: md5Hint.bottom 51 | anchors.left: parent.left 52 | anchors.right: parent.right 53 | anchors.leftMargin: Theme.paddingLarge 54 | anchors.rightMargin: Theme.paddingLarge 55 | } 56 | 57 | Label { 58 | id: sha1Hint 59 | anchors.top: md5Label.bottom 60 | anchors.topMargin: 32 61 | anchors.left: parent.left 62 | anchors.leftMargin: Theme.paddingMedium 63 | text: qsTr("SHA1 fingerprint:") 64 | } 65 | 66 | Label { 67 | id: sha1Label 68 | text: sha1Digest 69 | font.pixelSize: Theme.fontSizeMedium 70 | wrapMode: Text.WrapAnywhere 71 | width: parent.width 72 | anchors.top: sha1Hint.bottom 73 | anchors.left: parent.left 74 | anchors.right: parent.right 75 | anchors.leftMargin: Theme.paddingLarge 76 | anchors.rightMargin: Theme.paddingLarge 77 | } 78 | } 79 | 80 | onAccepted: { 81 | if (settings === null) { 82 | console.warn("Settings nullpointer ref, not accepting certificate") 83 | return; 84 | } 85 | 86 | settings.acceptTlsFingerprints(md5Digest, sha1Digest); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/app/qtquickcontrols2.conf: -------------------------------------------------------------------------------- 1 | ; This file can be edited to change the style of the application 2 | ; Read "Qt Quick Controls 2 Configuration File" for details: 3 | ; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html 4 | 5 | [Controls] 6 | Style=Material 7 | -------------------------------------------------------------------------------- /src/app/src/daemonctrl/daemoncontrol.h: -------------------------------------------------------------------------------- 1 | #ifndef DAEMONCONTROL_H 2 | #define DAEMONCONTROL_H 3 | 4 | #include 5 | #include 6 | 7 | #ifndef QT_NO_DBUS 8 | #include 9 | #endif 10 | 11 | class DaemonControl : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit DaemonControl(QObject *parent = Q_NULLPTR); 16 | 17 | Q_PROPERTY(bool daemonInstalled READ daemonInstalled NOTIFY daemonInstalledChanged) 18 | Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) 19 | 20 | bool uploading(); 21 | 22 | public slots: 23 | void reloadConfig(); 24 | void abort(); 25 | bool daemonInstalled(); 26 | 27 | private: 28 | void daemonRegistered(const QString& serviceName); 29 | void daemonUnregistered(const QString& serviceName); 30 | bool isCurrentlyUploading(); 31 | 32 | bool m_uploading; 33 | 34 | #ifndef QT_NO_DBUS 35 | QDBusInterface* m_daemonInterface = Q_NULLPTR; 36 | QDBusServiceWatcher* m_daemonWatcher = Q_NULLPTR; 37 | #endif 38 | 39 | signals: 40 | void daemonInstalledChanged(); 41 | void uploadingChanged(); 42 | 43 | private slots: 44 | void setUploading(bool value); 45 | }; 46 | 47 | #endif // DAEMONCONTROL_H 48 | -------------------------------------------------------------------------------- /src/app/src/daemonctrl/dummydaemonctrl.cpp: -------------------------------------------------------------------------------- 1 | #include "dummydaemonctrl.h" 2 | 3 | DaemonControl::DaemonControl(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/app/src/daemonctrl/dummydaemonctrl.h: -------------------------------------------------------------------------------- 1 | #ifndef DAEMONCONTROL_H 2 | #define DAEMONCONTROL_H 3 | 4 | #include 5 | 6 | // Dummy implementation 7 | class DaemonControl : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | 12 | Q_PROPERTY(bool daemonInstalled READ daemonInstalled NOTIFY daemonInstalledChanged) 13 | Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) 14 | 15 | explicit DaemonControl(QObject *parent = nullptr); 16 | 17 | bool uploading() { return false; } 18 | 19 | public slots: 20 | bool daemonInstalled() { return false; } 21 | void reloadConfig() {} 22 | void abort() {} 23 | 24 | signals: 25 | void daemonInstalledChanged(); 26 | void uploadingChanged(); 27 | 28 | }; 29 | 30 | #endif // DAEMONCONTROL_H 31 | -------------------------------------------------------------------------------- /src/app/src/directorycontentmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "directorycontentmodel.h" 2 | 3 | DirectoryContentModel::DirectoryContentModel(QObject *parent) 4 | : QAbstractListModel(parent) 5 | { 6 | } 7 | 8 | /*QVariant DirectoryContentModel::headerData(int section, Qt::Orientation orientation, int role) const 9 | { 10 | // FIXME: Implement me! 11 | } 12 | 13 | bool DirectoryContentModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) 14 | { 15 | if (value != headerData(section, orientation, role)) { 16 | // FIXME: Implement me! 17 | emit headerDataChanged(orientation, section, section); 18 | return true; 19 | } 20 | return false; 21 | }*/ 22 | 23 | int DirectoryContentModel::rowCount(const QModelIndex &parent) const 24 | { 25 | // For list models only the root node (an invalid parent) should return the list's size. For all 26 | // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. 27 | if (parent.isValid()) 28 | return 0; 29 | 30 | // FIXME: Implement me! 31 | return this->m_contentList.size(); 32 | } 33 | 34 | QVariant DirectoryContentModel::data(const QModelIndex &index, int role) const 35 | { 36 | Q_UNUSED(role) 37 | 38 | if (!index.isValid()) 39 | return QVariant(); 40 | 41 | if (index.row() > this->m_contentList.size()) 42 | return QVariant(); 43 | 44 | return this->m_contentList.at(index.row()); 45 | } 46 | 47 | bool DirectoryContentModel::setData(const QModelIndex &index, const QVariant &value, int role) 48 | { 49 | if (data(index, role) != value) { 50 | this->m_contentList.insert(index.row(), value); 51 | emit dataChanged(index, index, QVector() << role); 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | Qt::ItemFlags DirectoryContentModel::flags(const QModelIndex &index) const 58 | { 59 | if (!index.isValid()) 60 | return Qt::NoItemFlags; 61 | if (index.row() > this->m_contentList.size()) 62 | return Qt::NoItemFlags; 63 | 64 | return Qt::ItemIsEditable; // FIXME: Implement me! 65 | } 66 | 67 | /* 68 | bool DirectoryContentModel::insertRows(int row, int count, const QModelIndex &parent) 69 | { 70 | beginInsertRows(parent, row, row + count - 1); 71 | // FIXME: Implement me! 72 | endInsertRows(); 73 | } 74 | 75 | bool DirectoryContentModel::removeRows(int row, int count, const QModelIndex &parent) 76 | { 77 | beginRemoveRows(parent, row, row + count - 1); 78 | // FIXME: Implement me! 79 | endRemoveRows(); 80 | } 81 | */ 82 | -------------------------------------------------------------------------------- /src/app/src/directorycontentmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTORYCONTENTMODEL_H 2 | #define DIRECTORYCONTENTMODEL_H 3 | 4 | #include 5 | #include 6 | 7 | class DirectoryContentModel : public QAbstractListModel 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit DirectoryContentModel(QObject *parent = Q_NULLPTR); 13 | 14 | // Header: 15 | //QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 16 | 17 | //bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; 18 | 19 | // Basic functionality: 20 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 21 | 22 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 23 | 24 | // Editable: 25 | bool setData(const QModelIndex &index, const QVariant &value, 26 | int role = Qt::EditRole) override; 27 | 28 | Qt::ItemFlags flags(const QModelIndex& index) const override; 29 | 30 | // Add data: 31 | //bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; 32 | 33 | // Remove data: 34 | //bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; 35 | 36 | private: 37 | QVariantList m_contentList; 38 | }; 39 | Q_DECLARE_METATYPE(DirectoryContentModel*) 40 | 41 | #endif // DIRECTORYCONTENTMODEL_H 42 | -------------------------------------------------------------------------------- /src/app/src/ocsnetaccessfactory.cpp: -------------------------------------------------------------------------------- 1 | #include "ocsnetaccessfactory.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | OscNetAccess::OscNetAccess(QObject* parent, AccountBase* settings) : 9 | QNetworkAccessManager(parent), m_settings(settings) 10 | { 11 | QObject::connect(this, &OscNetAccess::sslErrors, 12 | this, [=](QNetworkReply* reply, const QList &errors) { 13 | if (errors.length() > 0) { 14 | QSslCertificate sslcert = errors[0].certificate(); 15 | const QString md5Digest = sslcert.digest(QCryptographicHash::Md5); 16 | const QString sha1Digest = sslcert.digest(QCryptographicHash::Sha1); 17 | 18 | if (md5Digest == hexToDigest(this->m_settings->md5Hex()) && 19 | sha1Digest == hexToDigest(this->m_settings->sha1Hex())) { 20 | reply->ignoreSslErrors(); 21 | 22 | return; 23 | } 24 | } 25 | 26 | qWarning() << "OscNetAccess: unhandled SSL error occured"; 27 | });} 28 | 29 | QNetworkReply* OscNetAccess::createRequest(Operation op, 30 | const QNetworkRequest &request, 31 | QIODevice *outgoingData) 32 | { 33 | // Create QNetworkRequest with proper authorization headers 34 | // if a settings object has been provided at construction time. 35 | const QNetworkRequest actualRequest = this->m_settings ? 36 | getOcsRequest(request, this->m_settings) : 37 | request; 38 | 39 | return QNetworkAccessManager::createRequest(op, 40 | actualRequest, 41 | outgoingData); 42 | } 43 | 44 | OcsNetAccessFactory::OcsNetAccessFactory(AccountBase *settings) 45 | : m_settings(settings) 46 | { 47 | qDebug() << Q_FUNC_INFO; 48 | } 49 | 50 | OcsNetAccessFactory::OcsNetAccessFactory(const OcsNetAccessFactory &o) 51 | { 52 | qDebug() << Q_FUNC_INFO; 53 | this->m_settings = o.m_settings; 54 | } 55 | 56 | QNetworkAccessManager* OcsNetAccessFactory::create(QObject *parent) 57 | { 58 | qDebug() << Q_FUNC_INFO; 59 | 60 | OscNetAccess *nam = new OscNetAccess(parent, this->m_settings); 61 | QNetworkDiskCache* cache = new QNetworkDiskCache(nam); 62 | cache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); 63 | nam->setCache(cache); 64 | return nam; 65 | } 66 | 67 | /*QUrl OcsNetAccessFactory::intercept(const QUrl& url, DataType type) 68 | { 69 | 70 | if (type != QQmlAbstractUrlInterceptor::UrlString) 71 | return url; 72 | 73 | qDebug() << Q_FUNC_INFO << url.scheme() << url; 74 | 75 | if (!(url.scheme().startsWith(QStringLiteral("http://")) || 76 | url.scheme().startsWith(QStringLiteral("https://")))) 77 | return url; 78 | 79 | return url; 80 | }*/ 81 | -------------------------------------------------------------------------------- /src/app/src/ocsnetaccessfactory.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSNETACCESSFACTORY_H 2 | #define OCSNETACCESSFACTORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | class OscNetAccess : public QNetworkAccessManager 15 | { 16 | Q_OBJECT 17 | public: 18 | explicit OscNetAccess(QObject* parent = Q_NULLPTR, 19 | AccountBase* settings = Q_NULLPTR); 20 | 21 | private: 22 | AccountBase* m_settings = Q_NULLPTR; 23 | 24 | public: 25 | QNetworkReply* createRequest(Operation op, 26 | const QNetworkRequest &request, 27 | QIODevice* outgoingData) Q_DECL_OVERRIDE; 28 | }; 29 | 30 | class OcsNetAccessFactory : 31 | //public QQmlAbstractUrlInterceptor, 32 | public QQmlNetworkAccessManagerFactory 33 | { 34 | public: 35 | OcsNetAccessFactory(AccountBase* settings = Q_NULLPTR); 36 | OcsNetAccessFactory(const OcsNetAccessFactory& o); 37 | 38 | //QUrl intercept(const QUrl& url, DataType type) Q_DECL_OVERRIDE; 39 | QNetworkAccessManager* create(QObject *parent) Q_DECL_OVERRIDE; 40 | 41 | private: 42 | AccountBase* m_settings = Q_NULLPTR; 43 | }; 44 | 45 | 46 | #endif // OCSNETACCESSFACTORY_H 47 | -------------------------------------------------------------------------------- /src/app/src/os/android/intentfileselector.cpp: -------------------------------------------------------------------------------- 1 | #include "intentfileselector.h" 2 | 3 | #include 4 | #include 5 | 6 | IntentFileSelector::IntentFileSelector(QObject *parent) : QObject(parent) 7 | { 8 | QObject::connect(&this->m_resultReceiver, &IntentFileSelectorReceiver::filePathReceived, 9 | this, &IntentFileSelector::fileSelected, 10 | Qt::QueuedConnection); 11 | } 12 | 13 | void IntentFileSelector::fileSelectIntent() 14 | { 15 | QAndroidJniObject ACTION_GET_CONTENT = 16 | QAndroidJniObject::fromString("android.intent.action.GET_CONTENT"); 17 | QAndroidJniObject intent("android/content/Intent"); 18 | 19 | if (!(ACTION_GET_CONTENT.isValid() && intent.isValid())) { 20 | return; 21 | } 22 | 23 | intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", 24 | ACTION_GET_CONTENT.object()); 25 | intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", 26 | QAndroidJniObject::fromString("*/*").object()); 27 | 28 | QtAndroid::startActivity(intent.object(), 29 | IntentFileSelectorReceiver::GET_FILE_REQUEST_CODE, 30 | &this->m_resultReceiver); 31 | } 32 | -------------------------------------------------------------------------------- /src/app/src/os/android/intentfileselector.h: -------------------------------------------------------------------------------- 1 | #ifndef INTENTFILESELECTOR_H 2 | #define INTENTFILESELECTOR_H 3 | 4 | #include 5 | #include "intentfileselectorreceiver.h" 6 | 7 | class IntentFileSelector : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit IntentFileSelector(QObject *parent = nullptr); 12 | 13 | public slots: 14 | void fileSelectIntent(); 15 | 16 | private: 17 | IntentFileSelectorReceiver m_resultReceiver; 18 | 19 | signals: 20 | void fileSelected(const QString& filePath); 21 | 22 | }; 23 | 24 | #endif // INTENTFILESELECTOR_H 25 | -------------------------------------------------------------------------------- /src/app/src/os/android/intentfileselectorreceiver.cpp: -------------------------------------------------------------------------------- 1 | #include "intentfileselectorreceiver.h" 2 | 3 | #include 4 | #include 5 | 6 | IntentFileSelectorReceiver::IntentFileSelectorReceiver(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | QString IntentFileSelectorReceiver::resolveUri(const QString& uri) 12 | { 13 | QAndroidJniObject jUrl = QAndroidJniObject::fromString(uri); 14 | QAndroidJniObject resolvedUri = 15 | QAndroidJniObject::callStaticObjectMethod( 16 | "me/fredl/ghostcloud/ShareUtil", 17 | "getFilePathForContent", 18 | "(Ljava/lang/String;)Ljava/lang/String;", 19 | jUrl.object()); 20 | 21 | const QString resolvedUriString = resolvedUri.toString(); 22 | qDebug() << "RESOLVED URI:" << resolvedUriString; 23 | 24 | return resolvedUriString; 25 | } 26 | 27 | void IntentFileSelectorReceiver::handleActivityResult(int receiverRequestCode, 28 | int resultCode, 29 | const QAndroidJniObject &data) 30 | { 31 | if (receiverRequestCode != GET_FILE_REQUEST_CODE) { 32 | qWarning() << "Request code" << resultCode << "received"; 33 | return; 34 | } 35 | 36 | if (resultCode == 0) { 37 | qWarning() << "Invalid result code"; 38 | return; 39 | } 40 | 41 | const QAndroidJniObject content = 42 | data.callObjectMethod("getDataString"); 43 | const QString filePath = resolveUri(content.toString()); 44 | 45 | qDebug() << "content: " << content.toString(); 46 | qDebug() << "file path: " << filePath; 47 | Q_EMIT filePathReceived(filePath); 48 | } 49 | -------------------------------------------------------------------------------- /src/app/src/os/android/intentfileselectorreceiver.h: -------------------------------------------------------------------------------- 1 | #ifndef INTENTFILESELECTORRECEIVER_H 2 | #define INTENTFILESELECTORRECEIVER_H 3 | 4 | #include 5 | #include 6 | 7 | class IntentFileSelectorReceiver : 8 | public QObject, 9 | public QAndroidActivityResultReceiver 10 | { 11 | Q_OBJECT 12 | public: 13 | const static int GET_FILE_REQUEST_CODE = 200; 14 | 15 | explicit IntentFileSelectorReceiver(QObject *parent = nullptr); 16 | virtual void handleActivityResult(int receiverRequestCode, 17 | int resultCode, 18 | const QAndroidJniObject &data) Q_DECL_OVERRIDE; 19 | 20 | private: 21 | QString resolveUri(const QString& uri); 22 | 23 | signals: 24 | void filePathReceived(const QString& filePath); 25 | 26 | }; 27 | 28 | #endif // INTENTFILESELECTORRECEIVER_H 29 | -------------------------------------------------------------------------------- /src/app/src/os/dummy/dummyintentfileselector.cpp: -------------------------------------------------------------------------------- 1 | #include "dummyintentfileselector.h" 2 | 3 | #include 4 | 5 | DummyIntentFileSelector::DummyIntentFileSelector(QObject *parent) : QObject(parent) 6 | { 7 | 8 | } 9 | 10 | void DummyIntentFileSelector::fileSelectIntent() 11 | { 12 | qInfo() << "NOT IMPLEMENTED"; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/src/os/dummy/dummyintentfileselector.h: -------------------------------------------------------------------------------- 1 | #ifndef DUMMYINTENTFILESELECTOR_H 2 | #define DUMMYINTENTFILESELECTOR_H 3 | 4 | #include 5 | 6 | class DummyIntentFileSelector : public QObject 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit DummyIntentFileSelector(QObject *parent = nullptr); 11 | 12 | public slots: 13 | void fileSelectIntent(); 14 | 15 | signals: 16 | void fileSelected(const QString& filePath); 17 | 18 | }; 19 | 20 | #endif // DUMMYINTENTFILESELECTOR_H 21 | -------------------------------------------------------------------------------- /src/app/src/webdavmediafeeder.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBDAVMEDIAFEEDER_H 2 | #define WEBDAVMEDIAFEEDER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class WebDavMediaFeeder : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QObject* mediaPlayer READ mediaPlayer 13 | WRITE setMediaPlayer 14 | NOTIFY mediaPlayerChanged) 15 | Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) 16 | Q_PROPERTY(AccountBase* settings READ settings WRITE setSettings NOTIFY settingsChanged) 17 | 18 | public: 19 | explicit WebDavMediaFeeder( 20 | QObject* parent = Q_NULLPTR, 21 | QObject* mediaPlayer = Q_NULLPTR, 22 | AccountBase* settings = Q_NULLPTR); 23 | ~WebDavMediaFeeder(); 24 | 25 | void setMediaPlayer(QObject* object); 26 | QObject* mediaPlayer(); 27 | void setUrl(const QUrl& url); 28 | QUrl url(); 29 | AccountBase* settings(); 30 | void setSettings(AccountBase* v); 31 | 32 | public slots: 33 | void play(); 34 | void pause(); 35 | void stop(); 36 | 37 | private: 38 | QObject* m_mediaPlayer = Q_NULLPTR; 39 | AccountBase* m_settings = Q_NULLPTR; 40 | QUrl m_url; 41 | 42 | signals: 43 | void mediaPlayerChanged(); 44 | void urlChanged(); 45 | void settingsChanged(); 46 | }; 47 | 48 | #endif // WEBDAVMEDIAFEEDER_H 49 | -------------------------------------------------------------------------------- /src/app/theme.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/theme/index.theme 4 | icons/theme/actions/32/view-refresh.svg 5 | icons/theme/actions/32/folder-new.svg 6 | icons/theme/actions/32/document-new.svg 7 | icons/theme/places/64/folder.svg 8 | icons/theme/actions/symbolic/window-close-symbolic.svg 9 | icons/theme/mimetypes/64/image-x-generic.svg 10 | icons/theme/mimetypes/64/audio-x-generic.svg 11 | icons/theme/mimetypes/64/video-x-generic.svg 12 | icons/theme/mimetypes/64/text-x-plain.svg 13 | icons/theme/actions/32/application-menu.svg 14 | icons/theme/actions/32/media-playback-pause.svg 15 | icons/theme/actions/32/media-playback-start.svg 16 | qtquickcontrols2.conf 17 | icons/theme/actions/32/go-previous.svg 18 | icons/theme/actions/24/list-add.svg 19 | icons/theme/actions/32/go-down.svg 20 | icons/theme/actions/32/go-up.svg 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/common/common.pri: -------------------------------------------------------------------------------- 1 | CONFIG += qt c++11 2 | QT += network xml sql 3 | 4 | linux:!android { 5 | !contains(CONFIG, quickcontrols) { 6 | QT += dbus 7 | } 8 | } 9 | android { 10 | QT += androidextras 11 | } 12 | 13 | DEFINES += QWEBDAVITEM_EXTENDED_PROPERTIES 14 | 15 | !macx { 16 | CONFIG(release, debug|release) { 17 | QMAKE_POST_LINK=$(STRIP) $(TARGET) 18 | DEFINES += QT_NO_DEBUG_OUTPUT 19 | } 20 | } 21 | 22 | contains(CONFIG, quickcontrols) { 23 | DEFINES += GHOSTCLOUD_UI_QUICKCONTROLS 24 | } 25 | 26 | INCLUDEPATH += $$PWD/src 27 | DEPENDPATH += $$PWD/src 28 | INCLUDEPATH += $$PWD/../../3rdparty/libqtcommandqueue/src 29 | DEPENDPATH += $$PWD/../../3rdparty/libqtcommandqueue/src 30 | 31 | INCLUDEPATH += $$PWD/../../3rdparty/qwebdavlib/qwebdavlib 32 | DEPENDPATH += $$PWD/../../3rdparty/qwebdavlib/qwebdavlib 33 | 34 | android { 35 | LIBS += $$OUT_PWD/../../3rdparty/openssl/libcrypto.so 36 | LIBS += $$OUT_PWD/../../3rdparty/openssl/libssl.so 37 | LIBS += $$OUT_PWD/../../3rdparty/qwebdavlib/qwebdavlib/libqwebdav.so 38 | LIBS += $$OUT_PWD/../../src/common/libharbourowncloudcommon.so 39 | } 40 | 41 | linux:!android { 42 | LIBS += $$OUT_PWD/../../3rdparty/qwebdavlib/qwebdavlib/libqwebdav.so.1 43 | LIBS += $$OUT_PWD/../../src/common/libharbourowncloudcommon.so.1 44 | } 45 | 46 | # Build everything statically on macOS 47 | macx { 48 | include($$PWD/../../3rdparty/qwebdavlib/qwebdavlib/qwebdavlib.pri) 49 | } 50 | 51 | ios { 52 | LIBS += $$OUT_PWD/../../3rdparty/qwebdavlib/qwebdavlib/libqwebdav.a 53 | CONFIG(release, debug|release) { 54 | LIBS += $$OUT_PWD/../../src/common/libharbourowncloudcommon.a 55 | } 56 | CONFIG(debug, debug|release) { 57 | LIBS += $$OUT_PWD/../../src/common/libharbourowncloudcommon_debug.a 58 | } 59 | } 60 | 61 | # Sailfish additionals 62 | contains(CONFIG, sailfish_build) { 63 | CONFIG += ghostcloud_link 64 | QMAKE_RPATHDIR += /usr/share/harbour-owncloud/lib 65 | } 66 | 67 | # Ubuntu Touch configuration 68 | contains(CONFIG, click) { 69 | DEFINES += GHOSTCLOUD_UBUNTU_TOUCH 70 | DEFINES += OS_SUPPORTS_THEME_PROVIDER # Qml-Ui-Set 71 | } 72 | 73 | # Ubuntu Touch Photo Backup configuration 74 | contains(CONFIG, clickphotobackup) { 75 | DEFINES += GHOSTCLOUD_UBUNTU_TOUCH_PHOTOBACKUP 76 | CONFIG += ghostcloud_link 77 | } 78 | 79 | contains(CONFIG, ghostcloud_link) { 80 | LIBS += $$OUT_PWD/../../3rdparty/qwebdavlib/qwebdavlib/libqwebdav.so.1 81 | LIBS += $$OUT_PWD/../../src/common/libharbourowncloudcommon.so.1 82 | } 83 | -------------------------------------------------------------------------------- /src/common/src/accountworkergenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCOUNTWORKERGENERATOR_H 2 | #define ACCOUNTWORKERGENERATOR_H 3 | 4 | #include 5 | #include "accountworkers.h" 6 | #include 7 | #include "settings/db/accountdb.h" 8 | #include 9 | 10 | class AccountWorkerGenerator : public QObject 11 | { 12 | Q_OBJECT 13 | 14 | Q_PROPERTY(QVariantList accountWorkers READ accountWorkers NOTIFY accountWorkersChanged) 15 | Q_PROPERTY(AccountsDbInterface* database READ database WRITE setDatabase NOTIFY databaseChanged) 16 | 17 | public: 18 | explicit AccountWorkerGenerator(QObject *parent = nullptr); 19 | 20 | QVariantList accountWorkers(); 21 | QVector accountWorkersVector(); 22 | AccountsDbInterface* database(); 23 | void setDatabase(AccountsDbInterface* database); 24 | 25 | public slots: 26 | AccountWorkers* newAccount(); 27 | 28 | private: 29 | void setAccountWorkers(QVector accountWorkers); 30 | void generateAccountWorkers(); 31 | void cleanup(); 32 | 33 | AccountsDbInterface* m_database = Q_NULLPTR; 34 | QVector m_accountWorkers; 35 | std::unique_ptr m_defaultNewAW; 36 | 37 | signals: 38 | void accountWorkersChanged(); 39 | void databaseChanged(); 40 | 41 | }; 42 | 43 | #endif // ACCOUNTWORKERGENERATOR_H 44 | -------------------------------------------------------------------------------- /src/common/src/accountworkers.cpp: -------------------------------------------------------------------------------- 1 | #include "accountworkers.h" 2 | 3 | AccountWorkers::AccountWorkers() : AccountWorkers(Q_NULLPTR, 4 | new AccountBase) 5 | { 6 | } 7 | 8 | AccountWorkers::AccountWorkers(QObject *parent, 9 | AccountBase* account, 10 | CloudStorageProvider* browserCommandQueue, 11 | CloudStorageProvider* transferCommandQueue, 12 | AccountInfoProvider* accountInfoCommandQueue, 13 | SharingProvider* sharingProvider) : 14 | QObject(parent), 15 | m_account(account), 16 | m_browserCommandQueue(browserCommandQueue), 17 | m_transferCommandQueue(transferCommandQueue), 18 | m_accountInfoCommandQueue(accountInfoCommandQueue), 19 | m_sharingProvider(sharingProvider) 20 | { 21 | this->m_cacheProvider = new CacheProvider(this, account); 22 | this->m_avatarFetcher = new AvatarFetcher(this); 23 | this->m_avatarFetcher->setCacheProvider(this->m_cacheProvider); 24 | this->m_avatarFetcher->setCommandQueue(this->m_browserCommandQueue); 25 | this->m_thumbnailFetcher = new ThumbnailFetcher(this); 26 | this->m_thumbnailFetcher->setCacheProvider(this->m_cacheProvider); 27 | this->m_thumbnailFetcher->setCommandQueue(this->m_browserCommandQueue); 28 | } 29 | 30 | AccountBase* AccountWorkers::account() 31 | { 32 | return this->m_account; 33 | } 34 | 35 | CloudStorageProvider* AccountWorkers::browserCommandQueue() 36 | { 37 | return this->m_browserCommandQueue; 38 | } 39 | 40 | CloudStorageProvider* AccountWorkers::transferCommandQueue() 41 | { 42 | return this->m_transferCommandQueue; 43 | } 44 | 45 | AccountInfoProvider* AccountWorkers::accountInfoCommandQueue() 46 | { 47 | return this->m_accountInfoCommandQueue; 48 | } 49 | 50 | SharingProvider* AccountWorkers::sharingProviderCommandQueue() 51 | { 52 | return this->m_sharingProvider; 53 | } 54 | 55 | CacheProvider* AccountWorkers::cacheProvider() 56 | { 57 | return this->m_cacheProvider; 58 | } 59 | 60 | AvatarFetcher* AccountWorkers::avatarFetcher() 61 | { 62 | return this->m_avatarFetcher; 63 | } 64 | 65 | ThumbnailFetcher* AccountWorkers::thumbnailFetcher() 66 | { 67 | return this->m_thumbnailFetcher; 68 | } 69 | -------------------------------------------------------------------------------- /src/common/src/accountworkers.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCOUNTWORKERS_H 2 | #define ACCOUNTWORKERS_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class AccountWorkers : public QObject 15 | { 16 | Q_OBJECT 17 | 18 | Q_PROPERTY(AccountBase* account READ account CONSTANT) 19 | Q_PROPERTY(CloudStorageProvider* browserCommandQueue READ browserCommandQueue CONSTANT) 20 | Q_PROPERTY(CloudStorageProvider* transferCommandQueue READ transferCommandQueue CONSTANT) 21 | Q_PROPERTY(AccountInfoProvider* accountInfoCommandQueue READ accountInfoCommandQueue CONSTANT) 22 | Q_PROPERTY(SharingProvider* sharingProvider READ sharingProviderCommandQueue CONSTANT) 23 | Q_PROPERTY(AvatarFetcher* avatarFetcher READ avatarFetcher CONSTANT) 24 | Q_PROPERTY(CacheProvider* cacheProvider READ cacheProvider CONSTANT) 25 | Q_PROPERTY(ThumbnailFetcher* thumbnailFetcher READ thumbnailFetcher CONSTANT) 26 | 27 | public: 28 | explicit AccountWorkers(); 29 | explicit AccountWorkers(QObject *parent, 30 | AccountBase* account = Q_NULLPTR, 31 | CloudStorageProvider* browserCommandQueue = Q_NULLPTR, 32 | CloudStorageProvider* transferCommandQueue = Q_NULLPTR, 33 | AccountInfoProvider* accountInfoCommandQueue = Q_NULLPTR, 34 | SharingProvider* sharingProvider = Q_NULLPTR); 35 | 36 | AccountBase* account(); 37 | CloudStorageProvider* browserCommandQueue(); 38 | CloudStorageProvider* transferCommandQueue(); 39 | AccountInfoProvider* accountInfoCommandQueue(); 40 | SharingProvider* sharingProviderCommandQueue(); 41 | CacheProvider* cacheProvider(); 42 | AvatarFetcher* avatarFetcher(); 43 | ThumbnailFetcher* thumbnailFetcher(); 44 | 45 | private: 46 | AccountBase* m_account = Q_NULLPTR; 47 | CloudStorageProvider* m_browserCommandQueue = Q_NULLPTR; 48 | CloudStorageProvider* m_transferCommandQueue = Q_NULLPTR; 49 | AccountInfoProvider* m_accountInfoCommandQueue = Q_NULLPTR; 50 | SharingProvider* m_sharingProvider = Q_NULLPTR; 51 | CacheProvider* m_cacheProvider = Q_NULLPTR; 52 | AvatarFetcher* m_avatarFetcher = Q_NULLPTR; 53 | ThumbnailFetcher* m_thumbnailFetcher = Q_NULLPTR; 54 | }; 55 | Q_DECLARE_METATYPE(AccountWorkers*) 56 | 57 | #endif // ACCOUNTWORKERS_H 58 | -------------------------------------------------------------------------------- /src/common/src/auth/authenticationexaminer.cpp: -------------------------------------------------------------------------------- 1 | #include "authenticationexaminer.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | AuthenticationExaminer::AuthenticationExaminer(QObject *parent) : 8 | QObject(parent) 9 | { 10 | 11 | } 12 | 13 | bool AuthenticationExaminer::examine(QString serverUrl, AuthenticationMethod method) 14 | { 15 | const QUrl urlParser = QUrl(serverUrl); 16 | if (!urlParser.isValid() || urlParser.host().isEmpty()) { 17 | qDebug() << "Provided server url" << serverUrl << "invalid, aborting examination."; 18 | Q_EMIT examinationFailed(method); 19 | return false; 20 | } 21 | 22 | this->m_tempSettings.setHoststring(serverUrl); 23 | 24 | switch (method) { 25 | case AuthenticationMethod::FLOW_DIALOG: 26 | { 27 | HttpGetCommandEntity* flowExamination = new HttpGetCommandEntity(this, 28 | NEXTCLOUD_ENDPOINT_LOGIN_FLOW, 29 | QMap(), 30 | &this->m_tempSettings); 31 | QObject::connect(flowExamination, &HttpGetCommandEntity::done, 32 | this, [=]() { 33 | const int statusCode = flowExamination->resultData()["statusCode"].toInt(); 34 | if (statusCode < 200 || statusCode >= 300) 35 | Q_EMIT examinationFailed(AuthenticationMethod::FLOW_DIALOG); 36 | else 37 | Q_EMIT examinationSucceeded(AuthenticationMethod::FLOW_DIALOG); 38 | flowExamination->deleteLater(); 39 | }); 40 | QObject::connect(flowExamination, &HttpGetCommandEntity::aborted, 41 | this, [=]() { 42 | Q_EMIT examinationFailed(AuthenticationMethod::FLOW_DIALOG); 43 | flowExamination->deleteLater(); 44 | }); 45 | flowExamination->run(); 46 | break; 47 | } 48 | default: 49 | break; 50 | } 51 | 52 | Q_EMIT examinationSucceeded(method); 53 | return true; 54 | } 55 | 56 | void AuthenticationExaminer::setRunning(bool v) 57 | { 58 | if (this->m_running == v) 59 | return; 60 | 61 | this->m_running = v; 62 | Q_EMIT runningChanged(); 63 | } 64 | 65 | bool AuthenticationExaminer::running() 66 | { 67 | return this->m_running; 68 | } 69 | -------------------------------------------------------------------------------- /src/common/src/auth/authenticationexaminer.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTHENTICATIONEXAMINER_H 2 | #define AUTHENTICATIONEXAMINER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class AuthenticationExaminer : public QObject 11 | { 12 | Q_OBJECT 13 | 14 | Q_PROPERTY(bool running READ running NOTIFY runningChanged) 15 | 16 | public: 17 | explicit AuthenticationExaminer(QObject *parent = Q_NULLPTR); 18 | enum AuthenticationMethod { 19 | QWEBDAV = 0, 20 | FLOW_DIALOG 21 | }; 22 | Q_ENUM(AuthenticationMethod) 23 | bool running(); 24 | 25 | public slots: 26 | bool examine(QString serverUrl, AuthenticationMethod method); 27 | 28 | private: 29 | AuthenticationMethod m_method; 30 | AccountBase m_tempSettings; 31 | 32 | void setRunning(bool v); 33 | bool m_running = false; 34 | 35 | signals: 36 | void examinationFailed(AuthenticationMethod method); 37 | void examinationSucceeded(AuthenticationMethod method); 38 | void runningChanged(); 39 | }; 40 | Q_DECLARE_METATYPE(AuthenticationExaminer*) 41 | 42 | #endif // AUTHENTICATIONEXAMINER_H 43 | -------------------------------------------------------------------------------- /src/common/src/auth/authenticator.cpp: -------------------------------------------------------------------------------- 1 | #include "authenticator.h" 2 | 3 | #include 4 | 5 | Authenticator::Authenticator(QObject *parent, AccountBase* settings) : 6 | QObject(parent), m_settings(settings) 7 | { 8 | } 9 | 10 | AccountBase* Authenticator::settings() 11 | { 12 | return this->m_settings; 13 | } 14 | 15 | void Authenticator::setSettings(AccountBase *v) 16 | { 17 | qDebug() << Q_FUNC_INFO << v; 18 | if (this->m_settings == v) 19 | return; 20 | 21 | if (this->m_settings) 22 | QObject::disconnect(this->m_settings, 23 | nullptr, 24 | nullptr, 25 | nullptr); 26 | 27 | this->m_settings = v; 28 | 29 | // Connect to changes of credentials, certificate and hostname settings 30 | if (this->m_settings) { 31 | QObject::connect(this->m_settings, &AccountBase::hoststringChanged, 32 | this, &Authenticator::updateClientSettings); 33 | QObject::connect(this->m_settings, &AccountBase::usernameChanged, 34 | this, &Authenticator::updateClientSettings); 35 | QObject::connect(this->m_settings, &AccountBase::passwordChanged, 36 | this, &Authenticator::updateClientSettings); 37 | QObject::connect(this->m_settings, &AccountBase::providerTypeChanged, 38 | this, &Authenticator::updateClientSettings); 39 | QObject::connect(this->m_settings, &AccountBase::customCertChanged, 40 | this, &Authenticator::updateClientSettings); 41 | } 42 | 43 | Q_EMIT settingsChanged(); 44 | } 45 | 46 | bool Authenticator::running() 47 | { 48 | return this->m_running; 49 | } 50 | 51 | void Authenticator::setRunning(bool v) 52 | { 53 | if (this->m_running == v) 54 | return; 55 | 56 | this->m_running = v; 57 | Q_EMIT runningChanged(); 58 | } 59 | -------------------------------------------------------------------------------- /src/common/src/auth/authenticator.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTHENTICATOR_H 2 | #define AUTHENTICATOR_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | class Authenticator : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(AccountBase* settings READ settings WRITE setSettings NOTIFY settingsChanged) 13 | Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) 14 | 15 | public: 16 | explicit Authenticator(QObject *parent = Q_NULLPTR, 17 | AccountBase* settings = Q_NULLPTR); 18 | 19 | public slots: 20 | virtual void authenticate() = 0; 21 | virtual void abort() = 0; 22 | 23 | protected: 24 | virtual void updateClientSettings() = 0; 25 | 26 | AccountBase* settings(); 27 | void setSettings(AccountBase* v); 28 | bool running(); 29 | void setRunning(bool v); 30 | 31 | private: 32 | AccountBase* m_settings = Q_NULLPTR; 33 | bool m_running = false; 34 | 35 | signals: 36 | void authenticationFailed(); 37 | void sslError(QString certMd5, QString certSha1); 38 | void authenticationSuccessful(); 39 | void settingsChanged(); 40 | void runningChanged(); 41 | }; 42 | Q_DECLARE_METATYPE(Authenticator*) 43 | 44 | #endif // AUTHENTICATOR_H 45 | -------------------------------------------------------------------------------- /src/common/src/auth/flowloginauthenticator.cpp: -------------------------------------------------------------------------------- 1 | #include "flowloginauthenticator.h" 2 | 3 | #include 4 | #include 5 | 6 | FlowLoginAuthenticator::FlowLoginAuthenticator(QObject *parent, 7 | AccountBase* settings) : 8 | Authenticator(parent, settings) 9 | { 10 | QObject::connect(this, &FlowLoginAuthenticator::settingsChanged, 11 | this, &FlowLoginAuthenticator::urlChanged); 12 | } 13 | 14 | void FlowLoginAuthenticator::authenticate() 15 | { 16 | // TODO: implement 17 | 18 | setRunning(true); 19 | } 20 | 21 | void FlowLoginAuthenticator::abort() 22 | { 23 | setRunning(false); 24 | } 25 | 26 | 27 | void FlowLoginAuthenticator::validateFlowResponse(QString responseUrl) 28 | { 29 | setRunning(false); 30 | 31 | const QUrl ncUrl(responseUrl); 32 | 33 | if (ncUrl.scheme() != QStringLiteral("nc://")) { 34 | qWarning() << "Scheme" << ncUrl.scheme() << "is not valid"; 35 | Q_EMIT authenticationFailed(); 36 | return; 37 | } 38 | 39 | QStringList pairs = ncUrl.path().split(':'); 40 | QString server, username, password; 41 | 42 | // Parse response url values 43 | for (QString pair : pairs) { 44 | if (pair.startsWith('&')) 45 | pair.mid(1); 46 | 47 | if (pair.startsWith(QStringLiteral("server"))) 48 | server = pair.mid(pair.indexOf(':')); 49 | else if (pair.startsWith(QStringLiteral("user"))) 50 | username = pair.mid(pair.indexOf(':')); 51 | else if (pair.startsWith(QStringLiteral("password"))) 52 | password = pair.mid(pair.indexOf(':')); 53 | } 54 | 55 | if (server.isEmpty() || username.isEmpty() || password.isEmpty()) { 56 | qWarning() << "Received response" << responseUrl << "not valid"; 57 | Q_EMIT authenticationFailed(); 58 | return; 59 | } 60 | 61 | qDebug() << "nc:" << server << username; 62 | if (this->settings()) { 63 | this->settings()->setUsername(username); 64 | this->settings()->setPassword(password); 65 | } 66 | Q_EMIT authenticationSuccessful(); 67 | } 68 | -------------------------------------------------------------------------------- /src/common/src/auth/flowloginauthenticator.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOWLOGINAUTHENTICATOR_H 2 | #define FLOWLOGINAUTHENTICATOR_H 3 | 4 | #include 5 | #include "authenticator.h" 6 | #include 7 | 8 | class FlowLoginAuthenticator : public Authenticator 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QString url READ url NOTIFY urlChanged) 13 | public: 14 | explicit FlowLoginAuthenticator(QObject *parent = Q_NULLPTR, 15 | AccountBase* commandQueue = Q_NULLPTR); 16 | 17 | QString url() { 18 | if (!this->settings()) 19 | return QStringLiteral(""); 20 | return this->settings()->hoststring() + NEXTCLOUD_ENDPOINT_LOGIN_FLOW; 21 | } 22 | 23 | protected: 24 | void updateClientSettings() Q_DECL_OVERRIDE {} 25 | 26 | public slots: 27 | void authenticate() Q_DECL_OVERRIDE; 28 | void abort() Q_DECL_OVERRIDE; 29 | void validateFlowResponse(QString responseUrl); 30 | 31 | signals: 32 | void urlChanged(); 33 | }; 34 | 35 | #endif // FLOWLOGINAUTHENTICATOR_H 36 | -------------------------------------------------------------------------------- /src/common/src/auth/qwebdavauthenticator.h: -------------------------------------------------------------------------------- 1 | #ifndef QWEBDAVAUTHENTICATOR_H 2 | #define QWEBDAVAUTHENTICATOR_H 3 | 4 | #include 5 | #include "authenticator.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class QWebDavAuthenticator : public Authenticator 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit QWebDavAuthenticator(QObject *parent = Q_NULLPTR, 17 | AccountBase* settings = Q_NULLPTR); 18 | 19 | public slots: 20 | void authenticate() Q_DECL_OVERRIDE; 21 | void abort() Q_DECL_OVERRIDE; 22 | 23 | protected: 24 | void updateClientSettings() Q_DECL_OVERRIDE; 25 | 26 | private: 27 | void sslErrorOccured(const QList &errors); 28 | void testConnectionFinished(QNetworkReply* reply); 29 | 30 | QWebdav* m_client = Q_NULLPTR; 31 | QWebdavDirParser m_dirParser; 32 | 33 | }; 34 | Q_DECLARE_METATYPE(QWebDavAuthenticator*) 35 | 36 | #endif // QWEBDAVAUTHENTICATOR_H 37 | -------------------------------------------------------------------------------- /src/common/src/cacheprovider.h: -------------------------------------------------------------------------------- 1 | #ifndef CACHEPROVIDER_H 2 | #define CACHEPROVIDER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class CacheProvider : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit CacheProvider(QObject *parent = Q_NULLPTR, 14 | AccountBase* account = Q_NULLPTR); 15 | 16 | bool cacheFileExists(const QString& identifier); 17 | bool isFileCurrent(const QString& identifier); 18 | QFile* getCacheFile(const QString& identifier, QFile::OpenMode mode); 19 | QString getPathForIdentifier(const QString& identifier); 20 | 21 | public slots: 22 | void clearCache(); 23 | void clearDownloads(); 24 | 25 | private: 26 | bool clearPath(const QString& path); 27 | 28 | QTimer m_clearTimer; 29 | QString m_cacheDir; 30 | QString m_downloadDir; 31 | 32 | signals: 33 | void cacheCleared(); 34 | }; 35 | 36 | #endif // CACHEPROVIDER_H 37 | -------------------------------------------------------------------------------- /src/common/src/commands/http/httpcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef HTTPCOMMANDENTITY_H 2 | #define HTTPCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class HttpCommandEntity : public CommandEntity 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit HttpCommandEntity(QObject *parent = Q_NULLPTR, 17 | QString path = QStringLiteral(""), 18 | QMap headers = QMap(), 19 | AccountBase* settings = Q_NULLPTR); 20 | ~HttpCommandEntity(); 21 | bool startWork(); 22 | bool abortWork(); 23 | 24 | protected: 25 | QUrl m_requestUrl; 26 | QNetworkReply* m_reply = Q_NULLPTR; 27 | QNetworkRequest m_request; 28 | QNetworkAccessManager m_accessManager; 29 | AccountBase* m_settings = Q_NULLPTR; 30 | 31 | private: 32 | QUrl setupRequestUrl(); 33 | 34 | QString m_path; 35 | QMap m_headers; 36 | 37 | signals: 38 | void sslErrorOccured(QString md5Digest, QString sha1Digest); 39 | 40 | }; 41 | 42 | #endif // HTTPCOMMANDENTITY_H 43 | -------------------------------------------------------------------------------- /src/common/src/commands/http/httpgetcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "httpgetcommandentity.h" 2 | 3 | #include 4 | 5 | HttpGetCommandEntity::HttpGetCommandEntity(QObject *parent, 6 | QString path, 7 | QMap headers, 8 | AccountBase* settings) : 9 | HttpCommandEntity(parent, path, headers, settings) { } 10 | 11 | bool HttpGetCommandEntity::startWork() 12 | { 13 | if (!HttpCommandEntity::startWork()) 14 | return false; 15 | 16 | qDebug() << "GET request:" << this->m_requestUrl.toString(); 17 | this->m_reply = this->m_accessManager.get(this->m_request); 18 | 19 | QObject::connect(this->m_reply, &QNetworkReply::finished, this, [=]() { 20 | if (!this->m_reply) { 21 | qWarning() << "Invalid reply, aborting."; 22 | abortWork(); 23 | return; 24 | } 25 | 26 | if (this->m_reply->error() != QNetworkReply::NoError) { 27 | qWarning() << "Error occured during HTTP get request:" << this->m_reply->errorString(); 28 | abortWork(); 29 | return; 30 | } 31 | 32 | const int httpStatusCode = 33 | this->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); 34 | 35 | if (httpStatusCode < 200 || httpStatusCode >= 400) { 36 | qWarning() << "Invalid HTTP status code" << httpStatusCode; 37 | abortWork(); 38 | return; 39 | } 40 | 41 | QVariantMap result; 42 | const QByteArray replyData = this->m_reply->readAll(); 43 | const QString mimeType = this->m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); 44 | const int contentLength = this->m_reply->header(QNetworkRequest::ContentLengthHeader).toInt(); 45 | result.insert("contentType", mimeType); 46 | result.insert("contentLength", contentLength); 47 | result.insert("content", replyData); 48 | result.insert("statusCode", httpStatusCode); 49 | this->m_resultData = result; 50 | 51 | Q_EMIT contentReady(); 52 | 53 | qInfo() << "Request finished, status code" << httpStatusCode; 54 | qDebug() << "Response length:" << contentLength; 55 | 56 | setState(FINISHED); 57 | Q_EMIT done(); 58 | }); 59 | 60 | setState(RUNNING); 61 | return true; 62 | } 63 | -------------------------------------------------------------------------------- /src/common/src/commands/http/httpgetcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef HTTPGETCOMMANDENTITY_H 2 | #define HTTPGETCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class HttpGetCommandEntity : public HttpCommandEntity 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit HttpGetCommandEntity(QObject* parent = Q_NULLPTR, 16 | QString path = QStringLiteral(""), 17 | QMap headers = QMap(), 18 | AccountBase* settings = Q_NULLPTR); 19 | 20 | bool startWork(); 21 | 22 | signals: 23 | void contentReady(); 24 | 25 | }; 26 | 27 | #endif // HTTPGETCOMMANDENTITY_H 28 | -------------------------------------------------------------------------------- /src/common/src/commands/nopcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "nopcommandentity.h" 2 | 3 | const CommandEntityInfo defaultNopInfo(const QString& type) 4 | { 5 | QMap properties; 6 | properties.insert("type", type); 7 | return CommandEntityInfo(properties); 8 | } 9 | 10 | NopCommandEntity::NopCommandEntity(QObject *parent, QString type) : 11 | StdFunctionCommandEntity(parent, [](){}, defaultNopInfo(type)) 12 | { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/common/src/commands/nopcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef NOPCOMMANDENTITY_H 2 | #define NOPCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | 7 | class NopCommandEntity : public StdFunctionCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit NopCommandEntity(QObject *parent = Q_NULLPTR, 12 | QString type = QStringLiteral("noop")); 13 | 14 | }; 15 | 16 | #endif // NOPCOMMANDENTITY_H 17 | -------------------------------------------------------------------------------- /src/common/src/commands/ocs/ocscommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "ocscommandentity.h" 2 | 3 | OcsCommandEntity::OcsCommandEntity(QObject *parent, 4 | QString path, 5 | QMap headers, 6 | AccountBase* settings) : 7 | HttpGetCommandEntity(parent, path, prepareOcsHeaders(settings, headers), settings) 8 | { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/common/src/commands/ocs/ocscommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSCOMMANDENTITY_H 2 | #define OCSCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class OcsCommandEntity : public HttpGetCommandEntity 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit OcsCommandEntity( 16 | QObject* parent = Q_NULLPTR, 17 | QString path = QStringLiteral(""), 18 | QMap headers = prepareOcsHeaders(), 19 | AccountBase* settings = Q_NULLPTR); 20 | 21 | }; 22 | 23 | #endif // OCSCOMMANDENTITY_H 24 | -------------------------------------------------------------------------------- /src/common/src/commands/ocs/ocssharelistcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "ocssharelistcommandentity.h" 2 | 3 | OcsShareListCommandEntity::OcsShareListCommandEntity(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/common/src/commands/ocs/ocssharelistcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSSHARELISTCOMMANDENTITY_H 2 | #define OCSSHARELISTCOMMANDENTITY_H 3 | 4 | #include 5 | 6 | class OcsShareListCommandEntity : public QObject 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit OcsShareListCommandEntity(QObject *parent = nullptr); 11 | 12 | signals: 13 | 14 | public slots: 15 | }; 16 | 17 | #endif // OCSSHARELISTCOMMANDENTITY_H 18 | -------------------------------------------------------------------------------- /src/common/src/commands/ocs/ocsuserinfocommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSUSERINFOCOMMANDENTITY_H 2 | #define OCSUSERINFOCOMMANDENTITY_H 3 | 4 | #include 5 | #include "ocscommandentity.h" 6 | 7 | class OcsUserInfoCommandEntity : public OcsCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit OcsUserInfoCommandEntity( 12 | QObject* parent = Q_NULLPTR, 13 | AccountBase* settings = Q_NULLPTR, 14 | QMap headers = prepareOcsHeaders()); 15 | 16 | bool startWork(); 17 | }; 18 | 19 | #endif // OCSUSERINFOCOMMANDENTITY_H 20 | -------------------------------------------------------------------------------- /src/common/src/commands/sync/ncsynccommandunit.h: -------------------------------------------------------------------------------- 1 | #ifndef NCSYNCCOMMANDUNIT_H 2 | #define NCSYNCCOMMANDUNIT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class NcSyncCommandUnit : public CommandUnit 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit NcSyncCommandUnit(QObject* parent = Q_NULLPTR, 16 | CloudStorageProvider* client = Q_NULLPTR, 17 | QString localPath = QStringLiteral(""), 18 | QString remotePath = QStringLiteral(""), 19 | QSharedPointer cachedTree = QSharedPointer(Q_NULLPTR)); 20 | 21 | QSharedPointer cachedTree(); 22 | 23 | protected: 24 | void expand(CommandEntity* previousCommandEntity); 25 | 26 | private: 27 | bool fileExistsRemotely(const QString& localFilePath, 28 | QStringList& missingDirectories); 29 | 30 | CloudStorageProvider* m_client = Q_NULLPTR; 31 | QString m_localPath; 32 | QString m_remotePath; 33 | QSharedPointer m_cachedTree; 34 | bool m_directoryCreation = false; 35 | 36 | }; 37 | 38 | #endif // NCSYNCCOMMANDUNIT_H 39 | -------------------------------------------------------------------------------- /src/common/src/commands/ubuntutouch/utfiledownloadcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef UTFILEDOWNLOADCOMMANDENTITY_H 2 | #define UTFILEDOWNLOADCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "commandentity.h" 8 | #include 9 | #include 10 | #include 11 | 12 | class UtFileDownloadCommandEntity : public CommandEntity 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit UtFileDownloadCommandEntity(QObject* parent = Q_NULLPTR, 18 | QString remotePath = QStringLiteral(""), 19 | QString localPath = QStringLiteral(""), 20 | AccountBase* settings = Q_NULLPTR); 21 | ~UtFileDownloadCommandEntity(); 22 | 23 | protected: 24 | bool startWork() Q_DECL_OVERRIDE; 25 | bool abortWork() Q_DECL_OVERRIDE; 26 | bool staticProgress() const Q_DECL_OVERRIDE { return false; } 27 | 28 | QString m_remotePath = QStringLiteral(""); 29 | QString m_localPath = QStringLiteral(""); 30 | QDir m_localDir; 31 | 32 | private Q_SLOTS: 33 | void handleProgress(qulonglong received, qulonglong total); 34 | void handleFinished(const QString& path); 35 | void handleError(Lomiri::DownloadManager::Error* error); 36 | 37 | private: 38 | Lomiri::DownloadManager::Manager* m_dlManager = Q_NULLPTR; 39 | Lomiri::DownloadManager::Download* m_download = Q_NULLPTR; 40 | AccountBase* m_settings = Q_NULLPTR; 41 | bool m_running = false; 42 | }; 43 | 44 | #endif // UTFILEDOWNLOADCOMMANDENTITY_H 45 | -------------------------------------------------------------------------------- /src/common/src/commands/ubuntutouch/utfileuploadcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "utfileuploadcommandentity.h" 2 | 3 | #ifdef Q_OS_IOS 4 | #include 5 | #endif 6 | 7 | UtFileUploadCommandEntity::FileUploadCommandEntity(QObject* parent, 8 | QString localPath, 9 | QString remotePath, 10 | AccountBase* client) : 11 | CommandEntity(parent), m_localPath(localPath), m_settings(settings), 12 | m_localFile(new QFile(localPath, this)) 13 | { 14 | const QString fileName = QFileInfo(*this->m_localFile).fileName(); 15 | 16 | this->m_remotePath = remotePath + fileName; 17 | 18 | // extensible list of command properties 19 | QMap info; 20 | info["type"] = QStringLiteral("davPut"); 21 | info["localPath"] = localPath; 22 | info["remotePath"] = remotePath; 23 | info["fileName"] = fileName; 24 | info["remoteFile"] = remotePath + fileName; 25 | this->m_commandInfo = CommandEntityInfo(info); 26 | } 27 | 28 | bool UtFileUploadCommandEntity::startWork() 29 | { 30 | if (!CommandEntity::startWork()) 31 | return false; 32 | 33 | if (!this->m_localFile->exists()) { 34 | qWarning() << "Local file" << this->m_localFile->fileName() << "does not exist, aborting."; 35 | abortWork(); 36 | return false; 37 | } 38 | 39 | const bool isOpen = this->m_localFile->open(QFile::ReadOnly); 40 | if (!isOpen) { 41 | qWarning() << "Failed to open" << this->m_localFile->fileName() << ", aborting."; 42 | abortWork(); 43 | return false; 44 | } 45 | 46 | if (!this->m_client) { 47 | qWarning() << "No valid client object available, aborting"; 48 | abortWork(); 49 | return false; 50 | } 51 | this->m_reply = this->m_client->put(this->m_remotePath, this->m_localFile); 52 | 53 | const bool canStart = WebDavCommandEntity::startWork(); 54 | if (!canStart) 55 | return false; 56 | 57 | setState(RUNNING); 58 | return true; 59 | } 60 | -------------------------------------------------------------------------------- /src/common/src/commands/ubuntutouch/utfileuploadcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef UTFILEUPLOADCOMMANDENTITY_H 2 | #define UTFILEUPLOADCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "commandentity.h" 8 | #include 9 | #include 10 | #include 11 | 12 | class UtFileUploadCommandEntity : public CommandEntity 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit UtFileUploadCommandEntity(QObject* parent = Q_NULLPTR, 18 | QString localPath = QStringLiteral(""), 19 | QString remotePath = QStringLiteral(""), 20 | AccountBase* settings = Q_NULLPTR); 21 | 22 | protected: 23 | bool startWork() Q_DECL_OVERRIDE; 24 | bool staticProgress() const Q_DECL_OVERRIDE { return false; } 25 | 26 | private: 27 | Lomiri::DownloadManager::Manager* m_dlManager = Q_NULLPTR; 28 | Lomiri::DownloadManager::Download* m_download = Q_NULLPTR; 29 | AccountBase* m_settings = Q_NULLPTR; 30 | bool m_running = false; 31 | QFile* m_localFile = Q_NULLPTR; 32 | QString m_remotePath; 33 | }; 34 | 35 | #endif // UTFILEUPLOADCOMMANDENTITY_H 36 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davcopycommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "davcopycommandentity.h" 2 | 3 | DavCopyCommandEntity::DavCopyCommandEntity(QObject* parent, 4 | QString fromPath, 5 | QString toPath, 6 | QWebdav* client) : 7 | WebDavCommandEntity(parent, client) 8 | { 9 | this->m_fromPath = fromPath; 10 | this->m_toPath = toPath; 11 | 12 | QMap info; 13 | info["type"] = QStringLiteral("davCopy"); 14 | info["fromPath"] = fromPath; 15 | info["toPath"] = toPath; 16 | this->m_commandInfo = CommandEntityInfo(info); 17 | } 18 | 19 | bool DavCopyCommandEntity::startWork() 20 | { 21 | if (!this->m_client) { 22 | qWarning() << "No valid client object available, aborting"; 23 | abortWork(); 24 | return false; 25 | } 26 | this->m_reply = this->m_client->copy(this->m_fromPath, this->m_toPath); 27 | 28 | QObject::connect(m_reply, &QNetworkReply::finished, this, [=]() { 29 | qInfo() << "Dav entity copying" << this->m_fromPath << "to" << this->m_toPath << "complete."; 30 | }); 31 | 32 | const bool canStart = WebDavCommandEntity::startWork(); 33 | if (!canStart) 34 | return false; 35 | 36 | setState(RUNNING); 37 | return true; 38 | } 39 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davcopycommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef DAVCOPYCOMMANDENTITY_H 2 | #define DAVCOPYCOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | 7 | class DavCopyCommandEntity : public WebDavCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit DavCopyCommandEntity(QObject* parent = Q_NULLPTR, 12 | QString fromPath = QStringLiteral(""), 13 | QString toPath = QStringLiteral(""), 14 | QWebdav* client = Q_NULLPTR); 15 | 16 | private: 17 | bool startWork(); 18 | 19 | QString m_fromPath = QStringLiteral(""); 20 | QString m_toPath = QStringLiteral(""); 21 | 22 | }; 23 | 24 | #endif // DAVCOPYCOMMANDENTITY_H 25 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davlistcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef DAVLISTCOMMANDENTITY_H 2 | #define DAVLISTCOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | 7 | #include 8 | 9 | class DavListCommandEntity : public WebDavCommandEntity 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit DavListCommandEntity(QObject* parent = Q_NULLPTR, 14 | QString remotePath = QStringLiteral(""), 15 | bool refresh = false, 16 | QWebdav* client = Q_NULLPTR); 17 | 18 | bool startWork(); 19 | 20 | private: 21 | QWebdavDirParser m_parser; 22 | QString m_remotePath; 23 | }; 24 | 25 | #endif // DAVLISTCOMMANDENTITY_H 26 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davmovecommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "davmovecommandentity.h" 2 | 3 | DavMoveCommandEntity::DavMoveCommandEntity(QObject* parent, 4 | QString fromPath, 5 | QString toPath, 6 | QWebdav* client) : 7 | WebDavCommandEntity(parent, client) 8 | { 9 | this->m_fromPath = fromPath; 10 | this->m_toPath = toPath; 11 | 12 | QMap info; 13 | info["type"] = QStringLiteral("davMove"); 14 | info["fromPath"] = fromPath; 15 | info["toPath"] = toPath; 16 | this->m_commandInfo = CommandEntityInfo(info); 17 | } 18 | 19 | bool DavMoveCommandEntity::startWork() 20 | { 21 | if (!this->m_client) { 22 | qWarning() << "No valid client object available, aborting"; 23 | abortWork(); 24 | return false; 25 | } 26 | 27 | this->m_reply = this->m_client->move(this->m_fromPath, this->m_toPath); 28 | 29 | QObject::connect(m_reply, &QNetworkReply::finished, this, [=]() { 30 | qInfo() << "Dav entity moving" << this->m_fromPath << "to" << this->m_toPath << "complete."; 31 | }); 32 | 33 | const bool canStart = WebDavCommandEntity::startWork(); 34 | if (!canStart) 35 | return false; 36 | 37 | setState(RUNNING); 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davmovecommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef DAVMOVECOMMANDENTITY_H 2 | #define DAVMOVECOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | 7 | class DavMoveCommandEntity : public WebDavCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit DavMoveCommandEntity(QObject* parent = Q_NULLPTR, 12 | QString fromPath = QStringLiteral(""), 13 | QString toPath = QStringLiteral(""), 14 | QWebdav* client = Q_NULLPTR); 15 | 16 | private: 17 | bool startWork(); 18 | 19 | QString m_fromPath = QStringLiteral(""); 20 | QString m_toPath = QStringLiteral(""); 21 | 22 | }; 23 | 24 | #endif // DAVMOVECOMMANDENTITY_H 25 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davproppatchcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "davproppatchcommandentity.h" 2 | 3 | DavPropPatchCommandEntity::DavPropPatchCommandEntity(QObject* parent, 4 | QString remotePath, 5 | QWebdav::PropValues properties, 6 | QWebdav* client) : 7 | WebDavCommandEntity(parent, client) 8 | { 9 | this->m_remotePath = remotePath; 10 | this->m_props = properties; 11 | 12 | QMap info; 13 | info["type"] = QStringLiteral("davPropPatch"); 14 | info["remotePath"] = remotePath; 15 | this->m_commandInfo = CommandEntityInfo(info); 16 | } 17 | 18 | bool DavPropPatchCommandEntity::startWork() 19 | { 20 | if (!this->m_client) { 21 | qWarning() << "No valid client object available, aborting"; 22 | abortWork(); 23 | return false; 24 | } 25 | 26 | this->m_reply = this->m_client->proppatch(this->m_remotePath, m_props); 27 | 28 | QObject::connect(m_reply, &QNetworkReply::finished, this, [=]() { 29 | qDebug() << "PropPatching " << this->m_remotePath << "complete."; 30 | }); 31 | 32 | const bool canStart = WebDavCommandEntity::startWork(); 33 | if (!canStart) 34 | return false; 35 | 36 | setState(RUNNING); 37 | return true; 38 | } 39 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davproppatchcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef DAVPROPPATCHCOMMANDENTITY_H 2 | #define DAVPROPPATCHCOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | 7 | class DavPropPatchCommandEntity : public WebDavCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit DavPropPatchCommandEntity(QObject* parent = Q_NULLPTR, 12 | QString remotePath = QStringLiteral(""), 13 | QWebdav::PropValues m_props = QWebdav::PropValues(), 14 | QWebdav* client = Q_NULLPTR); 15 | 16 | private: 17 | bool startWork(); 18 | 19 | QString m_remotePath; 20 | QWebdav::PropValues m_props; 21 | }; 22 | 23 | #endif // DAVPROPPATCHCOMMANDENTITY_H 24 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davrmcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "davrmcommandentity.h" 2 | 3 | DavRmCommandEntity::DavRmCommandEntity(QObject *parent, 4 | QString remotePath, 5 | QWebdav* client) : 6 | WebDavCommandEntity(parent, client) 7 | { 8 | this->m_remotePath = remotePath; 9 | 10 | QMap info; 11 | info["type"] = QStringLiteral("davRemove"); 12 | info["remotePath"] = remotePath; 13 | this->m_commandInfo = CommandEntityInfo(info); 14 | } 15 | 16 | bool DavRmCommandEntity::startWork() 17 | { 18 | if (!CommandEntity::startWork()) 19 | return false; 20 | 21 | if (!this->m_client) { 22 | qWarning() << "No valid client object available, aborting"; 23 | abortWork(); 24 | return false; 25 | } 26 | 27 | this->m_reply = this->m_client->remove(this->m_remotePath); 28 | 29 | QObject::connect(m_reply, &QNetworkReply::finished, this, [=]() { 30 | qInfo() << "Dav entity removal" << this->m_remotePath << "complete."; 31 | }); 32 | 33 | const bool canStart = WebDavCommandEntity::startWork(); 34 | if (!canStart) 35 | return false; 36 | 37 | setState(RUNNING); 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/davrmcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef DAVRMCOMMANDENTITY_H 2 | #define DAVRMCOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | 7 | class DavRmCommandEntity : public WebDavCommandEntity 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit DavRmCommandEntity(QObject* parent = Q_NULLPTR, 12 | QString remotePath = QStringLiteral(""), 13 | QWebdav* client = Q_NULLPTR); 14 | 15 | private: 16 | bool startWork(); 17 | 18 | QString m_remotePath = QStringLiteral(""); 19 | }; 20 | 21 | #endif // DAVRMCOMMANDENTITY_H 22 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/filedownloadcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEDOWNLOADCOMMANDENTITY_H 2 | #define FILEDOWNLOADCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "webdavcommandentity.h" 8 | #include 9 | 10 | class FileDownloadCommandEntity : public WebDavCommandEntity 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit FileDownloadCommandEntity(QObject* parent = Q_NULLPTR, 15 | QString remotePath = QStringLiteral(""), 16 | QString localPath = QStringLiteral(""), 17 | QWebdav* client = Q_NULLPTR); 18 | ~FileDownloadCommandEntity(); 19 | 20 | protected: 21 | bool startWork() Q_DECL_OVERRIDE; 22 | bool abortWork() Q_DECL_OVERRIDE; 23 | bool staticProgress() const Q_DECL_OVERRIDE { return false; } 24 | 25 | QString m_remotePath = QStringLiteral(""); 26 | QString m_localPath = QStringLiteral(""); 27 | QFile* m_localFile = Q_NULLPTR; 28 | QDir m_localDir; 29 | 30 | private: 31 | bool m_running = false; 32 | }; 33 | 34 | #endif // FILEDOWNLOADCOMMANDENTITY_H 35 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/fileuploadcommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "fileuploadcommandentity.h" 2 | 3 | #ifdef Q_OS_IOS 4 | #include 5 | #endif 6 | 7 | FileUploadCommandEntity::FileUploadCommandEntity(QObject* parent, 8 | QString localPath, 9 | QString remotePath, 10 | QWebdav* client) : 11 | WebDavCommandEntity(parent, client), 12 | m_localFile(new QFile(localPath, this)) 13 | { 14 | #ifdef Q_OS_IOS 15 | // On iOS we need to resolve the URL before use 16 | const QUrl localUrl(localPath); 17 | localPath = localUrl.toLocalFile(); 18 | 19 | const QUrlQuery fileNameQuery(localPath.mid(localPath.indexOf("id="))); 20 | qInfo() << "FILENAME on iOS:" << fileNameQuery.toString(QUrl::FullyEncoded); 21 | const QString fileId = fileNameQuery.queryItemValue("id"); 22 | const QString fileExtension = fileNameQuery.queryItemValue("ext"); 23 | const QString fileName = fileId + "." + fileExtension; 24 | #else 25 | const QString fileName = QFileInfo(*this->m_localFile).fileName(); 26 | #endif 27 | 28 | #ifdef Q_OS_MAC 29 | // On macOS we set the filename explicitly in the remotePath 30 | this->m_remotePath = remotePath; 31 | #else 32 | this->m_remotePath = remotePath + fileName; 33 | #endif 34 | 35 | // extensible list of command properties 36 | QMap info; 37 | info["type"] = QStringLiteral("davPut"); 38 | info["localPath"] = localPath; 39 | info["remotePath"] = remotePath; 40 | info["fileName"] = fileName; 41 | info["remoteFile"] = remotePath + fileName; 42 | this->m_commandInfo = CommandEntityInfo(info); 43 | } 44 | 45 | bool FileUploadCommandEntity::startWork() 46 | { 47 | if (!CommandEntity::startWork()) 48 | return false; 49 | 50 | if (!this->m_localFile->exists()) { 51 | qWarning() << "Local file" << this->m_localFile->fileName() << "does not exist, aborting."; 52 | abortWork(); 53 | return false; 54 | } 55 | 56 | const bool isOpen = this->m_localFile->open(QFile::ReadOnly); 57 | if (!isOpen) { 58 | qWarning() << "Failed to open" << this->m_localFile->fileName() << ", aborting."; 59 | abortWork(); 60 | return false; 61 | } 62 | 63 | if (!this->m_client) { 64 | qWarning() << "No valid client object available, aborting"; 65 | abortWork(); 66 | return false; 67 | } 68 | this->m_reply = this->m_client->put(this->m_remotePath, this->m_localFile); 69 | 70 | const bool canStart = WebDavCommandEntity::startWork(); 71 | if (!canStart) 72 | return false; 73 | 74 | setState(RUNNING); 75 | return true; 76 | } 77 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/fileuploadcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEUPLOADCOMMANDENTITY_H 2 | #define FILEUPLOADCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include "webdavcommandentity.h" 7 | #include 8 | 9 | class FileUploadCommandEntity : public WebDavCommandEntity 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit FileUploadCommandEntity(QObject* parent = Q_NULLPTR, 15 | QString localPath = QStringLiteral(""), 16 | QString remotePath = QStringLiteral(""), 17 | QWebdav* client = Q_NULLPTR); 18 | 19 | protected: 20 | bool startWork() Q_DECL_OVERRIDE; 21 | bool staticProgress() const Q_DECL_OVERRIDE { return false; } 22 | 23 | private: 24 | bool m_running = false; 25 | QFile* m_localFile = Q_NULLPTR; 26 | QString m_remotePath; 27 | }; 28 | 29 | #endif // FILEUPLOADCOMMANDENTITY_H 30 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/mkdavdircommandentity.cpp: -------------------------------------------------------------------------------- 1 | #include "mkdavdircommandentity.h" 2 | 3 | MkDavDirCommandEntity::MkDavDirCommandEntity(QObject* parent, 4 | QString remotePath, 5 | QWebdav* client) : 6 | WebDavCommandEntity(parent, client) 7 | { 8 | this->m_remotePath = remotePath; 9 | 10 | QMap info; 11 | info["type"] = QStringLiteral("davMkDir"); 12 | info["remotePath"] = remotePath; 13 | this->m_commandInfo = CommandEntityInfo(info); 14 | } 15 | 16 | bool MkDavDirCommandEntity::startWork() 17 | { 18 | if (!this->m_client) { 19 | qWarning() << "No valid client object available, aborting"; 20 | abortWork(); 21 | return false; 22 | } 23 | this->m_reply = this->m_client->mkdir(this->m_remotePath); 24 | 25 | QObject::connect(m_reply, 26 | #if QT_VERSION < 0x060000 27 | static_cast(&QNetworkReply::error), 28 | #else 29 | &QNetworkReply::errorOccurred, 30 | #endif 31 | this, 32 | [=](QNetworkReply::NetworkError error) { 33 | qInfo() << "Remote directory creation" << this->m_remotePath << "failed," 34 | << "error:" << error; 35 | }); 36 | 37 | QObject::connect(m_reply, &QNetworkReply::finished, this, [=]() { 38 | qInfo() << "Remote directory creation" << this->m_remotePath << "complete."; 39 | }); 40 | 41 | const bool canStart = WebDavCommandEntity::startWork(); 42 | if (!canStart) 43 | return false; 44 | 45 | setState(RUNNING); 46 | return true; 47 | } 48 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/mkdavdircommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef MKDAVDIRCOMMANDENTITY_H 2 | #define MKDAVDIRCOMMANDENTITY_H 3 | 4 | #include 5 | #include "webdavcommandentity.h" 6 | #include 7 | 8 | class MkDavDirCommandEntity : public WebDavCommandEntity 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit MkDavDirCommandEntity(QObject* parent = Q_NULLPTR, 13 | QString remotePath = QStringLiteral(""), 14 | QWebdav* client = Q_NULLPTR); 15 | 16 | private: 17 | bool startWork(); 18 | 19 | QString m_remotePath = QStringLiteral(""); 20 | }; 21 | 22 | #endif // MKDAVDIRCOMMANDENTITY_H 23 | -------------------------------------------------------------------------------- /src/common/src/commands/webdav/webdavcommandentity.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBDAVCOMMANDENTITY_H 2 | #define WEBDAVCOMMANDENTITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class WebDavCommandEntity : public CommandEntity 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit WebDavCommandEntity(QObject* parent = Q_NULLPTR, 14 | QWebdav* client = Q_NULLPTR); 15 | ~WebDavCommandEntity(); 16 | 17 | protected: 18 | bool startWork() Q_DECL_OVERRIDE; 19 | bool abortWork() Q_DECL_OVERRIDE; 20 | 21 | QWebdav* m_client = Q_NULLPTR; 22 | QNetworkReply* m_reply = Q_NULLPTR; 23 | 24 | signals: 25 | void sslErrorOccured(QString md5Digest, QString sha1Digest); 26 | 27 | }; 28 | 29 | #endif // WEBDAVCOMMANDENTITY_H 30 | -------------------------------------------------------------------------------- /src/common/src/net/abstractfetcher.cpp: -------------------------------------------------------------------------------- 1 | #include "abstractfetcher.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | AbstractFetcher::AbstractFetcher(QObject *parent) : QObject(parent) 9 | { 10 | } 11 | 12 | 13 | bool AbstractFetcher::fetching() 14 | { 15 | return this->m_fetching; 16 | } 17 | 18 | void AbstractFetcher::setFetching(bool v) 19 | { 20 | if (this->m_fetching == v) 21 | return; 22 | 23 | this->m_fetching = v; 24 | Q_EMIT fetchingChanged(); 25 | } 26 | 27 | QString AbstractFetcher::source() 28 | { 29 | return this->m_source; 30 | } 31 | 32 | void AbstractFetcher::setSource(const QString &v) 33 | { 34 | if (this->m_source == v) 35 | return; 36 | 37 | this->m_source = v; 38 | qDebug() << "new thumbnail source:" << this->m_source; 39 | Q_EMIT sourceChanged(); 40 | } 41 | 42 | CacheProvider* AbstractFetcher::cacheProvider() 43 | { 44 | return this->m_cacheProvider; 45 | } 46 | 47 | void AbstractFetcher::setCacheProvider(CacheProvider *v) 48 | { 49 | if (this->m_cacheProvider == v) 50 | return; 51 | 52 | this->m_cacheProvider = v; 53 | Q_EMIT cacheProviderChanged(); 54 | } 55 | 56 | CloudStorageProvider* AbstractFetcher::commandQueue() 57 | { 58 | return this->m_commandQueue; 59 | } 60 | 61 | void AbstractFetcher::setCommandQueue(CloudStorageProvider* v) 62 | { 63 | if (this->m_commandQueue == v) 64 | return; 65 | 66 | this->m_commandQueue = v; 67 | Q_EMIT commandQueueChanged(); 68 | } 69 | 70 | int AbstractFetcher::width() 71 | { 72 | return this->m_width; 73 | } 74 | 75 | void AbstractFetcher::setWidth(int v) 76 | { 77 | if (this->m_width == v) 78 | return; 79 | 80 | this->m_width = v; 81 | Q_EMIT widthChanged(); 82 | } 83 | 84 | int AbstractFetcher::height() 85 | { 86 | return this->m_height; 87 | } 88 | 89 | void AbstractFetcher::setHeight(int v) 90 | { 91 | if (this->m_height == v) 92 | return; 93 | 94 | this->m_height = v; 95 | Q_EMIT heightChanged(); 96 | } 97 | -------------------------------------------------------------------------------- /src/common/src/net/abstractfetcher.h: -------------------------------------------------------------------------------- 1 | #ifndef ABSTRACTFETCHER_H 2 | #define ABSTRACTFETCHER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class AbstractFetcher : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) 14 | Q_PROPERTY(CacheProvider* cacheProvider READ cacheProvider WRITE setCacheProvider NOTIFY cacheProviderChanged) 15 | Q_PROPERTY(CloudStorageProvider* commandQueue READ commandQueue WRITE setCommandQueue NOTIFY commandQueueChanged) 16 | Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) 17 | Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) 18 | Q_PROPERTY(bool fetching READ fetching NOTIFY fetchingChanged) 19 | 20 | public: 21 | explicit AbstractFetcher(QObject *parent = Q_NULLPTR); 22 | 23 | CacheProvider* cacheProvider(); 24 | void setCacheProvider(CacheProvider* v); 25 | CloudStorageProvider* commandQueue(); 26 | void setCommandQueue(CloudStorageProvider* v); 27 | 28 | public slots: 29 | virtual void fetch() = 0; 30 | 31 | protected: 32 | QString source(); 33 | void setSource(const QString& v); 34 | int width(); 35 | void setWidth(int v); 36 | int height(); 37 | void setHeight(int v); 38 | bool fetching(); 39 | void setFetching(bool v); 40 | 41 | private: 42 | QString m_source; 43 | int m_width = 0; 44 | int m_height = 0; 45 | bool m_fetching = false; 46 | CloudStorageProvider* m_commandQueue = Q_NULLPTR; 47 | CacheProvider* m_cacheProvider = Q_NULLPTR; 48 | 49 | signals: 50 | void sourceChanged(); 51 | void cacheProviderChanged(); 52 | void commandQueueChanged(); 53 | void widthChanged(); 54 | void heightChanged(); 55 | void fetchingChanged(); 56 | }; 57 | Q_DECLARE_METATYPE(AbstractFetcher*) 58 | 59 | #endif // ABSTRACTFETCHER_H 60 | -------------------------------------------------------------------------------- /src/common/src/net/avatarfetcher.h: -------------------------------------------------------------------------------- 1 | #ifndef AVATARFETCHER_H 2 | #define AVATARFETCHER_H 3 | 4 | #include 5 | #include "abstractfetcher.h" 6 | 7 | class AvatarFetcher : public AbstractFetcher 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit AvatarFetcher(QObject *parent = nullptr); 13 | 14 | public slots: 15 | void fetch() Q_DECL_OVERRIDE; 16 | 17 | }; 18 | 19 | #endif // AVATARFETCHER_H 20 | -------------------------------------------------------------------------------- /src/common/src/net/thumbnailfetcher.h: -------------------------------------------------------------------------------- 1 | #ifndef THUMBNAILFETCHER_H 2 | #define THUMBNAILFETCHER_H 3 | 4 | #include 5 | #include "abstractfetcher.h" 6 | #include 7 | #include 8 | #include 9 | 10 | class ThumbnailFetcher : public AbstractFetcher 11 | { 12 | Q_OBJECT 13 | 14 | Q_PROPERTY(QString remoteFile READ remoteFile WRITE setRemoteFile NOTIFY remoteFileChanged) 15 | 16 | public: 17 | explicit ThumbnailFetcher(QObject *parent = Q_NULLPTR); 18 | 19 | void setRemoteFile(QString v); 20 | QString remoteFile(); 21 | 22 | public slots: 23 | void fetch() Q_DECL_OVERRIDE; 24 | 25 | private: 26 | QString m_remoteFile; 27 | 28 | signals: 29 | void remoteFileChanged(); 30 | 31 | }; 32 | Q_DECLARE_METATYPE(ThumbnailFetcher*) 33 | 34 | #endif // THUMBNAILFETCHER_H 35 | -------------------------------------------------------------------------------- /src/common/src/nextcloudendpointconsts.h: -------------------------------------------------------------------------------- 1 | #ifndef NEXTCLOUDENDPOINTCONSTS_H 2 | #define NEXTCLOUDENDPOINTCONSTS_H 3 | 4 | #include 5 | #include 6 | 7 | const QString NEXTCLOUD_ENDPOINT_WEBDAV = QStringLiteral("remote.php/webdav"); 8 | const QString NEXTCLOUD_ENDPOINT_LOGIN_FLOW = QStringLiteral("index.php/login/flow"); 9 | const QString NEXTCLOUD_ENDPOINT_THUMBNAIL = QStringLiteral("index.php/apps/files/api/v1/thumbnail"); 10 | const QString NEXTCLOUD_ENDPOINT_AVATAR = QStringLiteral("index.php/avatar/%1/%2"); 11 | const QString NEXTCLOUD_ENDPOINT_OCS_USERINFO = QStringLiteral("ocs/v2.php/cloud/users/"); 12 | const QString NEXTCLOUD_ENDPOINT_OCS_SETTINGS = QStringLiteral("index.php/settings/user"); 13 | const QString NEXTCLOUD_ENDPOINT_OCS_SHARE = QStringLiteral("ocs/v2.php/apps/files_sharing/api/v1"); 14 | const QString NEXTCLOUD_ENDPOINT_OCS_SHARE_LIST = NEXTCLOUD_ENDPOINT_OCS_SHARE + QStringLiteral("/shares"); 15 | const QString NEXTCLOUD_ENDPOINT_OCS_SHARE_INFO = NEXTCLOUD_ENDPOINT_OCS_SHARE + QStringLiteral("/shares/%1"); 16 | const QString NEXTCLOUD_ENDPOINT_OCS_SHARE_NEW = NEXTCLOUD_ENDPOINT_OCS_SHARE + QStringLiteral("/shares"); 17 | const QString NEXTCLOUD_ENDPOINT_OCS_SHARE_DELETE = NEXTCLOUD_ENDPOINT_OCS_SHARE + QStringLiteral("/shares/%1"); 18 | 19 | #endif // NEXTCLOUDENDPOINTCONSTS_H 20 | -------------------------------------------------------------------------------- /src/common/src/ownclouddbusconsts.h: -------------------------------------------------------------------------------- 1 | #ifndef OWNCLOUDDBUSCONSTS_H 2 | #define OWNCLOUDDBUSCONSTS_H 3 | 4 | #define HARBOUR_OWNCLOUD_DAEMON_IFACE "com.github.beidl.HarbourOwncloud.Daemon.Uploader" 5 | #define HARBOUR_OWNCLOUD_PERMD_IFACE "com.github.beidl.HarbourOwncloud.Daemon.Permission" 6 | 7 | #include 8 | 9 | namespace HarbourOwncloud { 10 | namespace DBusConsts { 11 | // Photo backup daemon 12 | const QString DBUS_SERVICE = QStringLiteral(HARBOUR_OWNCLOUD_DAEMON_IFACE); 13 | const QString DBUS_PATH = QStringLiteral("/"); 14 | const QString DBUS_INTERFACE = QStringLiteral(HARBOUR_OWNCLOUD_DAEMON_IFACE); 15 | 16 | const QString DBUS_METHOD_RELOADCONFIG = QStringLiteral("reloadConfig"); 17 | const QString DBUS_METHOD_ABORT = QStringLiteral("abort"); 18 | const QString DBUS_SIGNAL_UPLOADINGCHANGED = QStringLiteral("uploadingChanged"); 19 | const QString DBUS_PROPERTY_UPLOADING = QStringLiteral("uploading"); 20 | 21 | // User-session-wide permission dialog 22 | namespace PermAgent { 23 | const QString DBUS_SERVICE = QStringLiteral(HARBOUR_OWNCLOUD_PERMD_IFACE); 24 | const QString DBUS_PATH = QStringLiteral("/"); 25 | const QString DBUS_INTERFACE = QStringLiteral(HARBOUR_OWNCLOUD_PERMD_IFACE); 26 | 27 | const QString DBUS_METHOD_REQUESTCONFIG = QStringLiteral("requestConfig"); 28 | } 29 | } 30 | } 31 | 32 | #endif // OWNCLOUDDBUSCONSTS_H 33 | -------------------------------------------------------------------------------- /src/common/src/provider/accountinfo/accountinfoprovider.cpp: -------------------------------------------------------------------------------- 1 | #include "accountinfoprovider.h" 2 | 3 | AccountInfoProvider::AccountInfoProvider(QObject *parent, 4 | AccountBase* settings) : 5 | SettingsBackedCommandQueue(parent, settings) 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/common/src/provider/accountinfo/accountinfoprovider.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCOUNTINFOPROVIDER_H 2 | #define ACCOUNTINFOPROVIDER_H 3 | 4 | #include 5 | #include 6 | 7 | class AccountInfoProvider : public SettingsBackedCommandQueue 8 | { 9 | Q_OBJECT 10 | 11 | Q_PROPERTY(QVariantMap userInfo READ userInfo NOTIFY userInfoChanged) 12 | public: 13 | explicit AccountInfoProvider(QObject *parent = Q_NULLPTR, 14 | AccountBase* settings = Q_NULLPTR); 15 | 16 | public slots: 17 | virtual CommandEntity* userInfoRequest() = 0; 18 | virtual QString providerSettingsUrl() = 0; 19 | 20 | signals: 21 | void userInfoChanged(); 22 | 23 | private: 24 | QVariantMap userInfo() { return m_userInfo; } 25 | QVariantMap m_userInfo; 26 | }; 27 | 28 | #endif // ACCOUNTINFOPROVIDER_H 29 | -------------------------------------------------------------------------------- /src/common/src/provider/accountinfo/ocscommandqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "ocscommandqueue.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | OcsCommandQueue::OcsCommandQueue(QObject *parent, AccountBase* settings) : 9 | AccountInfoProvider(parent, settings) 10 | { 11 | connect(this, &OcsCommandQueue::commandFinished, 12 | this, [=](CommandReceipt receipt) { 13 | qDebug() << "receipt.result: " << receipt.result; 14 | Q_EMIT userInfoChanged(); 15 | }); 16 | } 17 | 18 | CommandEntity* OcsCommandQueue::userInfoRequest() 19 | { 20 | if (!this->settings()) 21 | return Q_NULLPTR; 22 | 23 | if (this->settings()->providerType() != AccountBase::ProviderType::Nextcloud) { 24 | qDebug() << "User info requests are only supported on Nextcloud and ownCloud servers"; 25 | return Q_NULLPTR; 26 | } 27 | 28 | OcsUserInfoCommandEntity* command = new OcsUserInfoCommandEntity(this, 29 | this->settings()); 30 | enqueue(command); 31 | return command; 32 | } 33 | 34 | QString OcsCommandQueue::providerSettingsUrl() 35 | { 36 | if (!this->settings()) 37 | return QString(); 38 | 39 | if (this->settings()->providerType() != AccountBase::ProviderType::Nextcloud) { 40 | qDebug() << "Provider settings are only supported on Nextcloud and ownCloud servers"; 41 | return Q_NULLPTR; 42 | } 43 | 44 | // TODO: split implementation into NC and oC 45 | return this->settings()->hoststring() + "/" + NEXTCLOUD_ENDPOINT_OCS_SETTINGS; 46 | } 47 | -------------------------------------------------------------------------------- /src/common/src/provider/accountinfo/ocscommandqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSCOMMANDQUEUE_H 2 | #define OCSCOMMANDQUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class OcsCommandQueue : public AccountInfoProvider 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit OcsCommandQueue(QObject *parent = nullptr, 14 | AccountBase* settings = Q_NULLPTR); 15 | 16 | public slots: 17 | virtual CommandEntity* userInfoRequest() Q_DECL_OVERRIDE; 18 | virtual QString providerSettingsUrl() Q_DECL_OVERRIDE; 19 | 20 | }; 21 | 22 | #endif // OCSCOMMANDQUEUE_H 23 | -------------------------------------------------------------------------------- /src/common/src/provider/settingsbackedcommandqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "settingsbackedcommandqueue.h" 2 | 3 | SettingsBackedCommandQueue::SettingsBackedCommandQueue(QObject *parent, AccountBase* settings) : 4 | CommandQueue(parent) 5 | { 6 | setSettings(settings); 7 | } 8 | 9 | AccountBase* SettingsBackedCommandQueue::settings() 10 | { 11 | return this->m_settings; 12 | } 13 | 14 | void SettingsBackedCommandQueue::setSettings(AccountBase *v) 15 | { 16 | if (this->m_settings == v) 17 | return; 18 | 19 | // Disconnect from current settings object if it exists 20 | if (this->m_settings) 21 | QObject::disconnect(this->m_settings, 0, 0, 0); 22 | 23 | this->m_settings = v; 24 | Q_EMIT settingsChanged(); 25 | } 26 | -------------------------------------------------------------------------------- /src/common/src/provider/settingsbackedcommandqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSBACKEDCOMMANDQUEUE_H 2 | #define SETTINGSBACKEDCOMMANDQUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class SettingsBackedCommandQueue : public CommandQueue 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(AccountBase* settings READ settings WRITE setSettings NOTIFY settingsChanged) 13 | 14 | public: 15 | explicit SettingsBackedCommandQueue(QObject *parent = Q_NULLPTR, 16 | AccountBase* settings = Q_NULLPTR); 17 | 18 | AccountBase* settings(); 19 | void setSettings(AccountBase* v); 20 | 21 | private: 22 | AccountBase* m_settings = Q_NULLPTR; 23 | 24 | signals: 25 | void settingsChanged(); 26 | 27 | }; 28 | 29 | #endif // SETTINGSBACKEDCOMMANDQUEUE_H 30 | -------------------------------------------------------------------------------- /src/common/src/provider/sharing/ocssharingcommandqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "ocssharingcommandqueue.h" 2 | 3 | OcsSharingCommandQueue::OcsSharingCommandQueue(QObject *parent, 4 | AccountBase* settings) : 5 | SharingProvider(parent, settings) 6 | { 7 | 8 | } 9 | 10 | CommandEntity* OcsSharingCommandQueue::shareList() 11 | { 12 | return Q_NULLPTR; 13 | } 14 | -------------------------------------------------------------------------------- /src/common/src/provider/sharing/ocssharingcommandqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef OCSSHARINGCOMMANDQUEUE_H 2 | #define OCSSHARINGCOMMANDQUEUE_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | class OcsSharingCommandQueue : public SharingProvider 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit OcsSharingCommandQueue(QObject *parent = Q_NULLPTR, 14 | AccountBase* settings = Q_NULLPTR); 15 | 16 | virtual CommandEntity* shareList() Q_DECL_OVERRIDE; 17 | 18 | signals: 19 | 20 | public slots: 21 | }; 22 | 23 | #endif // OCSSHARINGCOMMANDQUEUE_H 24 | -------------------------------------------------------------------------------- /src/common/src/provider/sharing/sharingprovider.cpp: -------------------------------------------------------------------------------- 1 | #include "sharingprovider.h" 2 | 3 | SharingProvider::SharingProvider(QObject *parent, AccountBase* settings) : 4 | SettingsBackedCommandQueue(parent, settings) 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/common/src/provider/sharing/sharingprovider.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARINGPROVIDER_H 2 | #define SHARINGPROVIDER_H 3 | 4 | #include 5 | #include 6 | 7 | class SharingProvider : public SettingsBackedCommandQueue 8 | { 9 | Q_OBJECT 10 | 11 | Q_PROPERTY(QVariantList shares READ shares NOTIFY sharesChanged) 12 | 13 | public: 14 | explicit SharingProvider(QObject *parent = Q_NULLPTR, 15 | AccountBase* settings = Q_NULLPTR); 16 | 17 | virtual CommandEntity* shareList() = 0; 18 | QVariantList shares() { return this->m_shares; } 19 | 20 | private: 21 | QVariantList m_shares; 22 | 23 | signals: 24 | void sharesChanged(); 25 | }; 26 | 27 | #endif // SHARINGPROVIDER_H 28 | -------------------------------------------------------------------------------- /src/common/src/provider/storage/cloudstorageprovider.cpp: -------------------------------------------------------------------------------- 1 | #include "cloudstorageprovider.h" 2 | 3 | CloudStorageProvider::CloudStorageProvider(QObject *parent, AccountBase* settings) : 4 | SettingsBackedCommandQueue(parent, settings) 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/common/src/settings/db/accountdb.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCOUNTDB_H 2 | #define ACCOUNTDB_H 3 | 4 | #include 5 | #include 6 | #include "accountsdbinterface.h" 7 | 8 | class AccountDb : public AccountsDbInterface 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QVariantList accounts READ accountVariantList NOTIFY accountsChangedInherited) 13 | 14 | signals: 15 | // NOTIFY signal has to be defined in the same class as the property 16 | // see https://bugreports.qt.io/browse/QTBUG-7684 17 | void accountsChangedInherited(); 18 | 19 | public: 20 | explicit AccountDb(QObject *parent = Q_NULLPTR); 21 | ~AccountDb(); 22 | 23 | Q_INVOKABLE void refresh() override; 24 | 25 | public slots: 26 | QVector accounts() override; 27 | QVariantList accountVariantList() override; 28 | bool accountExists(const AccountBase* account) override; 29 | bool addAccount(AccountBase* account) override; 30 | bool updateAccount(AccountBase* account) override; 31 | bool removeAccount(AccountBase* account) override; 32 | 33 | private: 34 | void createDatabase(); 35 | void upgradeDatabase(); 36 | int currentDatabaseVersion(); 37 | void cleanup(); 38 | bool insertAccountIntoDatabase(AccountBase* account); 39 | 40 | QSqlDatabase m_database; 41 | QVector m_accounts; 42 | }; 43 | 44 | #endif // ACCOUNTDB_H 45 | -------------------------------------------------------------------------------- /src/common/src/settings/db/accountsdbinterface.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCOUNTSDBINTERFACE_H 2 | #define ACCOUNTSDBINTERFACE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class AccountsDbInterface : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit AccountsDbInterface(QObject* parent = nullptr) : 15 | QObject(parent) {} 16 | 17 | virtual Q_INVOKABLE void refresh() {} 18 | 19 | public slots: 20 | virtual QVector accounts() { 21 | return QVector(); 22 | } 23 | 24 | virtual QVariantList accountVariantList() { 25 | return QVariantList(); 26 | } 27 | 28 | virtual bool accountExists(const AccountBase* account) { 29 | Q_UNUSED(account); 30 | return false; 31 | } 32 | 33 | virtual bool addAccount(AccountBase* account) { 34 | Q_UNUSED(account); 35 | return false; 36 | } 37 | 38 | virtual bool updateAccount(AccountBase* account) { 39 | Q_UNUSED(account); 40 | return false; 41 | } 42 | 43 | virtual bool removeAccount(AccountBase* account) { 44 | Q_UNUSED(account); 45 | return false; 46 | } 47 | 48 | signals: 49 | void accountsChanged(); 50 | }; 51 | 52 | #endif // ACCOUNTSDBINTERFACE_H 53 | -------------------------------------------------------------------------------- /src/common/src/settings/db/syncdb.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNCDB_H 2 | #define SYNCDB_H 3 | 4 | #include 5 | #include 6 | 7 | class SyncDb : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit SyncDb(QObject *parent = Q_NULLPTR, 12 | QString userName = QStringLiteral("")); 13 | ~SyncDb(); 14 | 15 | private: 16 | void createDatabase(); 17 | 18 | private: 19 | QSqlDatabase m_database; 20 | 21 | }; 22 | 23 | #endif // SYNCDB_H 24 | -------------------------------------------------------------------------------- /src/common/src/settings/db/utaccountsdb.h: -------------------------------------------------------------------------------- 1 | #ifndef UTACCOUNTSDB_H 2 | #define UTACCOUNTSDB_H 3 | 4 | #include 5 | #include "accountsdbinterface.h" 6 | #include "accountdb.h" 7 | #include 8 | 9 | class UtAccountsDb : public AccountsDbInterface 10 | { 11 | Q_OBJECT 12 | 13 | Q_PROPERTY(QVariantList accounts READ accountVariantList NOTIFY accountsChanged) 14 | 15 | public: 16 | explicit UtAccountsDb(QObject *parent = nullptr); 17 | ~UtAccountsDb(); 18 | Q_INVOKABLE void refresh() override; 19 | 20 | public slots: 21 | QVector accounts() override; 22 | QVariantList accountVariantList() override; 23 | bool accountExists(const AccountBase* account) override; 24 | bool addAccount(AccountBase* account) override; 25 | bool updateAccount(AccountBase* account) override; 26 | bool removeAccount(AccountBase* account) override; 27 | 28 | private: 29 | void refreshAccountType(const QString& desiredServiceId, QVector& accounts); 30 | 31 | OnlineAccounts::Manager* m_manager = nullptr; 32 | QVector m_accounts; 33 | AccountDb* m_webdavDb; 34 | }; 35 | 36 | #endif // UTACCOUNTSDB_H 37 | -------------------------------------------------------------------------------- /src/common/src/settings/inifilesettings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "nextcloudsettingsbase.h" 8 | 9 | class IniFileSettings : public AccountBase 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | static IniFileSettings *instance(); 15 | IniFileSettings(QObject *parent = 0); 16 | 17 | public slots: 18 | bool readSettings(); 19 | QString filePath(); 20 | 21 | private: 22 | QSettings m_settings; 23 | }; 24 | Q_DECLARE_METATYPE(IniFileSettings*) 25 | 26 | #endif // SETTINGS_H 27 | -------------------------------------------------------------------------------- /src/common/src/settings/permittedsettings.cpp: -------------------------------------------------------------------------------- 1 | #include "permittedsettings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | PermittedSettings::PermittedSettings(QObject *parent) : 10 | AccountBase(parent) 11 | { 12 | } 13 | 14 | bool PermittedSettings::readSettings() 15 | { 16 | QDBusInterface permissiondIface(HarbourOwncloud::DBusConsts::PermAgent::DBUS_SERVICE, 17 | HarbourOwncloud::DBusConsts::PermAgent::DBUS_PATH, 18 | HarbourOwncloud::DBusConsts::PermAgent::DBUS_INTERFACE, 19 | QDBusConnection::sessionBus()); 20 | 21 | QDBusPendingCall pcall = permissiondIface.asyncCall(HarbourOwncloud::DBusConsts::PermAgent::DBUS_METHOD_REQUESTCONFIG); 22 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); 23 | connect(watcher, &QDBusPendingCallWatcher::finished, [=](QDBusPendingCallWatcher* wtchr) { 24 | QDBusPendingReply > reply = *wtchr; 25 | 26 | if (!reply.isError()) { 27 | QMap values = reply.value(); 28 | const bool isDenied = values.value(NEXTCLOUD_PERMD_REQUESTDENIED).toBool(); 29 | 30 | if (!isDenied) { 31 | const QString md5Hex = values.value(NEXTCLOUD_SETTINGS_KEY_CERTMD5).toString(); 32 | setMd5Hex(md5Hex); 33 | 34 | const QString sha1Hex = values.value(NEXTCLOUD_SETTINGS_KEY_CERTSHA1).toString(); 35 | setSha1Hex(sha1Hex); 36 | 37 | const bool isHttps = values.value(NEXTCLOUD_SETTINGS_KEY_ISHTTPS).toBool(); 38 | setIsHttps(isHttps); 39 | 40 | const QString hostname = values.value(NEXTCLOUD_SETTINGS_KEY_HOSTNAME).toString(); 41 | setHostname(hostname); 42 | 43 | const int port = values.value(NEXTCLOUD_SETTINGS_KEY_PORT).toInt(); 44 | setPort(port); 45 | 46 | const QString path = values.value(NEXTCLOUD_SETTINGS_KEY_PATH).toString(); 47 | setPath(path); 48 | 49 | const QString username = values.value(NEXTCLOUD_SETTINGS_KEY_USERNAME).toString(); 50 | setUsername(username); 51 | 52 | const QString password = values.value(NEXTCLOUD_SETTINGS_KEY_PASSWORD).toString(); 53 | setPassword(password); 54 | 55 | const int providerType = values.value(NEXTCLOUD_SETTINGS_KEY_PROVIDERTYPE).toInt(); 56 | setProviderType(providerType); 57 | 58 | refreshHostString(); 59 | } 60 | 61 | // Since settings are read, propagate changes to the SettingsBasedCommandQueue object 62 | emit settingsChanged(); 63 | } else { 64 | qWarning() << QDBusError::errorString(reply.error().type()); 65 | } 66 | 67 | wtchr->deleteLater(); 68 | }); 69 | 70 | return true; 71 | } 72 | -------------------------------------------------------------------------------- /src/common/src/settings/permittedsettings.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMITTEDSETTINGS_H 2 | #define PERMITTEDSETTINGS_H 3 | 4 | #include 5 | 6 | #include "nextcloudsettingsbase.h" 7 | 8 | class PermittedSettings : public AccountBase 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | PermittedSettings(QObject *parent = 0); 14 | 15 | public slots: 16 | bool readSettings(); 17 | 18 | }; 19 | Q_DECLARE_METATYPE(PermittedSettings*) 20 | 21 | #endif // PERMITTEDSETTINGS_H 22 | -------------------------------------------------------------------------------- /src/common/src/sharedstatecontroller.cpp: -------------------------------------------------------------------------------- 1 | #include "sharedstatecontroller.h" 2 | 3 | #include 4 | 5 | SharedStateController::SharedStateController(QObject *parent) : 6 | QObject(parent) 7 | { 8 | } 9 | 10 | bool SharedStateController::requestDirectoryListing(AccountBase* account, QString subPath) 11 | { 12 | if (!this->generator()) { 13 | qWarning() << Q_FUNC_INFO << "Generator is null"; 14 | return false; 15 | } 16 | 17 | std::function operation = [this, account, subPath](){ 18 | for (AccountWorkers* workers : this->generator()->accountWorkersVector()) { 19 | if (workers->account() != account) 20 | continue; 21 | 22 | CommandEntity* listingRequest = workers->browserCommandQueue()->directoryListingRequest(subPath, false, false); 23 | /*NcDirTreeCommandUnit* dirTreeRequest = new NcDirTreeCommandUnit(nullptr, 24 | workers->browserCommandQueue(), 25 | NODE_PATH_SEPARATOR, 26 | this->m_cachedTree, 27 | 1);*/ 28 | workers->browserCommandQueue()->enqueue(listingRequest); 29 | workers->browserCommandQueue()->run(); 30 | break; 31 | } 32 | }; 33 | 34 | if (this->thread() != QThread::currentThread()) { 35 | QMetaObject::invokeMethod(qApp, operation); 36 | return true; 37 | } 38 | 39 | operation(); 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /src/common/src/sharedstatecontroller.h: -------------------------------------------------------------------------------- 1 | #ifndef SHAREDSTATECONTROLLER_H 2 | #define SHAREDSTATECONTROLLER_H 3 | 4 | #include 5 | #include "settings/nextcloudsettingsbase.h" 6 | #include "accountworkergenerator.h" 7 | #include "commands/sync/ncdirtreecommandunit.h" 8 | 9 | class SharedStateController : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit SharedStateController(QObject *parent = nullptr); 14 | bool requestDirectoryListing(AccountBase* account, 15 | QString subPath); 16 | virtual AccountWorkerGenerator* generator() = 0; 17 | 18 | private: 19 | QSharedPointer m_cachedTree; 20 | }; 21 | 22 | #endif // SHAREDSTATECONTROLLER_H 23 | -------------------------------------------------------------------------------- /src/common/src/util/commandutil.cpp: -------------------------------------------------------------------------------- 1 | #include "commandutil.h" 2 | 3 | CommandUtil::CommandUtil(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/common/src/util/commandutil.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMANDUTIL_H 2 | #define COMMANDUTIL_H 3 | 4 | #include 5 | 6 | class CommandUtil : public QObject 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit CommandUtil(QObject *parent = Q_NULLPTR); 11 | 12 | signals: 13 | 14 | public slots: 15 | }; 16 | 17 | #endif // COMMANDUTIL_H 18 | -------------------------------------------------------------------------------- /src/common/src/util/filepathutil.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEPATHUTIL_H 2 | #define FILEPATHUTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class FilePathUtil : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | FilePathUtil(QObject* parent = Q_NULLPTR) : QObject(parent) {} 15 | Q_INVOKABLE static QString destinationFromMIME(const QString& mime); 16 | Q_INVOKABLE static QString destination(AccountBase* account); 17 | Q_INVOKABLE static QString getCanonicalPath(const QString &path); 18 | Q_INVOKABLE static QString getWebDavFileUrl(const QString &path, 19 | AccountBase* settings); 20 | Q_INVOKABLE static bool fileExists(const QString& filePath); 21 | Q_INVOKABLE static bool removeFile(const QString& filePath); 22 | Q_INVOKABLE static QDateTime getLastModified(const QString& filePath); 23 | }; 24 | 25 | #endif // FILEPATHUTIL_H 26 | -------------------------------------------------------------------------------- /src/common/src/util/providerutils.cpp: -------------------------------------------------------------------------------- 1 | #include "providerutils.h" 2 | #include 3 | 4 | // Implementations 5 | #include 6 | #include 7 | #include 8 | 9 | CloudStorageProvider* ProviderUtils::newStorageProviderByType(QObject* parent, AccountBase *settings) 10 | { 11 | CloudStorageProvider* provider = Q_NULLPTR; 12 | 13 | if (!settings) { 14 | qWarning() << "No valid settings object provided"; 15 | return provider; 16 | } 17 | 18 | switch (settings->providerType()) { 19 | case AccountBase::Nextcloud: 20 | case AccountBase::WebDav: 21 | provider = new WebDavCommandQueue(parent, settings); 22 | break; 23 | default: 24 | qWarning() << "Unsupported providerType" << settings->providerType(); 25 | break; 26 | } 27 | 28 | return provider; 29 | } 30 | 31 | AccountInfoProvider* ProviderUtils::newAccountInfoProviderByType(QObject* parent, AccountBase* settings) 32 | { 33 | AccountInfoProvider* provider = Q_NULLPTR; 34 | 35 | if (!settings) { 36 | qWarning() << "No valid settings object provided"; 37 | return provider; 38 | } 39 | 40 | switch (settings->providerType()) { 41 | case AccountBase::Nextcloud: 42 | provider = new OcsCommandQueue(parent, settings); 43 | break; 44 | default: 45 | qWarning() << "No AccountInfoProvider available for providerType" << settings->providerType(); 46 | break; 47 | } 48 | 49 | return provider; 50 | } 51 | 52 | SharingProvider* ProviderUtils::newSharingProviderByType(QObject* parent, AccountBase* settings) 53 | { 54 | SharingProvider* provider = Q_NULLPTR; 55 | 56 | if (!settings) { 57 | qWarning() << "No valid settings object provided"; 58 | return provider; 59 | } 60 | 61 | switch (settings->providerType()) { 62 | case AccountBase::Nextcloud: 63 | provider = new OcsSharingCommandQueue(parent, settings); 64 | break; 65 | default: 66 | qWarning() << "No AccountInfoProvider available for providerType" << settings->providerType(); 67 | break; 68 | } 69 | 70 | return provider; 71 | } 72 | -------------------------------------------------------------------------------- /src/common/src/util/providerutils.h: -------------------------------------------------------------------------------- 1 | #ifndef PROVIDERUTILS_H 2 | #define PROVIDERUTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class ProviderUtils 9 | { 10 | public: 11 | static CloudStorageProvider* newStorageProviderByType(QObject* parent, AccountBase* settings); 12 | static AccountInfoProvider* newAccountInfoProviderByType(QObject* parent, AccountBase* settings); 13 | static SharingProvider* newSharingProviderByType(QObject* parent, AccountBase* settings); 14 | }; 15 | 16 | #endif // PROVIDERUTILS_H 17 | -------------------------------------------------------------------------------- /src/common/src/util/qappprepareutil.h: -------------------------------------------------------------------------------- 1 | #ifndef QAPPPREPAREUTIL_H 2 | #define QAPPPREPAREUTIL_H 3 | 4 | #include 5 | 6 | inline void prepareAppProperties(QCoreApplication& app) 7 | { 8 | #if !defined(GHOSTCLOUD_UI_QUICKCONTROLS) 9 | const QString QHOSTCLOUD_APP_NAME = QStringLiteral("harbour-owncloud"); 10 | #else 11 | const QString QHOSTCLOUD_APP_NAME = QStringLiteral("GhostCloud"); 12 | #endif 13 | 14 | #if defined(GHOSTCLOUD_UBUNTU_TOUCH) 15 | app.setApplicationName(QStringLiteral("me.fredl.ghostcloud")); 16 | #elif defined(GHOSTCLOUD_UBUNTU_TOUCH_PHOTOBACKUP) 17 | app.setApplicationName(QStringLiteral("me.fredl.ghostcloudphotobackup")); 18 | #else 19 | app.setOrganizationName(QHOSTCLOUD_APP_NAME); 20 | app.setOrganizationDomain(QHOSTCLOUD_APP_NAME); 21 | app.setApplicationName(QHOSTCLOUD_APP_NAME); 22 | #endif 23 | } 24 | 25 | #endif // QAPPPREPAREUTIL_H 26 | -------------------------------------------------------------------------------- /src/common/src/util/shellcommand.cpp: -------------------------------------------------------------------------------- 1 | #include "shellcommand.h" 2 | 3 | #include 4 | 5 | void ShellCommand::runCommand(QString command, QStringList args) 6 | { 7 | #ifndef QT_NO_PROCESS 8 | QProcess *proc = new QProcess(); 9 | proc->setReadChannel(QProcess::StandardOutput); 10 | connect(proc, static_cast(&QProcess::finished), proc, &QProcess::deleteLater, Qt::DirectConnection); 11 | proc->start(command, args); 12 | #else 13 | qWarning() << "QProcess not supported on the target platform"; 14 | #endif 15 | } 16 | -------------------------------------------------------------------------------- /src/common/src/util/shellcommand.h: -------------------------------------------------------------------------------- 1 | #ifndef SHELLCOMMAND_H 2 | #define SHELLCOMMAND_H 3 | 4 | #include 5 | #include 6 | 7 | class ShellCommand : public QObject 8 | { 9 | public: 10 | static void runCommand(QString command, QStringList args); 11 | }; 12 | 13 | #endif // SHELLCOMMAND_H 14 | -------------------------------------------------------------------------------- /src/common/src/util/webdav_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBDAV_UTILS_H 2 | #define WEBDAV_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | QWebdav* getNewWebDav(AccountBase *settings, 12 | QObject* parent = Q_NULLPTR); 13 | 14 | void applySettingsToWebdav(AccountBase *settings, 15 | QWebdav *webdav); 16 | 17 | QMap prepareOcsHeaders( 18 | AccountBase* settings = Q_NULLPTR, 19 | QMap headers = QMap()); 20 | 21 | QNetworkRequest getOcsRequest(const QNetworkRequest& request, 22 | AccountBase* settings); 23 | 24 | QByteArray hexToDigest(const QString &input); 25 | 26 | #endif // WEBDAV_UTILS_H 27 | 28 | -------------------------------------------------------------------------------- /src/daemon/daemon.pro: -------------------------------------------------------------------------------- 1 | TARGET = harbour-owncloud-daemon 2 | 3 | CONFIG += qt c++11 ghostcloud_link 4 | QT = dbus network xml 5 | 6 | include($$PWD/../common/common.pri) 7 | 8 | contains(CONFIG, clickphotobackup) { 9 | DEFINES += GHOSTCLOUD_UBUNTU_TOUCH_PHOTOBACKUP 10 | } 11 | 12 | SOURCES += \ 13 | $$PWD/main.cpp \ 14 | $$PWD/filesystem.cpp \ 15 | $$PWD/networkmonitor.cpp \ 16 | $$PWD/dbushandler.cpp \ 17 | $$PWD/uploader.cpp 18 | 19 | HEADERS += \ 20 | $$PWD/filesystem.h \ 21 | $$PWD/networkmonitor.h \ 22 | $$PWD/dbushandler.h \ 23 | $$PWD/uploader.h 24 | 25 | OTHER_FILES += harbour-owncloud-daemon.service 26 | 27 | service.path = /usr/lib/systemd/user/ 28 | service.files += harbour-owncloud-daemon.service 29 | target.path = /usr/bin/ 30 | 31 | INSTALLS += target service 32 | -------------------------------------------------------------------------------- /src/daemon/dbushandler.cpp: -------------------------------------------------------------------------------- 1 | #include "dbushandler.h" 2 | #include 3 | 4 | DBusHandler::DBusHandler(QObject *parent) : QObject(parent), 5 | m_online(false), 6 | m_uploading(false) 7 | { 8 | } 9 | 10 | DBusHandler::~DBusHandler() 11 | { 12 | 13 | } 14 | 15 | void DBusHandler::setOnline(bool online) 16 | { 17 | qDebug() << Q_FUNC_INFO << "setting online" << online; 18 | if (online == m_online) return; 19 | m_online = online; 20 | emit onlineChanged(online); 21 | } 22 | 23 | void DBusHandler::setUploading(bool uploading) 24 | { 25 | qDebug() << Q_FUNC_INFO << "setting uploading" << uploading; 26 | if (uploading == m_uploading) return; 27 | m_uploading = uploading; 28 | emit uploadingChanged(uploading); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/daemon/dbushandler.h: -------------------------------------------------------------------------------- 1 | #ifndef DBUSHANDLER_H 2 | #define DBUSHANDLER_H 3 | 4 | #include 5 | #include 6 | 7 | class DBusHandler : public QObject 8 | { 9 | Q_OBJECT 10 | Q_CLASSINFO("D-Bus Interface", HARBOUR_OWNCLOUD_DAEMON_IFACE) 11 | Q_PROPERTY(bool online READ online NOTIFY onlineChanged) 12 | Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) 13 | 14 | public: 15 | explicit DBusHandler(QObject *parent = nullptr); 16 | ~DBusHandler(); 17 | 18 | public slots: 19 | void setOnline(bool online); 20 | bool online() { return m_online; } 21 | 22 | void setUploading(bool uploading); 23 | bool uploading() { return m_uploading; } 24 | 25 | void reloadConfig() { emit configReloadRequested(); } 26 | void abort() { emit abortRequested(); } 27 | 28 | signals: 29 | void fileUploaded(QString filePath); 30 | void onlineChanged(bool online); 31 | void uploadingChanged(bool uploading); 32 | void uploadError(QString errorMessage); 33 | void connectError(QString errorMessage); 34 | void configReloadRequested(); 35 | void abortRequested(); 36 | 37 | private: 38 | bool m_online; 39 | bool m_uploading; 40 | }; 41 | 42 | #endif // DBUSHANDLER_H 43 | -------------------------------------------------------------------------------- /src/daemon/filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef FILESYSTEM_H 2 | #define FILESYSTEM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Filesystem : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | struct WatchDelay { 17 | QString path; 18 | QTimer *timer = Q_NULLPTR; 19 | }; 20 | 21 | struct WatchedLocation { 22 | QString localDir; 23 | QString name; 24 | }; 25 | 26 | public: 27 | Filesystem(AccountBase* account = Q_NULLPTR); 28 | 29 | signals: 30 | void fileFound(QString locationDir, QString locationName, QString fullPath); 31 | void locationFound(QString locationDir, QString locationName); 32 | 33 | public slots: 34 | void inhibitScan(bool inhibit); 35 | void triggerRescan(); 36 | 37 | private slots: 38 | void scan(WatchedLocation location, QString dirPath, bool recursive = false); 39 | void prepareScan(QString dirPath); 40 | 41 | private: 42 | void rescan(); 43 | 44 | AccountBase* m_account; 45 | QFileSystemWatcher m_watcher; 46 | QMap m_watcherLocations; 47 | QSet m_existingFiles; 48 | bool m_inhibit = false; 49 | 50 | /* Camera creates temporary files before writing out content. 51 | * This condition can be triggered by having ~/Pictures be a 52 | * symlink to the SD card, as the SD card write speed is slower. 53 | * Delay scan of respective paths with a timer. This also improves 54 | * situations where a user shoots multiple pics repeatedly.*/ 55 | QList m_delayers; 56 | QMutex m_delayLock; 57 | 58 | bool isDelayActive(QString path); 59 | void resetDelay(QString path); 60 | void insertDelay(QString path); 61 | void clearDelays(); 62 | }; 63 | 64 | #endif//FILESYSTEM_H 65 | -------------------------------------------------------------------------------- /src/daemon/harbour-owncloud-daemon.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ownCloud photo backup 3 | After=lipstick.service 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/usr/bin/harbour-owncloud-daemon 8 | Restart=on-failure 9 | 10 | [Install] 11 | WantedBy=lipstick.service 12 | -------------------------------------------------------------------------------- /src/daemon/networkmonitor.cpp: -------------------------------------------------------------------------------- 1 | #include "networkmonitor.h" 2 | 3 | #include 4 | 5 | NetworkMonitor::NetworkMonitor(QObject *parent, 6 | AccountBase* settings) : 7 | QObject(parent), m_settings(settings) 8 | { 9 | this->m_shouldSync = false; 10 | connect(&this->m_configManager, &QNetworkConfigurationManager::configurationAdded, 11 | this, &NetworkMonitor::recheckNetworks); 12 | connect(&this->m_configManager, &QNetworkConfigurationManager::configurationChanged, 13 | this, &NetworkMonitor::recheckNetworks); 14 | connect(&this->m_configManager, &QNetworkConfigurationManager::configurationRemoved, 15 | this, &NetworkMonitor::recheckNetworks); 16 | connect(&this->m_configManager, &QNetworkConfigurationManager::onlineStateChanged, 17 | this, &NetworkMonitor::recheckNetworks); 18 | } 19 | 20 | NetworkMonitor::~NetworkMonitor() 21 | { 22 | 23 | } 24 | 25 | void NetworkMonitor::recheckNetworks() 26 | { 27 | QMutexLocker locker(&checkerMutex); 28 | 29 | if (this->m_settings) { 30 | const bool uploadOverCellular = this->m_settings->mobileUpload(); 31 | const bool uploadAutomatically = this->m_settings->uploadAutomatically(); 32 | 33 | if (!uploadAutomatically) { 34 | setShouldDownload(false); 35 | return; 36 | } 37 | 38 | // Don't explicitly check for bearer types in case cellular 39 | // upload is enabled, fall through otherwise 40 | if (uploadOverCellular) { 41 | setShouldDownload(true); 42 | return; 43 | } 44 | } 45 | 46 | if (!m_configManager.isOnline()) { 47 | setShouldDownload(false); 48 | return; 49 | } 50 | 51 | bool hasNonCellular = false; 52 | foreach (const QNetworkConfiguration &config, m_configManager.allConfigurations()) { 53 | if ((config.bearerType() == QNetworkConfiguration::BearerWLAN || 54 | config.bearerType() == QNetworkConfiguration::BearerEthernet) && 55 | config.state() == QNetworkConfiguration::Active) { 56 | hasNonCellular = true; 57 | break; 58 | } 59 | } 60 | 61 | if (hasNonCellular) { 62 | setShouldDownload(true); 63 | return; 64 | } 65 | 66 | setShouldDownload(false); 67 | } 68 | 69 | void NetworkMonitor::setShouldDownload(bool value) 70 | { 71 | if (this->m_shouldSync == value) { 72 | return; 73 | } 74 | 75 | this->m_shouldSync = value; 76 | Q_EMIT shouldSyncChanged(value); 77 | } 78 | -------------------------------------------------------------------------------- /src/daemon/networkmonitor.h: -------------------------------------------------------------------------------- 1 | #ifndef NETWORKMONITOR_H 2 | #define NETWORKMONITOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class NetworkMonitor : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit NetworkMonitor(QObject *parent = Q_NULLPTR, 16 | AccountBase* settings = Q_NULLPTR); 17 | ~NetworkMonitor(); 18 | bool shouldSync() { return m_shouldSync; } 19 | 20 | signals: 21 | void shouldSyncChanged(bool); 22 | 23 | public slots: 24 | void recheckNetworks(); 25 | 26 | private: 27 | void setShouldDownload(bool value); 28 | 29 | QNetworkConfigurationManager m_configManager; 30 | AccountBase* m_settings = Q_NULLPTR; 31 | bool m_shouldSync; 32 | QMutex checkerMutex; 33 | }; 34 | 35 | #endif // NETWORKMONITOR_H 36 | -------------------------------------------------------------------------------- /src/daemon/uploader.h: -------------------------------------------------------------------------------- 1 | #ifndef UPLOADER_H 2 | #define UPLOADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "networkmonitor.h" 8 | 9 | class Uploader : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Uploader(QObject *parent = Q_NULLPTR, 14 | const QString& targetDirectory = QStringLiteral(""), 15 | NetworkMonitor* networkMonitor = Q_NULLPTR, 16 | AccountBase* settings = Q_NULLPTR); 17 | public: 18 | bool running(); 19 | bool shouldSync(); 20 | 21 | public slots: 22 | void triggerSync(const QString &localPath, const QString &remoteSubdir); 23 | void stopSync(); 24 | 25 | private: 26 | const QString m_targetDirectory; 27 | NetworkMonitor* m_networkMonitor = Q_NULLPTR; 28 | AccountBase* m_settings = Q_NULLPTR; 29 | WebDavCommandQueue* m_webDavCommandQueue = Q_NULLPTR; 30 | QSet m_syncingPaths; 31 | 32 | signals: 33 | void runningChanged(); 34 | 35 | }; 36 | 37 | #endif // UPLOADER_H 38 | -------------------------------------------------------------------------------- /src/permission-agent/PermissionsDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | import Sailfish.Silica 1.0 3 | import harbour.owncloud 1.0 4 | 5 | ApplicationWindow 6 | { 7 | id: dialogRoot 8 | cover: undefined 9 | 10 | Connections { 11 | target: queue 12 | onPermissionRequested: { 13 | accountDb.refresh() 14 | pageStack.openDialog(dialog) 15 | } 16 | } 17 | 18 | initialPage: Component { 19 | Page { 20 | SilicaFlickable { } 21 | } 22 | } 23 | 24 | Dialog { 25 | id: dialog 26 | 27 | property var selectedAccount : null 28 | canAccept: selectedAccount !== null 29 | 30 | AccountWorkerGenerator { 31 | id: accountWorkerGenerator 32 | database: AccountDb { 33 | id: accountDb 34 | } 35 | } 36 | 37 | DialogHeader { 38 | id: header 39 | title: qsTr("Which cloud storage account would you like to use?") 40 | } 41 | 42 | ComboBox { 43 | id: accountsList 44 | width: parent.width 45 | anchors { 46 | top: header.bottom 47 | left: parent.left 48 | right: parent.right 49 | } 50 | onCurrentIndexChanged: { 51 | if (currentIndex === 0) { 52 | dialog.selectedAccount = null 53 | } 54 | } 55 | 56 | menu: ContextMenu { 57 | MenuItem { 58 | text: qsTr("Select an account...") 59 | } 60 | 61 | Repeater { 62 | id: accountRepeater 63 | model: accountWorkerGenerator.accountWorkers 64 | delegate: MenuItem { 65 | property var delegateAccountWorkers : accountRepeater.model[index] 66 | text: qsTr("%1 on %2", "username on https://server:443/dav/").arg(delegateAccountWorkers.account.username).arg(delegateAccountWorkers.account.hoststring) 67 | onClicked: { 68 | dialog.selectedAccount = delegateAccountWorkers.account 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | onAccepted: { 76 | dialogRoot.deactivate() 77 | queue.permitFirstInQueue(selectedAccount) 78 | accountsList.currentIndex = 0 79 | } 80 | onRejected: { 81 | dialogRoot.deactivate() 82 | queue.discardFirstInQueue() 83 | accountsList.currentIndex = 0 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/permission-agent/dbushandler.cpp: -------------------------------------------------------------------------------- 1 | #include "dbushandler.h" 2 | #include 3 | #include 4 | #include 5 | 6 | DBusHandler::DBusHandler(QObject *parent) : QObject(parent) 7 | { 8 | } 9 | 10 | DBusHandler::~DBusHandler() 11 | { 12 | 13 | } 14 | 15 | void DBusHandler::requestConfig() { 16 | message().setDelayedReply(true); 17 | emit dialogRequested(message()); 18 | } 19 | -------------------------------------------------------------------------------- /src/permission-agent/dbushandler.h: -------------------------------------------------------------------------------- 1 | #ifndef DBUSHANDLER_H 2 | #define DBUSHANDLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class DBusHandler : public QObject, QDBusContext 10 | { 11 | Q_OBJECT 12 | Q_CLASSINFO("D-Bus Interface", HARBOUR_OWNCLOUD_PERMD_IFACE) 13 | 14 | public: 15 | explicit DBusHandler(QObject *parent = nullptr); 16 | ~DBusHandler(); 17 | 18 | public slots: 19 | void requestConfig(); 20 | 21 | signals: 22 | void dialogRequested(QDBusMessage requestMessage); 23 | 24 | }; 25 | 26 | #endif // DBUSHANDLER_H 27 | -------------------------------------------------------------------------------- /src/permission-agent/dialogview.cpp: -------------------------------------------------------------------------------- 1 | #include "dialogview.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | DialogView::DialogView(QWindow *parent) : QQuickView(parent) 8 | { 9 | m_nativeHandle = QGuiApplication::platformNativeInterface(); 10 | connect(this, &DialogView::openglContextCreated, this, 11 | [=](QOpenGLContext *context) { 12 | m_nativeHandle->setWindowProperty(handle(), QLatin1String("CATEGORY"), "dialog"); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /src/permission-agent/dialogview.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOGVIEW_H 2 | #define DIALOGVIEW_H 3 | 4 | #include 5 | 6 | class QPlatformNativeInterface; 7 | class DialogView : public QQuickView 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit DialogView(QWindow *parent = Q_NULLPTR); 12 | 13 | private: 14 | QPlatformNativeInterface* m_nativeHandle = nullptr; 15 | 16 | signals: 17 | 18 | public slots: 19 | }; 20 | 21 | #endif // DIALOGVIEW_H 22 | -------------------------------------------------------------------------------- /src/permission-agent/harbour-owncloud-permission-agent.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ownCloud photo backup 3 | After=lipstick.service 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/usr/bin/harbour-owncloud-permission-agent 8 | Restart=always 9 | 10 | [Install] 11 | WantedBy=lipstick.service 12 | -------------------------------------------------------------------------------- /src/permission-agent/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dbushandler.h" 14 | #include "dialogview.h" 15 | #include "permissionrequestqueue.h" 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | qmlRegisterType("harbour.owncloud", 1, 0, "AccountDb"); 20 | qmlRegisterType("harbour.owncloud", 1, 0, "AccountWorkerGenerator"); 21 | qmlRegisterUncreatableType("harbour.owncloud", 1, 0, "AccountWorkers", 22 | "AccountWorkers are provided through the AccountDbWorkers type"); 23 | 24 | QGuiApplication app(argc, argv); 25 | prepareAppProperties(app); 26 | 27 | DBusHandler *dbusHandler = new DBusHandler; 28 | PermissionRequestQueue *requestQueue = new PermissionRequestQueue; 29 | QObject::connect(dbusHandler, &DBusHandler::dialogRequested, 30 | requestQueue, &PermissionRequestQueue::enqueueRequest); 31 | 32 | // We only need one instance 33 | if(!QDBusConnection::sessionBus().registerService(HarbourOwncloud::DBusConsts::PermAgent::DBUS_SERVICE) || 34 | !QDBusConnection::sessionBus().registerObject(HarbourOwncloud::DBusConsts::PermAgent::DBUS_PATH, dbusHandler, 35 | QDBusConnection::ExportAllSlots)) { 36 | exit(1); 37 | } 38 | 39 | DialogView* permissionsDialog = new DialogView(); 40 | permissionsDialog->engine()->rootContext()->setContextProperty("queue", requestQueue); 41 | permissionsDialog->setSource(QUrl("qrc:/PermissionsDialog.qml")); 42 | permissionsDialog->setFlags(Qt::Dialog | Qt::FramelessWindowHint); 43 | 44 | // Show and raise dialog on a request 45 | QObject::connect(requestQueue, &PermissionRequestQueue::permissionRequested, permissionsDialog, &QQuickView::show); 46 | QObject::connect(requestQueue, &PermissionRequestQueue::permissionRequested, permissionsDialog, &QQuickView::raise); 47 | 48 | return app.exec(); 49 | } 50 | -------------------------------------------------------------------------------- /src/permission-agent/permission-agent.pro: -------------------------------------------------------------------------------- 1 | TARGET = harbour-owncloud-permission-agent 2 | 3 | CONFIG = qt c++11 sailfishapp sailfish_build 4 | QT = dbus quick xml gui-private 5 | 6 | include($$PWD/../common/common.pri) 7 | 8 | SOURCES += \ 9 | main.cpp \ 10 | dbushandler.cpp \ 11 | dialogview.cpp \ 12 | permissionrequestqueue.cpp 13 | 14 | HEADERS += \ 15 | dbushandler.h \ 16 | dialogview.h \ 17 | permissionrequestqueue.h 18 | 19 | OTHER_FILES += harbour-owncloud-permission-agent.service 20 | 21 | service.path = /usr/lib/systemd/user/ 22 | service.files += harbour-owncloud-permission-agent.service 23 | binary.path = /usr/bin/ 24 | binary.files += $$OUT_PWD/harbour-owncloud-permission-agent 25 | 26 | INSTALLS += service binary 27 | 28 | RESOURCES += qml.qrc 29 | -------------------------------------------------------------------------------- /src/permission-agent/permissionrequestqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "permissionrequestqueue.h" 2 | 3 | #include 4 | #include 5 | 6 | PermissionRequestQueue::PermissionRequestQueue(QObject *parent) : QObject(parent) 7 | { 8 | } 9 | 10 | void PermissionRequestQueue::enqueueRequest(QDBusMessage requestMessage) 11 | { 12 | m_requestQueue.enqueue(requestMessage); 13 | emit permissionRequested(); 14 | } 15 | 16 | void PermissionRequestQueue::permitFirstInQueue(AccountBase* account) 17 | { 18 | if (m_requestQueue.length() < 1) 19 | return; 20 | 21 | QDBusMessage request = m_requestQueue.dequeue(); 22 | 23 | QMap values; 24 | values.insert(NEXTCLOUD_SETTINGS_KEY_CERTMD5, account->md5Hex()); 25 | values.insert(NEXTCLOUD_SETTINGS_KEY_CERTSHA1, account->sha1Hex()); 26 | values.insert(NEXTCLOUD_SETTINGS_KEY_ISHTTPS, account->isHttps()); 27 | values.insert(NEXTCLOUD_SETTINGS_KEY_HOSTNAME, account->hostname()); 28 | values.insert(NEXTCLOUD_SETTINGS_KEY_PORT, account->port()); 29 | values.insert(NEXTCLOUD_SETTINGS_KEY_PATH, account->path()); 30 | values.insert(NEXTCLOUD_SETTINGS_KEY_USERNAME, account->username()); 31 | values.insert(NEXTCLOUD_SETTINGS_KEY_PASSWORD, account->password()); 32 | values.insert(NEXTCLOUD_SETTINGS_KEY_PROVIDERTYPE, account->providerType()); 33 | values.insert(NEXTCLOUD_SETTINGS_KEY_MOBILEUPLOAD, account->mobileUpload()); 34 | values.insert(NEXTCLOUD_SETTINGS_KEY_NOTIFICATIONS, account->notifications()); 35 | values.insert(NEXTCLOUD_SETTINGS_KEY_UPLOADAUTOMATICALLY, account->uploadAutomatically()); 36 | values.insert(NEXTCLOUD_PERMD_REQUESTDENIED, false); 37 | 38 | QDBusMessage reply = request.createReply(values); 39 | QDBusConnection::sessionBus().send(reply); 40 | 41 | qInfo() << "Request permitted"; 42 | 43 | // Check for the next request 44 | if (m_requestQueue.length() > 0) 45 | emit permissionRequested(); 46 | } 47 | 48 | void PermissionRequestQueue::discardFirstInQueue() 49 | { 50 | // Dequeue and return 51 | if (m_requestQueue.length() < 1) 52 | return; 53 | 54 | QDBusMessage request = m_requestQueue.dequeue(); 55 | 56 | QMap values; 57 | values.insert(NEXTCLOUD_PERMD_REQUESTDENIED, true); 58 | 59 | QDBusMessage reply = request.createReply(values); 60 | QDBusConnection::sessionBus().send(reply); 61 | qInfo() << "Request rejected"; 62 | 63 | // Check for the next request 64 | if (m_requestQueue.length() > 0) 65 | emit permissionRequested(); 66 | } 67 | -------------------------------------------------------------------------------- /src/permission-agent/permissionrequestqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMISSIONREQUESTQUEUE_H 2 | #define PERMISSIONREQUESTQUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class PermissionRequestQueue : public QObject 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit PermissionRequestQueue(QObject *parent = 0); 16 | void enqueueRequest(QDBusMessage requestMessage); 17 | 18 | public slots: 19 | void permitFirstInQueue(AccountBase* account); 20 | void discardFirstInQueue(); 21 | 22 | private: 23 | QQueue m_requestQueue; 24 | 25 | signals: 26 | void permissionRequested(); 27 | }; 28 | 29 | #endif // PERMISSIONREQUESTQUEUE_H 30 | -------------------------------------------------------------------------------- /src/permission-agent/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | PermissionsDialog.qml 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/qmlcommon/qmlcommon.pri: -------------------------------------------------------------------------------- 1 | CONFIG += qt c++11 2 | QT += qml 3 | 4 | INCLUDEPATH += $$PWD/src 5 | DEPENDPATH += $$PWD/src 6 | 7 | HEADERS += \ 8 | $$PWD/src/qmlmap.h 9 | 10 | SOURCES += \ 11 | $$PWD/src/qmlmap.cpp 12 | 13 | -------------------------------------------------------------------------------- /src/qmlcommon/src/qmlmap.cpp: -------------------------------------------------------------------------------- 1 | #include "qmlmap.h" 2 | 3 | QmlMap::QmlMap(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void QmlMap::insert(const QString &key, const QVariant &value) 9 | { 10 | this->m_map.insert(key, value); 11 | Q_EMIT inserted(key); 12 | } 13 | 14 | bool QmlMap::contains(const QString &key) 15 | { 16 | return this->m_map.contains(key); 17 | } 18 | 19 | QVariant QmlMap::value(const QString &key) 20 | { 21 | return this->m_map.value(key); 22 | } 23 | 24 | int QmlMap::remove(const QString &key) 25 | { 26 | int ret = this->m_map.remove(key); 27 | if (ret > 0) 28 | Q_EMIT removed(key); 29 | return ret; 30 | } 31 | 32 | void QmlMap::clear() 33 | { 34 | if (this->m_map.empty()) 35 | return; 36 | this->m_map.clear(); 37 | Q_EMIT cleared(); 38 | } 39 | -------------------------------------------------------------------------------- /src/qmlcommon/src/qmlmap.h: -------------------------------------------------------------------------------- 1 | #ifndef QMLMAP_H 2 | #define QMLMAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QmlMap : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit QmlMap(QObject *parent = Q_NULLPTR); 13 | 14 | public slots: 15 | void insert(const QString& key, const QVariant& value); 16 | bool contains(const QString& key); 17 | QVariant value(const QString& key); 18 | int remove(const QString& key); 19 | void clear(); 20 | 21 | private: 22 | QMap m_map; 23 | 24 | signals: 25 | void inserted(QString key); 26 | void removed(QString key); 27 | void cleared(); 28 | 29 | }; 30 | Q_DECLARE_METATYPE(QmlMap*) 31 | 32 | #endif // QMLMAP_H 33 | -------------------------------------------------------------------------------- /src/qmlextension/harbourowncloudqmlplugin.cpp: -------------------------------------------------------------------------------- 1 | #include "harbourowncloudqmlplugin.h" 2 | -------------------------------------------------------------------------------- /src/qmlextension/harbourowncloudqmlplugin.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class HarbourOwncloudQmlPlugin : public QQmlExtensionPlugin 11 | { 12 | Q_OBJECT 13 | Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) 14 | 15 | public: 16 | void registerTypes(const char *uri) 17 | { 18 | Q_ASSERT(uri == QLatin1String("com.github.beidl.harbourowncloud")); 19 | qmlRegisterType(uri, 1, 0, "CommandEntity"); 20 | qmlRegisterType(uri, 1, 0, "WebDavCommandQueue"); 21 | qmlRegisterType(uri, 1, 0, "AccountBase"); 22 | qmlRegisterType(uri, 1, 0, "PermittedSettings"); 23 | qmlRegisterType(uri, 1, 0, "FilePathUtil"); 24 | qmlRegisterType(uri, 1, 0, "QmlMap"); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/qmlextension/qmldir: -------------------------------------------------------------------------------- 1 | module com.github.beidl.harbourowncloud 2 | plugin harbourowncloudqmlplugin 3 | -------------------------------------------------------------------------------- /src/qmlextension/qmlextension.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | TARGET = $$qtLibraryTarget(harbourowncloudqmlplugin) 3 | CONFIG += plugin sailfish_build 4 | DEPENDPATH += . 5 | 6 | include($$PWD/../common/common.pri) 7 | include($$PWD/../qmlcommon/qmlcommon.pri) 8 | 9 | SOURCES += \ 10 | harbourowncloudqmlplugin.cpp 11 | 12 | target.path = $$[QT_INSTALL_QML]/com/github/beidl/harbourowncloud 13 | qmldir.files = $$PWD/qmldir 14 | qmldir.path = $$[QT_INSTALL_QML]/com/github/beidl/harbourowncloud 15 | 16 | INSTALLS += target qmldir 17 | 18 | HEADERS += \ 19 | harbourowncloudqmlplugin.h 20 | -------------------------------------------------------------------------------- /src/sharing/ghostcloudconsts.h: -------------------------------------------------------------------------------- 1 | #ifndef NEXTCLOUDCONSTS_H 2 | #define NEXTCLOUDCONSTS_H 3 | 4 | #include 5 | 6 | #define HARBOUROWNCLOUD_PLUGINID "com.github.beidl.harbour-owncloud.sharing" 7 | 8 | namespace harourowncloud { 9 | namespace consts { 10 | const QString SHARE_ID = QStringLiteral(HARBOUROWNCLOUD_PLUGINID); 11 | } 12 | } 13 | 14 | #endif // NEXTCLOUDCONSTS_H 15 | -------------------------------------------------------------------------------- /src/sharing/ghostcloudplugininfo.cpp: -------------------------------------------------------------------------------- 1 | #include "ghostcloudplugininfo.h" 2 | #include "ghostcloudconsts.h" 3 | 4 | #include 5 | 6 | GhostCloudPluginInfo::GhostCloudPluginInfo() 7 | : m_ready(false) 8 | { 9 | } 10 | 11 | GhostCloudPluginInfo::~GhostCloudPluginInfo() 12 | { 13 | } 14 | 15 | QList GhostCloudPluginInfo::info() const 16 | { 17 | return m_infoList; 18 | } 19 | 20 | void GhostCloudPluginInfo::query() 21 | { 22 | TransferMethodInfo info; 23 | QStringList capabilities; 24 | 25 | // Capabilites ie. what mimetypes this plugin supports 26 | capabilities << QLatin1String("image/*") 27 | << QLatin1String("video/*") 28 | << QLatin1String("text/*") 29 | << QLatin1String("application/*"); 30 | 31 | // TODO: Translations for 3rd party plugins is not yet supported by Sailfish OS. 32 | // Adding support there later, but for now just use what ever non-translated 33 | // string here. This string will be visible in the share method list. 34 | //: Display name for example share plugin 35 | //% "Example plugin" 36 | info.displayName = QStringLiteral("GhostCloud"); 37 | 38 | // Method ID is a unique identifier for this plugin. It is used to identify which share plugin should be 39 | // used for starting the sharing. 40 | info.methodId = harourowncloud::consts::SHARE_ID; 41 | 42 | // Path to the Sharing UI which this plugin provides. 43 | info.shareUIPath = QStringLiteral("/usr/share/nemo-transferengine/plugins/GhostCloudShareUI.qml"); 44 | 45 | info.accountIcon = QStringLiteral("image://theme/icon-m-share-harbour-owncloud"); 46 | 47 | // Pass information about capabilities. This info is used for filtering share plugins 48 | // which don't support defined types. For example, this plugin won't appear in the 49 | // share method list, if someone tries to share content which isn't image or vcard type, 50 | info.capabilitities = capabilities; 51 | 52 | m_infoList << info; 53 | 54 | // Let the world know that this plugin is ready 55 | m_ready = true; 56 | emit infoReady(); 57 | } 58 | 59 | 60 | bool GhostCloudPluginInfo::ready() const 61 | { 62 | return m_ready; 63 | } 64 | -------------------------------------------------------------------------------- /src/sharing/ghostcloudplugininfo.h: -------------------------------------------------------------------------------- 1 | #ifndef NEXTCLOUDPLUGININFO_H 2 | #define NEXTCLOUDPLUGININFO_H 3 | 4 | #include 5 | #include 6 | 7 | class GhostCloudPluginInfo : public TransferPluginInfo 8 | { 9 | Q_OBJECT 10 | public: 11 | GhostCloudPluginInfo(); 12 | ~GhostCloudPluginInfo(); 13 | 14 | QList info() const; 15 | void query(); 16 | bool ready() const; 17 | private: 18 | QList m_infoList; 19 | bool m_ready; 20 | }; 21 | 22 | #endif // NEXTCLOUDPLUGININFO_H 23 | -------------------------------------------------------------------------------- /src/sharing/ghostcloudshareplugin.cpp: -------------------------------------------------------------------------------- 1 | #include "ghostcloudshareplugin.h" 2 | #include "ghostclouduploader.h" 3 | #include "ghostcloudplugininfo.h" 4 | #include "ghostcloudconsts.h" 5 | 6 | #include 7 | 8 | GhostCloudSharePlugin::GhostCloudSharePlugin() 9 | { 10 | } 11 | 12 | GhostCloudSharePlugin::~GhostCloudSharePlugin() 13 | { 14 | } 15 | 16 | MediaTransferInterface * GhostCloudSharePlugin::transferObject() 17 | { 18 | return new GhostCloudUploader; 19 | } 20 | 21 | TransferPluginInfo *GhostCloudSharePlugin::infoObject() 22 | { 23 | return new GhostCloudPluginInfo; 24 | } 25 | 26 | QString GhostCloudSharePlugin::pluginId() const 27 | { 28 | return harourowncloud::consts::SHARE_ID; 29 | } 30 | 31 | bool GhostCloudSharePlugin::enabled() const 32 | { 33 | return true; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/sharing/ghostcloudshareplugin.h: -------------------------------------------------------------------------------- 1 | #ifndef NEXTCLOUDSHAREPLUGIN_H 2 | #define NEXTCLOUDSHAREPLUGIN_H 3 | 4 | #include 5 | #include "ghostcloudconsts.h" 6 | #include 7 | 8 | class Q_DECL_EXPORT GhostCloudSharePlugin : public QObject, public TransferPluginInterface 9 | { 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "com.github.beidl.harbour-owncloud.sharing") 12 | Q_INTERFACES(TransferPluginInterface) 13 | public: 14 | GhostCloudSharePlugin(); 15 | ~GhostCloudSharePlugin(); 16 | 17 | MediaTransferInterface * transferObject(); 18 | TransferPluginInfo *infoObject(); 19 | QString pluginId() const; 20 | bool enabled() const ; 21 | 22 | }; 23 | 24 | #endif // NEXTCLOUDSHAREPLUGIN_H 25 | -------------------------------------------------------------------------------- /src/sharing/ghostclouduploader.h: -------------------------------------------------------------------------------- 1 | #ifndef NEXTCLOUDUPLOADER_H 2 | #define NEXTCLOUDUPLOADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class GhostCloudUploader : public MediaTransferInterface 10 | { 11 | Q_OBJECT 12 | public: 13 | GhostCloudUploader(QObject *parent = 0); 14 | ~GhostCloudUploader(); 15 | 16 | QString displayName() const; 17 | QUrl serviceIcon() const; 18 | bool cancelEnabled() const; 19 | bool restartEnabled() const; 20 | 21 | private: 22 | WebDavCommandQueue m_commandQueue; 23 | 24 | public Q_SLOTS: 25 | void start(); 26 | void cancel(); 27 | }; 28 | 29 | #endif // NEXTCLOUDUPLOADER_H 30 | -------------------------------------------------------------------------------- /src/sharing/icons/z1.0/icon-m-share-harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/sharing/icons/z1.0/icon-m-share-harbour-owncloud.png -------------------------------------------------------------------------------- /src/sharing/icons/z1.25/icon-m-share-harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/sharing/icons/z1.25/icon-m-share-harbour-owncloud.png -------------------------------------------------------------------------------- /src/sharing/icons/z1.5-large/icon-m-share-harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/sharing/icons/z1.5-large/icon-m-share-harbour-owncloud.png -------------------------------------------------------------------------------- /src/sharing/icons/z1.75/icon-m-share-harbour-owncloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/src/sharing/icons/z1.75/icon-m-share-harbour-owncloud.png -------------------------------------------------------------------------------- /src/sharing/sharing.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | TARGET = $$qtLibraryTarget(ghostcloudshareplugin) 3 | CONFIG += plugin sailfish_build 4 | DEPENDPATH += . 5 | 6 | CONFIG += link_pkgconfig 7 | PKGCONFIG += nemotransferengine-qt5 8 | 9 | include($$PWD/../common/common.pri) 10 | 11 | # Input 12 | HEADERS += \ 13 | ghostcloudconsts.h \ 14 | ghostclouduploader.h \ 15 | ghostcloudplugininfo.h \ 16 | ghostcloudshareplugin.h 17 | 18 | SOURCES += \ 19 | ghostcloudplugininfo.cpp \ 20 | ghostclouduploader.cpp \ 21 | ghostcloudshareplugin.cpp 22 | 23 | OTHER_FILES += \ 24 | GhostCloudShareUI.qml 25 | 26 | target.path = $$LIBDIR/nemo-transferengine/plugins 27 | 28 | shareui.files = $$PWD/*.qml 29 | shareui.path = /usr/share/nemo-transferengine/plugins 30 | 31 | shareui_icon_64.files = $$PWD/icons/z1.0/icon-m-share-harbour-owncloud.png 32 | shareui_icon_64.path = /usr/share/themes/sailfish-default/meegotouch/z1.0/icons 33 | 34 | shareui_icon_80.files = $$PWD/icons/z1.25/icon-m-share-harbour-owncloud.png 35 | shareui_icon_80.path = /usr/share/themes/sailfish-default/meegotouch/z1.25/icons 36 | 37 | shareui_icon_72.files = $$PWD/icons/z1.5-large/icon-m-share-harbour-owncloud.png 38 | shareui_icon_72.path = /usr/share/themes/sailfish-default/meegotouch/z1.5-large/icons 39 | 40 | shareui_icon_112.files = $$PWD/icons/z1.75/icon-m-share-harbour-owncloud.png 41 | shareui_icon_112.path = /usr/share/themes/sailfish-default/meegotouch/z1.75/icons 42 | 43 | INSTALLS += \ 44 | target \ 45 | shareui \ 46 | shareui_icon_64 \ 47 | shareui_icon_80 \ 48 | shareui_icon_72 \ 49 | shareui_icon_112 50 | -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | QMAKE_CXXFLAGS += -std=gnu++0x 2 | 3 | TEMPLATE = subdirs 4 | CONFIG += ordered 5 | SUBDIRS += common 6 | 7 | !contains(CONFIG, noapp) { 8 | SUBDIRS += app 9 | } 10 | 11 | contains(CONFIG, noadditionals) { 12 | CONFIG += nodaemon nopermissionagent noqmlextension nosharing 13 | } 14 | 15 | !contains(CONFIG, nodaemon) { 16 | SUBDIRS += daemon 17 | } 18 | 19 | !contains(CONFIG, nopermissionagent) { 20 | SUBDIRS += permission-agent 21 | } 22 | 23 | !contains(CONFIG, noqmlextension) { 24 | SUBDIRS += qmlextension 25 | } 26 | 27 | !contains(CONFIG, nosharing) { 28 | SUBDIRS += sharing 29 | } 30 | 31 | contains(CONFIG, clickphotobackup) { 32 | SUBDIRS += ut-photobackup 33 | } 34 | -------------------------------------------------------------------------------- /src/ut-photobackup/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/icon_gray.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ut-photobackup/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/main.qml 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ut-photobackup/src/daemoncontrol.h: -------------------------------------------------------------------------------- 1 | #ifndef DAEMONCONTROL_H 2 | #define DAEMONCONTROL_H 3 | 4 | #include 5 | #include 6 | 7 | #ifndef QT_NO_DBUS 8 | #include 9 | #endif 10 | 11 | class DaemonControl : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit DaemonControl(QObject *parent = Q_NULLPTR); 16 | 17 | Q_PROPERTY(bool daemonInstalled READ daemonInstalled NOTIFY daemonInstalledChanged) 18 | Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) 19 | 20 | bool uploading(); 21 | 22 | public slots: 23 | void reloadConfig(); 24 | void abort(); 25 | bool daemonInstalled(); 26 | 27 | private: 28 | void daemonRegistered(const QString& serviceName); 29 | void daemonUnregistered(const QString& serviceName); 30 | bool isCurrentlyUploading(); 31 | 32 | bool m_uploading; 33 | 34 | #ifndef QT_NO_DBUS 35 | QDBusInterface* m_daemonInterface = Q_NULLPTR; 36 | QDBusServiceWatcher* m_daemonWatcher = Q_NULLPTR; 37 | #endif 38 | 39 | signals: 40 | void daemonInstalledChanged(); 41 | void uploadingChanged(); 42 | 43 | private slots: 44 | void setUploading(bool value); 45 | }; 46 | 47 | #endif // DAEMONCONTROL_H 48 | -------------------------------------------------------------------------------- /src/ut-photobackup/src/main.cpp: -------------------------------------------------------------------------------- 1 | // Qt Core & QML 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Common 10 | #include 11 | #include 12 | 13 | #include "daemoncontrol.h" 14 | #include "servicecreator.h" 15 | 16 | // Provide a fake SailfishOS namespace 17 | // on QtQuick.Controls-based environments 18 | namespace SailfishApp { 19 | static QGuiApplication* application(int& argc, char** argv) { 20 | if (qApp) 21 | return static_cast(qApp); 22 | return new QGuiApplication(argc, argv); 23 | } 24 | } 25 | 26 | namespace { 27 | inline static void createNecessaryDir(const QString& path) { 28 | const QDir configDir = QDir(path); 29 | if (!configDir.exists()) { 30 | const auto success = configDir.mkpath(configDir.absolutePath()); 31 | if (success) 32 | return; 33 | 34 | qWarning() << "Failed to create" << configDir.absolutePath(); 35 | return; 36 | } 37 | } 38 | } 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 43 | 44 | qmlRegisterType("harbour.owncloud", 1, 0, "DaemonControl"); 45 | qmlRegisterType("harbour.owncloud", 1, 0, "ServiceCreator"); 46 | qmlRegisterType("harbour.owncloud", 1, 0, "AccountsDb"); 47 | 48 | QGuiApplication* app = SailfishApp::application(argc, argv); 49 | prepareAppProperties(*app); 50 | 51 | // Create common directories 52 | { 53 | const QString upstartServiceDir = 54 | QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QStringLiteral("/.config/upstart"); 55 | createNecessaryDir(upstartServiceDir); 56 | } 57 | 58 | bool gspParse = false; 59 | const int gspEnv = qgetenv("GRID_UNIT_PX").toInt(&gspParse); 60 | const int GRID_UNIT_PX = gspParse ? gspEnv : 8; 61 | 62 | const int headerBarSize = 48; 63 | 64 | QQmlApplicationEngine* newEngine = new QQmlApplicationEngine(app); 65 | newEngine->rootContext()->setContextProperty("headerBarSize", headerBarSize); 66 | newEngine->rootContext()->setContextProperty("GRID_UNIT_PX", GRID_UNIT_PX); 67 | newEngine->load(QUrl("qrc:/qml/main.qml")); 68 | 69 | return app->exec(); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/ut-photobackup/src/servicecreator.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVICECREATOR_H 2 | #define SERVICECREATOR_H 3 | 4 | #include 5 | 6 | class ServiceCreator : public QObject 7 | { 8 | Q_OBJECT 9 | 10 | Q_PROPERTY(bool serviceEnabled READ serviceEnabled WRITE setServiceEnabled NOTIFY serviceEnabledChanged) 11 | 12 | public: 13 | explicit ServiceCreator(QObject *parent = nullptr); 14 | 15 | private: 16 | bool serviceEnabled(); 17 | void setServiceEnabled(bool value); 18 | 19 | QString serviceFilePath(); 20 | QString appId(); 21 | void initCtl(const QString& action); 22 | void initCtlReload(); 23 | 24 | signals: 25 | void serviceEnabledChanged(); 26 | 27 | }; 28 | 29 | #endif // SERVICECREATOR_H 30 | -------------------------------------------------------------------------------- /src/ut-photobackup/ut-photobackup.pro: -------------------------------------------------------------------------------- 1 | TARGET = harbour-owncloud-photobackup 2 | TEMPLATE = app 3 | 4 | QMAKE_RPATHDIR += $$OUT_PWD/../../3rdparty/qwebdav 5 | QMAKE_RPATHDIR += $$OUT_PWD/../common 6 | 7 | target.path = /usr/bin 8 | libwebdav.files += $$OUT_PWD/../../3rdparty/qwebdavlib/qwebdavlib/libqwebdav.so.1 9 | libwebdav.path = /usr/lib 10 | libcommon.files += $$OUT_PWD/../common/libharbourowncloudcommon.so.1 11 | libcommon.path = /usr/lib 12 | 13 | INSTALLS += target libwebdav libcommon 14 | 15 | include($$PWD/../common/common.pri) 16 | 17 | CONFIG += qt 18 | QT += quick qml dbus 19 | 20 | SOURCES += \ 21 | $$PWD/src/main.cpp \ 22 | $$PWD/src/servicecreator.cpp \ 23 | $$PWD/src/daemoncontrol.cpp 24 | 25 | HEADERS += \ 26 | $$PWD/src/servicecreator.h \ 27 | $$PWD/src/daemoncontrol.h 28 | 29 | RESOURCES += \ 30 | $$PWD/qml.qrc \ 31 | $$PWD/icons.qrc 32 | -------------------------------------------------------------------------------- /utphotobackup/ghostcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredldotme/harbour-owncloud/9abec1881c42f3fb3b60caddf30e1b9ec2ca6407/utphotobackup/ghostcloud.png -------------------------------------------------------------------------------- /utphotobackup/harbour-owncloud-photobackup.accounts: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "GhostCloud Photo Backups", 5 | "description": "Backup camera photos to your cloud", 6 | "provider": "nextcloud" 7 | }, 8 | { 9 | "name": "GhostCloud Photo Backups", 10 | "description": "Backup camera photos to your cloud", 11 | "provider": "owncloud" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /utphotobackup/harbour-owncloud-photobackup.apparmor: -------------------------------------------------------------------------------- 1 | { 2 | "policy_groups": [], 3 | "template" : "unconfined", 4 | "policy_version": 20.04 5 | } 6 | -------------------------------------------------------------------------------- /utphotobackup/harbour-owncloud-photobackup.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Icon=ghostcloud.png 4 | Exec=run.sh 5 | Name=GhostCloud Photo Backup 6 | X-Ubuntu-Touch=true 7 | X-Ubuntu-Splash-Color=#F5F5F5 8 | -------------------------------------------------------------------------------- /utphotobackup/manifest.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "name": "me.fredl.ghostcloudphotobackup", 3 | "title": "GhostCloud Photo Backup", 4 | "version": "0.9.9.8", 5 | "description": "Photo backups, built on the multi-platform client for ownCloud & NextCloud", 6 | "architecture": "@CLICK_ARCH@", 7 | "framework": "ubuntu-sdk-20.04", 8 | "maintainer": "Alfred Neumayer ", 9 | "hooks": { 10 | "harbour-owncloud-photobackup": { 11 | "apparmor": "harbour-owncloud-photobackup.apparmor", 12 | "desktop": "harbour-owncloud-photobackup.desktop", 13 | "accounts": "harbour-owncloud-photobackup.accounts" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /utphotobackup/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LD_LIBRARY_PATH=$PWD/usr/lib:$LD_LIBRARY_PATH 4 | export QT_QUICK_CONTROLS_MOBILE=true 5 | export QT_QUICK_CONTROLS_STYLE=Suru 6 | 7 | exec $PWD/usr/bin/harbour-owncloud-photobackup \ 8 | --desktop_file_hint=${HOME}/.local/share/applications/${APP_ID}.desktop "$@" 9 | -------------------------------------------------------------------------------- /utphotobackup/utphotobackup.pro: -------------------------------------------------------------------------------- 1 | # This creates the manifest.json file, it is the description file for the 2 | # click package. 3 | 4 | TEMPLATE = aux 5 | 6 | # figure out the current build architecture 7 | CLICK_ARCH=$$system(dpkg-architecture -qDEB_HOST_ARCH) 8 | 9 | # do not remove this line, it is required by the IDE even if you do 10 | # not substitute variables in the manifest file 11 | UBUNTU_MANIFEST_FILE = $$PWD/manifest.json.in 12 | 13 | 14 | # substitute the architecture in the manifest file 15 | manifest_file.output = manifest.json 16 | manifest_file.CONFIG += no_link \ 17 | add_inputs_as_makefile_deps\ 18 | target_predeps 19 | manifest_file.commands = sed s/@CLICK_ARCH@/$$CLICK_ARCH/g ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT} 20 | manifest_file.input = UBUNTU_MANIFEST_FILE 21 | QMAKE_EXTRA_COMPILERS += manifest_file 22 | 23 | # installation path of the manifest file 24 | mfile.CONFIG += no_check_exist 25 | mfile.files += $$OUT_PWD/manifest.json 26 | mfile.path = / 27 | 28 | # AppArmor profile 29 | apparmor.files += $$PWD/harbour-owncloud-photobackup.apparmor 30 | apparmor.path = / 31 | 32 | # Desktop launcher icon 33 | desktopicon.files += $$PWD/ghostcloud.png 34 | desktopicon.path = / 35 | 36 | # Desktop launcher 37 | desktop.files += $$PWD/harbour-owncloud-photobackup.desktop 38 | desktop.path = / 39 | 40 | # Accounts description 41 | accounts.files += $$PWD/harbour-owncloud-photobackup.accounts 42 | accounts.path = / 43 | 44 | # Run script 45 | runscript.files += $$PWD/run.sh 46 | runscript.path = / 47 | 48 | INSTALLS += mfile apparmor runscript desktopicon desktop accounts 49 | --------------------------------------------------------------------------------