mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-24 17:05:00 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
845189c638 |
+4
-5
@@ -1,6 +1,5 @@
|
|||||||
commit_message: '[ci skip]'
|
commit_message: "[ci skip]"
|
||||||
|
escape_special_characters: 0
|
||||||
files:
|
files:
|
||||||
- source: /src/main/resources/i18n/strings.properties
|
- source: /main/ui/src/main/resources/i18n/strings.properties
|
||||||
translation: /src/main/resources/i18n/strings_%two_letters_code%.properties
|
translation: /main/ui/src/main/resources/i18n/strings_%two_letters_code%.properties
|
||||||
escape_quotes: 0
|
|
||||||
escape_special_characters: 0
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ include:
|
|||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexual language or imagery and unwelcome sexual attention or
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances
|
advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
* Public or private harassment
|
||||||
|
|||||||
+1
-1
@@ -14,5 +14,5 @@ For _everything else_, please visit our official [Cryptomator Community](https:/
|
|||||||
- Discussions about the apps
|
- Discussions about the apps
|
||||||
- [Development discussions](https://community.cryptomator.org/c/development)
|
- [Development discussions](https://community.cryptomator.org/c/development)
|
||||||
- General questions
|
- General questions
|
||||||
- Discussions regarding our design decisions
|
- Discussions regarding our design decissions
|
||||||
- Our roadmap
|
- Our roadmap
|
||||||
|
|||||||
+16
-42
@@ -20,38 +20,41 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-maven-
|
${{ runner.os }}-maven-
|
||||||
- name: Ensure to use tagged version
|
- name: Ensure to use tagged version
|
||||||
run: mvn versions:set -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
|
run: mvn versions:set --file main/pom.xml -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
- name: Build and Test
|
- name: Build and Test
|
||||||
run: mvn -B clean install jacoco:report -Pcoverage,dependency-check
|
run: mvn -B install --file main/pom.xml -Pcoverage
|
||||||
- name: Upload code coverage report
|
- name: Run Codacy Coverage Reporter
|
||||||
id: codacyCoverageReporter
|
if: github.repository == 'cryptomator/cryptomator'
|
||||||
run: bash <(curl -Ls https://coverage.codacy.com/get.sh)
|
run: |
|
||||||
|
curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar
|
||||||
|
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
|
||||||
|
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
|
||||||
|
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
|
||||||
|
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar final
|
||||||
env:
|
env:
|
||||||
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||||
continue-on-error: true
|
|
||||||
### TODO: move to matrix build:
|
|
||||||
- name: Assemble buildkit-linux.zip
|
- name: Assemble buildkit-linux.zip
|
||||||
run: mvn -B clean package -DskipTests -Plinux
|
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,linux
|
||||||
- name: Upload buildkit-linux.zip
|
- name: Upload buildkit-linux.zip
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: buildkit-linux.zip
|
name: buildkit-linux.zip
|
||||||
path: target/buildkit-linux.zip
|
path: main/buildkit/target/buildkit-linux.zip
|
||||||
- name: Assemble buildkit-mac.zip
|
- name: Assemble buildkit-mac.zip
|
||||||
run: mvn -B clean package -DskipTests -Pmac
|
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,mac
|
||||||
- name: Upload buildkit-mac.zip
|
- name: Upload buildkit-mac.zip
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: buildkit-mac.zip
|
name: buildkit-mac.zip
|
||||||
path: target/buildkit-mac.zip
|
path: main/buildkit/target/buildkit-mac.zip
|
||||||
- name: Assemble buildkit-win.zip
|
- name: Assemble buildkit-win.zip
|
||||||
run: mvn -B clean package -DskipTests -Pwindows
|
run: mvn -B clean package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease,windows
|
||||||
- name: Upload buildkit-win.zip
|
- name: Upload buildkit-win.zip
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: buildkit-win.zip
|
name: buildkit-win.zip
|
||||||
path: target/buildkit-win.zip
|
path: main/buildkit/target/buildkit-win.zip
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Draft a Release on GitHub Releases
|
name: Draft a Release on GitHub Releases
|
||||||
@@ -59,7 +62,6 @@ jobs:
|
|||||||
needs: build
|
needs: build
|
||||||
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'cryptomator/cryptomator'
|
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'cryptomator/cryptomator'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Download buildkit-linux.zip
|
- name: Download buildkit-linux.zip
|
||||||
uses: actions/download-artifact@v1
|
uses: actions/download-artifact@v1
|
||||||
with:
|
with:
|
||||||
@@ -75,15 +77,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: buildkit-win.zip
|
name: buildkit-win.zip
|
||||||
path: .
|
path: .
|
||||||
- name: Create tarball
|
|
||||||
run: git archive --prefix="cryptomator-${{ github.ref }}/" -o "cryptomator-${{ github.ref }}.tar.gz" ${{ github.ref }}
|
|
||||||
- name: Sign tarball with key 615D449FE6E6A235
|
|
||||||
run: |
|
|
||||||
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
|
|
||||||
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a "cryptomator-${{ github.ref }}.tar.gz"
|
|
||||||
env:
|
|
||||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
|
||||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1
|
uses: actions/create-release@v1
|
||||||
@@ -99,16 +92,6 @@ jobs:
|
|||||||
* [ ] add Linux appimage, zsync file and signature file
|
* [ ] add Linux appimage, zsync file and signature file
|
||||||
* [ ] add Windows installer and signature file
|
* [ ] add Windows installer and signature file
|
||||||
* [ ] add MacOs disk image and signature file
|
* [ ] add MacOs disk image and signature file
|
||||||
|
|
||||||
## What's new
|
|
||||||
|
|
||||||
## Bugfixes
|
|
||||||
|
|
||||||
## Misc
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
:scroll: A complete list of closed issues is available [here](LINK)
|
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
- name: Upload buildkit-linux.zip to GitHub Releases
|
- name: Upload buildkit-linux.zip to GitHub Releases
|
||||||
@@ -138,12 +121,3 @@ jobs:
|
|||||||
asset_path: buildkit-win.zip
|
asset_path: buildkit-win.zip
|
||||||
asset_name: buildkit-win.zip
|
asset_name: buildkit-win.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
- name: Upload tarball signature to GitHub Releases
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: "cryptomator-${{ github.ref }}.tar.gz.asc"
|
|
||||||
asset_name: "cryptomator-${{ github.ref }}.tar.gz.asc"
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|||||||
+1
-4
@@ -17,12 +17,9 @@ pom.xml.versionsBackup
|
|||||||
# IntelliJ Settings Files (https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems) #
|
# IntelliJ Settings Files (https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems) #
|
||||||
.idea/**/workspace.xml
|
.idea/**/workspace.xml
|
||||||
.idea/**/tasks.xml
|
.idea/**/tasks.xml
|
||||||
.idea/**/shelf
|
.idea/dictionaries
|
||||||
.idea/dictionaries/**
|
|
||||||
!.idea/dictionaries/dict_*
|
|
||||||
.idea/compiler.xml
|
.idea/compiler.xml
|
||||||
.idea/encodings.xml
|
.idea/encodings.xml
|
||||||
.idea/jarRepositories.xml
|
.idea/jarRepositories.xml
|
||||||
.idea/uiDesigner.xml
|
|
||||||
.idea/**/libraries/
|
.idea/**/libraries/
|
||||||
*.iml
|
*.iml
|
||||||
Generated
-15
@@ -1,15 +0,0 @@
|
|||||||
<component name="ProjectDictionaryState">
|
|
||||||
<dictionary name="dict_de">
|
|
||||||
<words>
|
|
||||||
<w>tresorinhalt</w>
|
|
||||||
<w>tresorkonfigurationsdatei</w>
|
|
||||||
<w>tresorlaufwerk</w>
|
|
||||||
<w>tresorliste</w>
|
|
||||||
<w>tresorname</w>
|
|
||||||
<w>tresoroptionen</w>
|
|
||||||
<w>tresorstatistik</w>
|
|
||||||
<w>ungespeicherten</w>
|
|
||||||
<w>ungespeicherter</w>
|
|
||||||
</words>
|
|
||||||
</dictionary>
|
|
||||||
</component>
|
|
||||||
Generated
-106
@@ -1,106 +0,0 @@
|
|||||||
<component name="ProjectDictionaryState">
|
|
||||||
<dictionary name="dict_project">
|
|
||||||
<words>
|
|
||||||
<w>addvault</w>
|
|
||||||
<w>addvaultwizard</w>
|
|
||||||
<w>adoptopenjdk</w>
|
|
||||||
<w>affero</w>
|
|
||||||
<w>aquafx</w>
|
|
||||||
<w>autolock</w>
|
|
||||||
<w>autolocked</w>
|
|
||||||
<w>autolocking</w>
|
|
||||||
<w>baos</w>
|
|
||||||
<w>bkup</w>
|
|
||||||
<w>buildkit</w>
|
|
||||||
<w>changepassword</w>
|
|
||||||
<w>checkerframework</w>
|
|
||||||
<w>crit</w>
|
|
||||||
<w>crowdin</w>
|
|
||||||
<w>cryptofs</w>
|
|
||||||
<w>cryptomator</w>
|
|
||||||
<w>cryptomator's</w>
|
|
||||||
<w>cryptor</w>
|
|
||||||
<w>csprng</w>
|
|
||||||
<w>dcryptomator</w>
|
|
||||||
<w>dfuse</w>
|
|
||||||
<w>dirid</w>
|
|
||||||
<w>djdk</w>
|
|
||||||
<w>dokany</w>
|
|
||||||
<w>dragboard</w>
|
|
||||||
<w>easybind</w>
|
|
||||||
<w>encr</w>
|
|
||||||
<w>errorprone</w>
|
|
||||||
<w>failureaccess</w>
|
|
||||||
<w>fbidis</w>
|
|
||||||
<w>fldinst</w>
|
|
||||||
<w>fldrslt</w>
|
|
||||||
<w>fontawesomefx</w>
|
|
||||||
<w>gdrive</w>
|
|
||||||
<w>gvfs</w>
|
|
||||||
<w>hmmss</w>
|
|
||||||
<w>httpcomponents</w>
|
|
||||||
<w>httpcore</w>
|
|
||||||
<w>iclouddrive</w>
|
|
||||||
<w>jensd</w>
|
|
||||||
<w>jffi</w>
|
|
||||||
<w>keyloading</w>
|
|
||||||
<w>kibs</w>
|
|
||||||
<w>listcell</w>
|
|
||||||
<w>listenablefuture</w>
|
|
||||||
<w>lopp</w>
|
|
||||||
<w>mainwindow</w>
|
|
||||||
<w>masterkey</w>
|
|
||||||
<w>masterkeyfile</w>
|
|
||||||
<w>mibs</w>
|
|
||||||
<w>mountpath</w>
|
|
||||||
<w>mpc's</w>
|
|
||||||
<w>needsmigration</w>
|
|
||||||
<w>noncommercially</w>
|
|
||||||
<w>noël</w>
|
|
||||||
<w>nulab</w>
|
|
||||||
<w>oatomic</w>
|
|
||||||
<w>oauto</w>
|
|
||||||
<w>objectgraph</w>
|
|
||||||
<w>odefault</w>
|
|
||||||
<w>ogid</w>
|
|
||||||
<w>onoappledouble</w>
|
|
||||||
<w>ordonly</w>
|
|
||||||
<w>ouid</w>
|
|
||||||
<w>ovolname</w>
|
|
||||||
<w>passthrough</w>
|
|
||||||
<w>patreon</w>
|
|
||||||
<w>pcloud</w>
|
|
||||||
<w>probot</w>
|
|
||||||
<w>recoverykey</w>
|
|
||||||
<w>relicensing</w>
|
|
||||||
<w>removevault</w>
|
|
||||||
<w>revealer</w>
|
|
||||||
<w>serceman</w>
|
|
||||||
<w>setolabs</w>
|
|
||||||
<w>skymatic</w>
|
|
||||||
<w>socio</w>
|
|
||||||
<w>spof</w>
|
|
||||||
<w>stenzel</w>
|
|
||||||
<w>styleclass</w>
|
|
||||||
<w>sublicenses</w>
|
|
||||||
<w>sublicensing</w>
|
|
||||||
<w>systemkeychain</w>
|
|
||||||
<w>tada</w>
|
|
||||||
<w>tidelift</w>
|
|
||||||
<w>tmpmountpoint</w>
|
|
||||||
<w>tobiasdiez</w>
|
|
||||||
<w>toggler</w>
|
|
||||||
<w>traymenu</w>
|
|
||||||
<w>unknownerror</w>
|
|
||||||
<w>unlockable</w>
|
|
||||||
<w>vaultconfig</w>
|
|
||||||
<w>vaultlist</w>
|
|
||||||
<w>vaultname</w>
|
|
||||||
<w>vaultoptions</w>
|
|
||||||
<w>wrongfilealert</w>
|
|
||||||
<w>xattr</w>
|
|
||||||
<w>zillmann</w>
|
|
||||||
<w>zxcvbn</w>
|
|
||||||
</words>
|
|
||||||
</dictionary>
|
|
||||||
</component>
|
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
<option name="processCode" value="true" />
|
<option name="processCode" value="true" />
|
||||||
<option name="processLiterals" value="true" />
|
<option name="processLiterals" value="true" />
|
||||||
<option name="processComments" value="true" />
|
<option name="processComments" value="true" />
|
||||||
|
|||||||
Generated
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
<option name="originalFiles">
|
<option name="originalFiles">
|
||||||
<list>
|
<list>
|
||||||
<option value="$PROJECT_DIR$/pom.xml" />
|
<option value="$PROJECT_DIR$/main/pom.xml" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/Desktop.iml" filepath="$PROJECT_DIR$/.idea/Desktop.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
|
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
|
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
|
<env name="LD_LIBRARY_PATH" value="/usr/local/lib" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="launcher" />
|
||||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[](https://cryptomator.org/)
|
[](https://cryptomator.org/)
|
||||||
|
|
||||||
[](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
|
[](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
|
||||||
[](https://snyk.io/test/github/cryptomator/cryptomator)
|
[](https://snyk.io/test/github/cryptomator/cryptomator?targetFile=main%2Fpom.xml)
|
||||||
[](https://www.codacy.com/gh/cryptomator/cryptomator/dashboard)
|
[](https://www.codacy.com/gh/cryptomator/cryptomator/dashboard)
|
||||||
[](http://twitter.com/Cryptomator)
|
[](http://twitter.com/Cryptomator)
|
||||||
[](https://translate.cryptomator.org/)
|
[](https://translate.cryptomator.org/)
|
||||||
@@ -48,7 +48,7 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Works with Dropbox, Google Drive, OneDrive, MEGA, pCloud, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
|
- Works with Dropbox, Google Drive, OneDrive, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
|
||||||
- Open Source means: No backdoors, control is better than trust
|
- Open Source means: No backdoors, control is better than trust
|
||||||
- Client-side: No accounts, no data shared with any online service
|
- Client-side: No accounts, no data shared with any online service
|
||||||
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive
|
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive
|
||||||
@@ -87,13 +87,13 @@ For more information on the security details visit [cryptomator.org](https://doc
|
|||||||
### Run Maven
|
### Run Maven
|
||||||
|
|
||||||
```
|
```
|
||||||
mvn clean install
|
cd main
|
||||||
# or mvn clean install -Pwindows
|
mvn clean install -Prelease,windows
|
||||||
# or mvn clean install -Pmac
|
# or mvn clean install -Prelease,mac
|
||||||
# or mvn clean install -Plinux
|
# or mvn clean install -Prelease,linux
|
||||||
```
|
```
|
||||||
|
|
||||||
This will build all the jars and bundle them together with their OS-specific dependencies under `target`. This can now be used to build native packages.
|
This will build all the jars and bundle them together with their OS-specific dependencies under `main/buildkit/target`. This can now be used to build native packages.
|
||||||
|
|
||||||
### Start Cryptomator
|
### Start Cryptomator
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,6 @@
|
|||||||
<outputDirectory></outputDirectory>
|
<outputDirectory></outputDirectory>
|
||||||
<fileMode>0755</fileMode>
|
<fileMode>0755</fileMode>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<fileSet>
|
|
||||||
<directory>target/</directory>
|
|
||||||
<includes>
|
|
||||||
<include>cryptomator-*.jar</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>libs</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>target/libs</directory>
|
<directory>target/libs</directory>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -29,13 +29,6 @@
|
|||||||
<outputDirectory></outputDirectory>
|
<outputDirectory></outputDirectory>
|
||||||
<fileMode>0755</fileMode>
|
<fileMode>0755</fileMode>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<fileSet>
|
|
||||||
<directory>target/</directory>
|
|
||||||
<includes>
|
|
||||||
<include>cryptomator-*.jar</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>libs</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>target/libs</directory>
|
<directory>target/libs</directory>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -29,13 +29,6 @@
|
|||||||
<outputDirectory></outputDirectory>
|
<outputDirectory></outputDirectory>
|
||||||
<fileMode>0755</fileMode>
|
<fileMode>0755</fileMode>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<fileSet>
|
|
||||||
<directory>target/</directory>
|
|
||||||
<includes>
|
|
||||||
<include>cryptomator-*.jar</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>libs</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>target/libs</directory>
|
<directory>target/libs</directory>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>main</artifactId>
|
||||||
|
<version>1.6.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>buildkit</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Cryptomator Build Kit</name>
|
||||||
|
<description>Builds a package that can be built with Ant locally</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>launcher</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- copy resources -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-resources</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.basedir}/src/main/resources</directory>
|
||||||
|
<includes>
|
||||||
|
<include>version.txt</include>
|
||||||
|
<include>ffi-version.txt</include>
|
||||||
|
<include>launcher-mac.sh</include>
|
||||||
|
<include>launcher-linux.sh</include>
|
||||||
|
<include>launcher-win.bat</include>
|
||||||
|
<include>LICENSE.txt</include>
|
||||||
|
</includes>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- copy libraries to target/libs/: -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-libs</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<includeScope>runtime</includeScope>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<excludeClassifiers>linux,mac,win</excludeClassifiers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>linux</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>assemble-linux</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>assembly-linux.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<finalName>buildkit-linux</finalName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-linux-libs</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<includeGroupIds>org.openjfx</includeGroupIds>
|
||||||
|
<classifier>linux</classifier>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>mac</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>assemble-mac</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>assembly-mac.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<finalName>buildkit-mac</finalName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-mac-libs</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<includeGroupIds>org.openjfx</includeGroupIds>
|
||||||
|
<classifier>mac</classifier>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>windows</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>assemble-win</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>assembly-win.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<finalName>buildkit-win</finalName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-win-libs</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
||||||
|
<includeGroupIds>org.openjfx</includeGroupIds>
|
||||||
|
<classifier>win</classifier>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>main</artifactId>
|
||||||
|
<version>1.6.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>commons</artifactId>
|
||||||
|
<name>Cryptomator Commons</name>
|
||||||
|
<description>Shared utilities</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>cryptofs</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>fuse-nio-adapter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>dokany-nio-adapter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>webdav-nio-adapter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>integrations-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JavaFx -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-base</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-graphics</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- EasyBind -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.tobiasdiez</groupId>
|
||||||
|
<artifactId>easybind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JWT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Google -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache Commons -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DI -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.dagger</groupId>
|
||||||
|
<artifactId>dagger</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
+7
-22
@@ -15,8 +15,6 @@ import org.cryptomator.common.settings.SettingsProvider;
|
|||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
import org.cryptomator.common.vaults.VaultComponent;
|
import org.cryptomator.common.vaults.VaultComponent;
|
||||||
import org.cryptomator.common.vaults.VaultListManager;
|
import org.cryptomator.common.vaults.VaultListManager;
|
||||||
import org.cryptomator.common.vaults.VaultListModule;
|
|
||||||
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
|
|
||||||
import org.cryptomator.frontend.webdav.WebDavServer;
|
import org.cryptomator.frontend.webdav.WebDavServer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -27,8 +25,6 @@ import javafx.beans.binding.Binding;
|
|||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@@ -38,7 +34,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Module(subcomponents = {VaultComponent.class}, includes = {VaultListModule.class, KeychainModule.class})
|
@Module(subcomponents = {VaultComponent.class}, includes = {KeychainModule.class})
|
||||||
public abstract class CommonsModule {
|
public abstract class CommonsModule {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CommonsModule.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CommonsModule.class);
|
||||||
@@ -46,7 +42,6 @@ public abstract class CommonsModule {
|
|||||||
private static final int NUM_CORE_BG_THREADS = 6;
|
private static final int NUM_CORE_BG_THREADS = 6;
|
||||||
private static final long BG_THREAD_KEEPALIVE_SECONDS = 60l;
|
private static final long BG_THREAD_KEEPALIVE_SECONDS = 60l;
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("licensePublicKey")
|
@Named("licensePublicKey")
|
||||||
@@ -60,22 +55,6 @@ public abstract class CommonsModule {
|
|||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
static SecureRandom provideCSPRNG() {
|
|
||||||
try {
|
|
||||||
return SecureRandom.getInstanceStrong();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IllegalStateException("A strong algorithm must exist in every Java platform.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
static MasterkeyFileAccess provideMasterkeyFileAccess(SecureRandom csprng) {
|
|
||||||
return new MasterkeyFileAccess(Constants.PEPPER, csprng);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("SemVer")
|
@Named("SemVer")
|
||||||
@@ -89,6 +68,12 @@ public abstract class CommonsModule {
|
|||||||
return settingsProvider.get();
|
return settingsProvider.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static ObservableList<Vault> provideVaultList(VaultListManager vaultListManager) {
|
||||||
|
return vaultListManager.getVaultList();
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
static ScheduledExecutorService provideScheduledExecutorService(ShutdownHook shutdownHook) {
|
static ScheduledExecutorService provideScheduledExecutorService(ShutdownHook shutdownHook) {
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.cryptomator.common;
|
||||||
|
|
||||||
|
public interface Constants {
|
||||||
|
|
||||||
|
String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||||
|
|
||||||
|
}
|
||||||
+4
-4
@@ -99,12 +99,12 @@ public class Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// visible for testing
|
// visible for testing
|
||||||
public Path getHomeDir() {
|
Path getHomeDir() {
|
||||||
return getPath("user.home").orElseThrow();
|
return getPath("user.home").orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// visible for testing
|
// visible for testing
|
||||||
public Stream<Path> getPaths(String propertyName) {
|
Stream<Path> getPaths(String propertyName) {
|
||||||
Stream<String> rawSettingsPaths = getRawList(propertyName, PATH_LIST_SEP);
|
Stream<String> rawSettingsPaths = getRawList(propertyName, PATH_LIST_SEP);
|
||||||
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Paths::get).map(this::replaceHomeDir);
|
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Paths::get).map(this::replaceHomeDir);
|
||||||
}
|
}
|
||||||
@@ -123,8 +123,8 @@ public class Environment {
|
|||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
} else {
|
} else {
|
||||||
Iterable<String> iter = Splitter.on(separator).split(value);
|
Iterable<String> iter = Splitter.on(separator).split(value);
|
||||||
Spliterator<String> spliterator = Spliterators.spliteratorUnknownSize(iter.iterator(), Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
Spliterator<String> spliter = Spliterators.spliteratorUnknownSize(iter.iterator(), Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||||
return StreamSupport.stream(spliterator, false);
|
return StreamSupport.stream(spliter, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-5
@@ -60,17 +60,17 @@ public class SemVerComparator implements Comparator<String> {
|
|||||||
final int commonCompCount = Math.min(vComps1.length, vComps2.length);
|
final int commonCompCount = Math.min(vComps1.length, vComps2.length);
|
||||||
|
|
||||||
for (int i = 0; i < commonCompCount; i++) {
|
for (int i = 0; i < commonCompCount; i++) {
|
||||||
int subversionComparisonResult = 0;
|
int subversionComparisionResult = 0;
|
||||||
try {
|
try {
|
||||||
final int v1 = Integer.parseInt(vComps1[i]);
|
final int v1 = Integer.parseInt(vComps1[i]);
|
||||||
final int v2 = Integer.parseInt(vComps2[i]);
|
final int v2 = Integer.parseInt(vComps2[i]);
|
||||||
subversionComparisonResult = v1 - v2;
|
subversionComparisionResult = v1 - v2;
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
// ok, lets compare this fragment lexicographically
|
// ok, lets compare this fragment lexicographically
|
||||||
subversionComparisonResult = vComps1[i].compareTo(vComps2[i]);
|
subversionComparisionResult = vComps1[i].compareTo(vComps2[i]);
|
||||||
}
|
}
|
||||||
if (subversionComparisonResult != 0) {
|
if (subversionComparisionResult != 0) {
|
||||||
return subversionComparisonResult;
|
return subversionComparisionResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-4
@@ -59,10 +59,8 @@ public class KeychainManager implements KeychainAccessProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
|
public void changePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
|
||||||
if (isPassphraseStored(key)) {
|
getKeychainOrFail().changePassphrase(key, passphrase);
|
||||||
getKeychainOrFail().changePassphrase(key, passphrase);
|
setPassphraseStored(key, true);
|
||||||
setPassphraseStored(key, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+2
-2
@@ -34,11 +34,11 @@ public class KeychainModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
static ObjectExpression<KeychainAccessProvider> provideKeychainAccessProvider(Settings settings, Set<KeychainAccessProvider> providers) {
|
static ObjectExpression<KeychainAccessProvider> provideKeychainAccessProvider(Settings settings, Set<KeychainAccessProvider> providers) {
|
||||||
return Bindings.createObjectBinding(() -> {
|
return Bindings.createObjectBinding(() -> {
|
||||||
var selectedProviderClass = settings.keychainProvider().get();
|
var selectedProviderClass = settings.keychainBackend().get().getProviderClass();
|
||||||
var selectedProvider = providers.stream().filter(provider -> provider.getClass().getName().equals(selectedProviderClass)).findAny();
|
var selectedProvider = providers.stream().filter(provider -> provider.getClass().getName().equals(selectedProviderClass)).findAny();
|
||||||
var fallbackProvider = providers.stream().findAny().orElse(null);
|
var fallbackProvider = providers.stream().findAny().orElse(null);
|
||||||
return selectedProvider.orElse(fallbackProvider);
|
return selectedProvider.orElse(fallbackProvider);
|
||||||
}, settings.keychainProvider());
|
}, settings.keychainBackend());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
package org.cryptomator.common.mountpoint;
|
package org.cryptomator.common.mountpoint;
|
||||||
|
|
||||||
import dagger.multibindings.IntKey;
|
import com.google.common.base.Preconditions;
|
||||||
import org.cryptomator.common.vaults.Volume;
|
import org.cryptomator.common.vaults.Volume;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -12,13 +12,13 @@ import java.util.SortedSet;
|
|||||||
* preparation of a mountpoint or an exception otherwise.<br>
|
* preparation of a mountpoint or an exception otherwise.<br>
|
||||||
* <p>All <i>MountPointChoosers (MPCs)</i> need to implement this class and must be added to
|
* <p>All <i>MountPointChoosers (MPCs)</i> need to implement this class and must be added to
|
||||||
* the pool of possible MPCs by the {@link MountPointChooserModule MountPointChooserModule.}
|
* the pool of possible MPCs by the {@link MountPointChooserModule MountPointChooserModule.}
|
||||||
* The MountPointChooserModule will sort them according to their {@link IntKey IntKey priority.}
|
* The MountPointChooserModule will sort them according to their {@link #getPriority() priority.}
|
||||||
* The priority must be defined by the developer to reflect a useful execution order.<br>
|
* The priority must be defined by the developer to reflect a useful execution order.<br>
|
||||||
* A specific priority <b>must not</b> be assigned to more than one MPC at a time;
|
* A specific priority <b>must not</b> be assigned to more than one MPC at a time;
|
||||||
* the result of having two MPCs with equal priority is undefined.
|
* the result of having two MPCs with equal priority is undefined.
|
||||||
*
|
*
|
||||||
* <p>MPCs are executed by a {@link Volume} in descending order of their priority
|
* <p>MPCs are executed by a {@link Volume} in ascending order of their priority
|
||||||
* (higher priorities are tried first) to find and prepare a suitable mountpoint for the volume.
|
* (smaller priorities are tried first) to find and prepare a suitable mountpoint for the volume.
|
||||||
* The volume has access to a {@link SortedSet} of MPCs in this specific order,
|
* The volume has access to a {@link SortedSet} of MPCs in this specific order,
|
||||||
* that is provided by the Module. The Set contains all available Choosers, even if they
|
* that is provided by the Module. The Set contains all available Choosers, even if they
|
||||||
* are not {@link #isApplicable(Volume) applicable} for the Vault/Volume. The Volume must
|
* are not {@link #isApplicable(Volume) applicable} for the Vault/Volume. The Volume must
|
||||||
+10
-12
@@ -9,7 +9,6 @@ import dagger.multibindings.IntoMap;
|
|||||||
import org.cryptomator.common.vaults.PerVault;
|
import org.cryptomator.common.vaults.PerVault;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@@ -25,22 +24,16 @@ public abstract class MountPointChooserModule {
|
|||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@IntKey(1000)
|
@IntKey(0)
|
||||||
@PerVault
|
@PerVault
|
||||||
public abstract MountPointChooser bindCustomMountPointChooser(CustomMountPointChooser chooser);
|
public abstract MountPointChooser bindCustomMountPointChooser(CustomMountPointChooser chooser);
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@IntKey(900)
|
@IntKey(100)
|
||||||
@PerVault
|
@PerVault
|
||||||
public abstract MountPointChooser bindCustomDriveLetterChooser(CustomDriveLetterChooser chooser);
|
public abstract MountPointChooser bindCustomDriveLetterChooser(CustomDriveLetterChooser chooser);
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@IntKey(800)
|
|
||||||
@PerVault
|
|
||||||
public abstract MountPointChooser bindAvailableDriveLetterChooser(AvailableDriveLetterChooser chooser);
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@IntKey(101)
|
@IntKey(101)
|
||||||
@@ -49,7 +42,13 @@ public abstract class MountPointChooserModule {
|
|||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@IntKey(100)
|
@IntKey(200)
|
||||||
|
@PerVault
|
||||||
|
public abstract MountPointChooser bindAvailableDriveLetterChooser(AvailableDriveLetterChooser chooser);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@IntKey(999)
|
||||||
@PerVault
|
@PerVault
|
||||||
public abstract MountPointChooser bindTemporaryMountPointChooser(TemporaryMountPointChooser chooser);
|
public abstract MountPointChooser bindTemporaryMountPointChooser(TemporaryMountPointChooser chooser);
|
||||||
|
|
||||||
@@ -57,8 +56,7 @@ public abstract class MountPointChooserModule {
|
|||||||
@PerVault
|
@PerVault
|
||||||
@Named("orderedMountPointChoosers")
|
@Named("orderedMountPointChoosers")
|
||||||
public static Iterable<MountPointChooser> provideOrderedMountPointChoosers(Map<Integer, MountPointChooser> choosers) {
|
public static Iterable<MountPointChooser> provideOrderedMountPointChoosers(Map<Integer, MountPointChooser> choosers) {
|
||||||
SortedMap<Integer, MountPointChooser> sortedChoosers = new TreeMap<>(Comparator.reverseOrder());
|
SortedMap<Integer, MountPointChooser> sortedChoosers = new TreeMap<>(choosers);
|
||||||
sortedChoosers.putAll(choosers);
|
|
||||||
return Iterables.unmodifiableIterable(sortedChoosers.values());
|
return Iterables.unmodifiableIterable(sortedChoosers.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.cryptomator.common.settings;
|
||||||
|
|
||||||
|
public enum KeychainBackend {
|
||||||
|
GNOME("org.cryptomator.linux.keychain.SecretServiceKeychainAccess"),
|
||||||
|
KDE("org.cryptomator.linux.keychain.KDEWalletKeychainAccess"),
|
||||||
|
MAC_SYSTEM_KEYCHAIN("org.cryptomator.macos.keychain.MacSystemKeychainAccess"),
|
||||||
|
WIN_SYSTEM_KEYCHAIN("org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess");
|
||||||
|
|
||||||
|
private final String providerClass;
|
||||||
|
|
||||||
|
KeychainBackend(String providerClass) {
|
||||||
|
this.providerClass = providerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderClass() {
|
||||||
|
return providerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+6
-7
@@ -30,7 +30,7 @@ public class Settings {
|
|||||||
public static final int MIN_PORT = 1024;
|
public static final int MIN_PORT = 1024;
|
||||||
public static final int MAX_PORT = 65535;
|
public static final int MAX_PORT = 65535;
|
||||||
public static final boolean DEFAULT_ASKED_FOR_UPDATE_CHECK = false;
|
public static final boolean DEFAULT_ASKED_FOR_UPDATE_CHECK = false;
|
||||||
public static final boolean DEFAULT_CHECK_FOR_UPDATES = false;
|
public static final boolean DEFAULT_CHECK_FOR_UDPATES = false;
|
||||||
public static final boolean DEFAULT_START_HIDDEN = false;
|
public static final boolean DEFAULT_START_HIDDEN = false;
|
||||||
public static final int DEFAULT_PORT = 42427;
|
public static final int DEFAULT_PORT = 42427;
|
||||||
public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
|
public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
|
||||||
@@ -38,15 +38,14 @@ public class Settings {
|
|||||||
public static final boolean DEFAULT_DEBUG_MODE = false;
|
public static final boolean DEFAULT_DEBUG_MODE = false;
|
||||||
public static final VolumeImpl DEFAULT_PREFERRED_VOLUME_IMPL = SystemUtils.IS_OS_WINDOWS ? VolumeImpl.DOKANY : VolumeImpl.FUSE;
|
public static final VolumeImpl DEFAULT_PREFERRED_VOLUME_IMPL = SystemUtils.IS_OS_WINDOWS ? VolumeImpl.DOKANY : VolumeImpl.FUSE;
|
||||||
public static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
|
public static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
|
||||||
@Deprecated // to be changed to "whatever is available" eventually
|
public static final KeychainBackend DEFAULT_KEYCHAIN_BACKEND = SystemUtils.IS_OS_WINDOWS ? KeychainBackend.WIN_SYSTEM_KEYCHAIN : SystemUtils.IS_OS_MAC ? KeychainBackend.MAC_SYSTEM_KEYCHAIN : KeychainBackend.GNOME;
|
||||||
public static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : "org.cryptomator.linux.keychain.SecretServiceKeychainAccess";
|
|
||||||
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
|
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
|
||||||
public static final String DEFAULT_LICENSE_KEY = "";
|
public static final String DEFAULT_LICENSE_KEY = "";
|
||||||
public static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
|
public static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
|
||||||
|
|
||||||
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
|
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
|
||||||
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
|
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
|
||||||
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UPDATES);
|
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UDPATES);
|
||||||
private final BooleanProperty startHidden = new SimpleBooleanProperty(DEFAULT_START_HIDDEN);
|
private final BooleanProperty startHidden = new SimpleBooleanProperty(DEFAULT_START_HIDDEN);
|
||||||
private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT);
|
private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT);
|
||||||
private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS);
|
private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS);
|
||||||
@@ -54,7 +53,7 @@ public class Settings {
|
|||||||
private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE);
|
private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE);
|
||||||
private final ObjectProperty<VolumeImpl> preferredVolumeImpl = new SimpleObjectProperty<>(DEFAULT_PREFERRED_VOLUME_IMPL);
|
private final ObjectProperty<VolumeImpl> preferredVolumeImpl = new SimpleObjectProperty<>(DEFAULT_PREFERRED_VOLUME_IMPL);
|
||||||
private final ObjectProperty<UiTheme> theme = new SimpleObjectProperty<>(DEFAULT_THEME);
|
private final ObjectProperty<UiTheme> theme = new SimpleObjectProperty<>(DEFAULT_THEME);
|
||||||
private final ObjectProperty<String> keychainProvider = new SimpleObjectProperty<>(DEFAULT_KEYCHAIN_PROVIDER);
|
private final ObjectProperty<KeychainBackend> keychainBackend = new SimpleObjectProperty<>(DEFAULT_KEYCHAIN_BACKEND);
|
||||||
private final ObjectProperty<NodeOrientation> userInterfaceOrientation = new SimpleObjectProperty<>(DEFAULT_USER_INTERFACE_ORIENTATION);
|
private final ObjectProperty<NodeOrientation> userInterfaceOrientation = new SimpleObjectProperty<>(DEFAULT_USER_INTERFACE_ORIENTATION);
|
||||||
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
|
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
|
||||||
private final BooleanProperty showMinimizeButton = new SimpleBooleanProperty(DEFAULT_SHOW_MINIMIZE_BUTTON);
|
private final BooleanProperty showMinimizeButton = new SimpleBooleanProperty(DEFAULT_SHOW_MINIMIZE_BUTTON);
|
||||||
@@ -78,7 +77,7 @@ public class Settings {
|
|||||||
debugMode.addListener(this::somethingChanged);
|
debugMode.addListener(this::somethingChanged);
|
||||||
preferredVolumeImpl.addListener(this::somethingChanged);
|
preferredVolumeImpl.addListener(this::somethingChanged);
|
||||||
theme.addListener(this::somethingChanged);
|
theme.addListener(this::somethingChanged);
|
||||||
keychainProvider.addListener(this::somethingChanged);
|
keychainBackend.addListener(this::somethingChanged);
|
||||||
userInterfaceOrientation.addListener(this::somethingChanged);
|
userInterfaceOrientation.addListener(this::somethingChanged);
|
||||||
licenseKey.addListener(this::somethingChanged);
|
licenseKey.addListener(this::somethingChanged);
|
||||||
showMinimizeButton.addListener(this::somethingChanged);
|
showMinimizeButton.addListener(this::somethingChanged);
|
||||||
@@ -141,7 +140,7 @@ public class Settings {
|
|||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<String> keychainProvider() { return keychainProvider; }
|
public ObjectProperty<KeychainBackend> keychainBackend() { return keychainBackend; }
|
||||||
|
|
||||||
public ObjectProperty<NodeOrientation> userInterfaceOrientation() {
|
public ObjectProperty<NodeOrientation> userInterfaceOrientation() {
|
||||||
return userInterfaceOrientation;
|
return userInterfaceOrientation;
|
||||||
+11
-2
@@ -48,7 +48,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
|||||||
out.name("preferredVolumeImpl").value(value.preferredVolumeImpl().get().name());
|
out.name("preferredVolumeImpl").value(value.preferredVolumeImpl().get().name());
|
||||||
out.name("theme").value(value.theme().get().name());
|
out.name("theme").value(value.theme().get().name());
|
||||||
out.name("uiOrientation").value(value.userInterfaceOrientation().get().name());
|
out.name("uiOrientation").value(value.userInterfaceOrientation().get().name());
|
||||||
out.name("keychainProvider").value(value.keychainProvider().get());
|
out.name("keychainBackend").value(value.keychainBackend().get().name());
|
||||||
out.name("licenseKey").value(value.licenseKey().get());
|
out.name("licenseKey").value(value.licenseKey().get());
|
||||||
out.name("showMinimizeButton").value(value.showMinimizeButton().get());
|
out.name("showMinimizeButton").value(value.showMinimizeButton().get());
|
||||||
out.name("showTrayIcon").value(value.showTrayIcon().get());
|
out.name("showTrayIcon").value(value.showTrayIcon().get());
|
||||||
@@ -82,7 +82,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
|||||||
case "preferredVolumeImpl" -> settings.preferredVolumeImpl().set(parsePreferredVolumeImplName(in.nextString()));
|
case "preferredVolumeImpl" -> settings.preferredVolumeImpl().set(parsePreferredVolumeImplName(in.nextString()));
|
||||||
case "theme" -> settings.theme().set(parseUiTheme(in.nextString()));
|
case "theme" -> settings.theme().set(parseUiTheme(in.nextString()));
|
||||||
case "uiOrientation" -> settings.userInterfaceOrientation().set(parseUiOrientation(in.nextString()));
|
case "uiOrientation" -> settings.userInterfaceOrientation().set(parseUiOrientation(in.nextString()));
|
||||||
case "keychainProvider" -> settings.keychainProvider().set(in.nextString());
|
case "keychainBackend" -> settings.keychainBackend().set(parseKeychainBackend(in.nextString()));
|
||||||
case "licenseKey" -> settings.licenseKey().set(in.nextString());
|
case "licenseKey" -> settings.licenseKey().set(in.nextString());
|
||||||
case "showMinimizeButton" -> settings.showMinimizeButton().set(in.nextBoolean());
|
case "showMinimizeButton" -> settings.showMinimizeButton().set(in.nextBoolean());
|
||||||
case "showTrayIcon" -> settings.showTrayIcon().set(in.nextBoolean());
|
case "showTrayIcon" -> settings.showTrayIcon().set(in.nextBoolean());
|
||||||
@@ -124,6 +124,15 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KeychainBackend parseKeychainBackend(String backendName) {
|
||||||
|
try {
|
||||||
|
return KeychainBackend.valueOf(backendName.toUpperCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOG.warn("Invalid keychain backend {}. Defaulting to {}.", backendName, Settings.DEFAULT_KEYCHAIN_BACKEND);
|
||||||
|
return Settings.DEFAULT_KEYCHAIN_BACKEND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private NodeOrientation parseUiOrientation(String uiOrientationName) {
|
private NodeOrientation parseUiOrientation(String uiOrientationName) {
|
||||||
try {
|
try {
|
||||||
return NodeOrientation.valueOf(uiOrientationName.toUpperCase());
|
return NodeOrientation.valueOf(uiOrientationName.toUpperCase());
|
||||||
+1
-1
@@ -101,7 +101,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
|||||||
if (settings == null) {
|
if (settings == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // always save to preferred (first) path
|
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // alway save to preferred (first) path
|
||||||
settingsPath.ifPresent(path -> {
|
settingsPath.ifPresent(path -> {
|
||||||
Runnable saveCommand = () -> this.save(settings, path);
|
Runnable saveCommand = () -> this.save(settings, path);
|
||||||
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, SAVE_DELAY_MS, TimeUnit.MILLISECONDS);
|
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, SAVE_DELAY_MS, TimeUnit.MILLISECONDS);
|
||||||
+10
-19
@@ -24,6 +24,8 @@ import java.nio.file.Path;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings specific to a single vault.
|
* The settings specific to a single vault.
|
||||||
@@ -31,14 +33,12 @@ import java.util.Random;
|
|||||||
public class VaultSettings {
|
public class VaultSettings {
|
||||||
|
|
||||||
public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false;
|
public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false;
|
||||||
public static final boolean DEFAULT_REVEAL_AFTER_MOUNT = true;
|
public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true;
|
||||||
public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false;
|
public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false;
|
||||||
public static final boolean DEFAULT_USES_READONLY_MODE = false;
|
public static final boolean DEFAULT_USES_READONLY_MODE = false;
|
||||||
public static final String DEFAULT_MOUNT_FLAGS = "";
|
public static final String DEFAULT_MOUNT_FLAGS = "";
|
||||||
public static final int DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH = -1;
|
public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1;
|
||||||
public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
|
public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
|
||||||
public static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false;
|
|
||||||
public static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60;
|
|
||||||
|
|
||||||
private static final Random RNG = new Random();
|
private static final Random RNG = new Random();
|
||||||
|
|
||||||
@@ -47,15 +47,14 @@ public class VaultSettings {
|
|||||||
private final StringProperty displayName = new SimpleStringProperty();
|
private final StringProperty displayName = new SimpleStringProperty();
|
||||||
private final StringProperty winDriveLetter = new SimpleStringProperty();
|
private final StringProperty winDriveLetter = new SimpleStringProperty();
|
||||||
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
|
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
|
||||||
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REVEAL_AFTER_MOUNT);
|
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT);
|
||||||
private final BooleanProperty useCustomMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH);
|
private final BooleanProperty useCustomMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH);
|
||||||
private final StringProperty customMountPath = new SimpleStringProperty();
|
private final StringProperty customMountPath = new SimpleStringProperty();
|
||||||
private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE);
|
private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE);
|
||||||
private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS);
|
private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS);
|
||||||
private final IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH);
|
private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT);
|
||||||
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
|
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
|
||||||
private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE);
|
|
||||||
private final IntegerProperty autoLockIdleSeconds = new SimpleIntegerProperty(DEFAULT_AUTOLOCK_IDLE_SECONDS);
|
|
||||||
private final StringBinding mountName;
|
private final StringBinding mountName;
|
||||||
|
|
||||||
public VaultSettings(String id) {
|
public VaultSettings(String id) {
|
||||||
@@ -64,7 +63,7 @@ public class VaultSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Observable[] observables() {
|
Observable[] observables() {
|
||||||
return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, autoLockWhenIdle, autoLockIdleSeconds};
|
return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VaultSettings withRandomId() {
|
public static VaultSettings withRandomId() {
|
||||||
@@ -153,8 +152,8 @@ public class VaultSettings {
|
|||||||
return mountFlags;
|
return mountFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerProperty maxCleartextFilenameLength() {
|
public IntegerProperty filenameLengthLimit() {
|
||||||
return maxCleartextFilenameLength;
|
return filenameLengthLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<WhenUnlocked> actionAfterUnlock() {
|
public ObjectProperty<WhenUnlocked> actionAfterUnlock() {
|
||||||
@@ -165,14 +164,6 @@ public class VaultSettings {
|
|||||||
return actionAfterUnlock.get();
|
return actionAfterUnlock.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanProperty autoLockWhenIdle() {
|
|
||||||
return autoLockWhenIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntegerProperty autoLockIdleSeconds() {
|
|
||||||
return autoLockIdleSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hashcode/Equals */
|
/* Hashcode/Equals */
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+5
-13
@@ -29,10 +29,8 @@ class VaultSettingsJsonAdapter {
|
|||||||
out.name("customMountPath").value(value.customMountPath().get());
|
out.name("customMountPath").value(value.customMountPath().get());
|
||||||
out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get());
|
out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get());
|
||||||
out.name("mountFlags").value(value.mountFlags().get());
|
out.name("mountFlags").value(value.mountFlags().get());
|
||||||
out.name("maxCleartextFilenameLength").value(value.maxCleartextFilenameLength().get());
|
out.name("filenameLengthLimit").value(value.filenameLengthLimit().get());
|
||||||
out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name());
|
out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name());
|
||||||
out.name("autoLockWhenIdle").value(value.autoLockWhenIdle().get());
|
|
||||||
out.name("autoLockIdleSeconds").value(value.autoLockIdleSeconds().get());
|
|
||||||
out.endObject();
|
out.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,14 +42,12 @@ class VaultSettingsJsonAdapter {
|
|||||||
String customMountPath = null;
|
String customMountPath = null;
|
||||||
String winDriveLetter = null;
|
String winDriveLetter = null;
|
||||||
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
|
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
|
||||||
boolean revealAfterMount = VaultSettings.DEFAULT_REVEAL_AFTER_MOUNT;
|
boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT;
|
||||||
boolean useCustomMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH;
|
boolean useCustomMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH;
|
||||||
boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE;
|
boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE;
|
||||||
String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS;
|
String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS;
|
||||||
int maxCleartextFilenameLength = VaultSettings.DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH;
|
int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT;
|
||||||
WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK;
|
WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK;
|
||||||
boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE;
|
|
||||||
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
|
|
||||||
|
|
||||||
in.beginObject();
|
in.beginObject();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
@@ -68,10 +64,8 @@ class VaultSettingsJsonAdapter {
|
|||||||
case "individualMountPath", "customMountPath" -> customMountPath = in.nextString();
|
case "individualMountPath", "customMountPath" -> customMountPath = in.nextString();
|
||||||
case "usesReadOnlyMode" -> usesReadOnlyMode = in.nextBoolean();
|
case "usesReadOnlyMode" -> usesReadOnlyMode = in.nextBoolean();
|
||||||
case "mountFlags" -> mountFlags = in.nextString();
|
case "mountFlags" -> mountFlags = in.nextString();
|
||||||
case "maxCleartextFilenameLength" -> maxCleartextFilenameLength = in.nextInt();
|
case "filenameLengthLimit" -> filenameLengthLimit = in.nextInt();
|
||||||
case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString());
|
case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString());
|
||||||
case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean();
|
|
||||||
case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt();
|
|
||||||
default -> {
|
default -> {
|
||||||
LOG.warn("Unsupported vault setting found in JSON: " + name);
|
LOG.warn("Unsupported vault setting found in JSON: " + name);
|
||||||
in.skipValue();
|
in.skipValue();
|
||||||
@@ -94,10 +88,8 @@ class VaultSettingsJsonAdapter {
|
|||||||
vaultSettings.customMountPath().set(customMountPath);
|
vaultSettings.customMountPath().set(customMountPath);
|
||||||
vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode);
|
vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode);
|
||||||
vaultSettings.mountFlags().set(mountFlags);
|
vaultSettings.mountFlags().set(mountFlags);
|
||||||
vaultSettings.maxCleartextFilenameLength().set(maxCleartextFilenameLength);
|
vaultSettings.filenameLengthLimit().set(filenameLengthLimit);
|
||||||
vaultSettings.actionAfterUnlock().set(actionAfterUnlock);
|
vaultSettings.actionAfterUnlock().set(actionAfterUnlock);
|
||||||
vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle);
|
|
||||||
vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds);
|
|
||||||
return vaultSettings;
|
return vaultSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
+8
-6
@@ -5,15 +5,15 @@ import org.cryptomator.common.mountpoint.MountPointChooser;
|
|||||||
import org.cryptomator.common.settings.VaultSettings;
|
import org.cryptomator.common.settings.VaultSettings;
|
||||||
import org.cryptomator.common.settings.VolumeImpl;
|
import org.cryptomator.common.settings.VolumeImpl;
|
||||||
import org.cryptomator.cryptofs.CryptoFileSystem;
|
import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||||
import org.cryptomator.frontend.dokany.DokanyMountFailedException;
|
|
||||||
import org.cryptomator.frontend.dokany.Mount;
|
import org.cryptomator.frontend.dokany.Mount;
|
||||||
import org.cryptomator.frontend.dokany.MountFactory;
|
import org.cryptomator.frontend.dokany.MountFactory;
|
||||||
|
import org.cryptomator.frontend.dokany.MountFailedException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import java.util.function.Consumer;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
public class DokanyVolume extends AbstractVolume {
|
public class DokanyVolume extends AbstractVolume {
|
||||||
|
|
||||||
@@ -22,13 +22,15 @@ public class DokanyVolume extends AbstractVolume {
|
|||||||
private static final String FS_TYPE_NAME = "CryptomatorFS";
|
private static final String FS_TYPE_NAME = "CryptomatorFS";
|
||||||
|
|
||||||
private final VaultSettings vaultSettings;
|
private final VaultSettings vaultSettings;
|
||||||
|
private final MountFactory mountFactory;
|
||||||
|
|
||||||
private Mount mount;
|
private Mount mount;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DokanyVolume(VaultSettings vaultSettings, @Named("orderedMountPointChoosers") Iterable<MountPointChooser> choosers) {
|
public DokanyVolume(VaultSettings vaultSettings, ExecutorService executorService, @Named("orderedMountPointChoosers") Iterable<MountPointChooser> choosers) {
|
||||||
super(choosers);
|
super(choosers);
|
||||||
this.vaultSettings = vaultSettings;
|
this.vaultSettings = vaultSettings;
|
||||||
|
this.mountFactory = new MountFactory(executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -37,11 +39,11 @@ public class DokanyVolume extends AbstractVolume {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws InvalidMountPointException, VolumeException {
|
public void mount(CryptoFileSystem fs, String mountFlags) throws InvalidMountPointException, VolumeException {
|
||||||
this.mountPoint = determineMountPoint();
|
this.mountPoint = determineMountPoint();
|
||||||
try {
|
try {
|
||||||
this.mount = MountFactory.mount(fs.getPath("/"), mountPoint, vaultSettings.mountName().get(), FS_TYPE_NAME, mountFlags.strip(), onExitAction);
|
this.mount = mountFactory.mount(fs.getPath("/"), mountPoint, vaultSettings.mountName().get(), FS_TYPE_NAME, mountFlags.strip());
|
||||||
} catch (DokanyMountFailedException e) {
|
} catch (MountFailedException e) {
|
||||||
if (vaultSettings.getCustomMountPath().isPresent()) {
|
if (vaultSettings.getCustomMountPath().isPresent()) {
|
||||||
LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPoint);
|
LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPoint);
|
||||||
}
|
}
|
||||||
+12
-12
@@ -6,8 +6,8 @@ import org.cryptomator.common.mountpoint.InvalidMountPointException;
|
|||||||
import org.cryptomator.common.mountpoint.MountPointChooser;
|
import org.cryptomator.common.mountpoint.MountPointChooser;
|
||||||
import org.cryptomator.common.settings.VolumeImpl;
|
import org.cryptomator.common.settings.VolumeImpl;
|
||||||
import org.cryptomator.cryptofs.CryptoFileSystem;
|
import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||||
|
import org.cryptomator.frontend.fuse.mount.CommandFailedException;
|
||||||
import org.cryptomator.frontend.fuse.mount.EnvironmentVariables;
|
import org.cryptomator.frontend.fuse.mount.EnvironmentVariables;
|
||||||
import org.cryptomator.frontend.fuse.mount.FuseMountException;
|
|
||||||
import org.cryptomator.frontend.fuse.mount.FuseMountFactory;
|
import org.cryptomator.frontend.fuse.mount.FuseMountFactory;
|
||||||
import org.cryptomator.frontend.fuse.mount.FuseNotSupportedException;
|
import org.cryptomator.frontend.fuse.mount.FuseNotSupportedException;
|
||||||
import org.cryptomator.frontend.fuse.mount.Mount;
|
import org.cryptomator.frontend.fuse.mount.Mount;
|
||||||
@@ -20,7 +20,6 @@ import javax.inject.Named;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class FuseVolume extends AbstractVolume {
|
public class FuseVolume extends AbstractVolume {
|
||||||
@@ -36,21 +35,20 @@ public class FuseVolume extends AbstractVolume {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws InvalidMountPointException, VolumeException {
|
public void mount(CryptoFileSystem fs, String mountFlags) throws InvalidMountPointException, VolumeException {
|
||||||
this.mountPoint = determineMountPoint();
|
this.mountPoint = determineMountPoint();
|
||||||
mount(fs.getPath("/"), mountFlags, onExitAction);
|
|
||||||
|
mount(fs.getPath("/"), mountFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mount(Path root, String mountFlags, Consumer<Throwable> onExitAction) throws VolumeException {
|
private void mount(Path root, String mountFlags) throws VolumeException {
|
||||||
try {
|
try {
|
||||||
Mounter mounter = FuseMountFactory.getMounter();
|
Mounter mounter = FuseMountFactory.getMounter();
|
||||||
EnvironmentVariables envVars = EnvironmentVariables.create() //
|
EnvironmentVariables envVars = EnvironmentVariables.create() //
|
||||||
.withFlags(splitFlags(mountFlags)) //
|
.withFlags(splitFlags(mountFlags)).withMountPoint(mountPoint) //
|
||||||
.withMountPoint(mountPoint) //
|
|
||||||
.withFileNameTranscoder(mounter.defaultFileNameTranscoder()) //
|
|
||||||
.build();
|
.build();
|
||||||
this.mount = mounter.mount(root, envVars, onExitAction);
|
this.mount = mounter.mount(root, envVars);
|
||||||
} catch ( FuseMountException | FuseNotSupportedException e) {
|
} catch (CommandFailedException | FuseNotSupportedException e) {
|
||||||
throw new VolumeException("Unable to mount Filesystem", e);
|
throw new VolumeException("Unable to mount Filesystem", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +89,8 @@ public class FuseVolume extends AbstractVolume {
|
|||||||
public synchronized void unmountForced() throws VolumeException {
|
public synchronized void unmountForced() throws VolumeException {
|
||||||
try {
|
try {
|
||||||
mount.unmountForced();
|
mount.unmountForced();
|
||||||
} catch (FuseMountException e) {
|
mount.close();
|
||||||
|
} catch (CommandFailedException e) {
|
||||||
throw new VolumeException(e);
|
throw new VolumeException(e);
|
||||||
}
|
}
|
||||||
cleanupMountPoint();
|
cleanupMountPoint();
|
||||||
@@ -101,7 +100,8 @@ public class FuseVolume extends AbstractVolume {
|
|||||||
public synchronized void unmount() throws VolumeException {
|
public synchronized void unmount() throws VolumeException {
|
||||||
try {
|
try {
|
||||||
mount.unmount();
|
mount.unmount();
|
||||||
} catch (FuseMountException e) {
|
mount.close();
|
||||||
|
} catch (CommandFailedException e) {
|
||||||
throw new VolumeException(e);
|
throw new VolumeException(e);
|
||||||
}
|
}
|
||||||
cleanupMountPoint();
|
cleanupMountPoint();
|
||||||
+46
-80
@@ -17,12 +17,10 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
|
|||||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
||||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags;
|
import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags;
|
||||||
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
||||||
import org.cryptomator.cryptofs.VaultConfig;
|
import org.cryptomator.cryptofs.common.Constants;
|
||||||
import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig;
|
|
||||||
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
|
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
|
||||||
import org.cryptomator.cryptolib.api.CryptoException;
|
import org.cryptomator.cryptolib.api.CryptoException;
|
||||||
import org.cryptomator.cryptolib.api.MasterkeyLoader;
|
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
||||||
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -37,29 +35,28 @@ import javafx.beans.property.BooleanProperty;
|
|||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||||
|
|
||||||
@PerVault
|
@PerVault
|
||||||
public class Vault {
|
public class Vault {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Vault.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Vault.class);
|
||||||
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
|
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
|
||||||
private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
private final VaultSettings vaultSettings;
|
private final VaultSettings vaultSettings;
|
||||||
private final Provider<Volume> volumeProvider;
|
private final Provider<Volume> volumeProvider;
|
||||||
private final StringBinding defaultMountFlags;
|
private final StringBinding defaultMountFlags;
|
||||||
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
|
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
|
||||||
private final VaultState state;
|
private final ObjectProperty<VaultState> state;
|
||||||
private final ObjectProperty<Exception> lastKnownException;
|
private final ObjectProperty<Exception> lastKnownException;
|
||||||
private final VaultStats stats;
|
private final VaultStats stats;
|
||||||
private final StringBinding displayName;
|
private final StringBinding displayName;
|
||||||
@@ -77,7 +74,7 @@ public class Vault {
|
|||||||
private volatile Volume volume;
|
private volatile Volume volume;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
|
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, ObjectProperty<VaultState> state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
|
||||||
this.vaultSettings = vaultSettings;
|
this.vaultSettings = vaultSettings;
|
||||||
this.volumeProvider = volumeProvider;
|
this.volumeProvider = volumeProvider;
|
||||||
this.defaultMountFlags = defaultMountFlags;
|
this.defaultMountFlags = defaultMountFlags;
|
||||||
@@ -102,31 +99,24 @@ public class Vault {
|
|||||||
// Commands
|
// Commands
|
||||||
// ********************************************************************************/
|
// ********************************************************************************/
|
||||||
|
|
||||||
private CryptoFileSystem createCryptoFileSystem(MasterkeyLoader keyLoader) throws IOException, MasterkeyLoadingFailedException {
|
private CryptoFileSystem createCryptoFileSystem(CharSequence passphrase) throws NoSuchFileException, IOException, InvalidPassphraseException, CryptoException {
|
||||||
Set<FileSystemFlags> flags = EnumSet.noneOf(FileSystemFlags.class);
|
Set<FileSystemFlags> flags = EnumSet.noneOf(FileSystemFlags.class);
|
||||||
if (vaultSettings.usesReadOnlyMode().get()) {
|
if (vaultSettings.usesReadOnlyMode().get()) {
|
||||||
flags.add(FileSystemFlags.READONLY);
|
flags.add(FileSystemFlags.READONLY);
|
||||||
} else if(vaultSettings.maxCleartextFilenameLength().get() == -1) {
|
|
||||||
LOG.debug("Determining cleartext filename length limitations...");
|
|
||||||
var checker = new FileSystemCapabilityChecker();
|
|
||||||
int shorteningThreshold = getUnverifiedVaultConfig().allegedShorteningThreshold();
|
|
||||||
int ciphertextLimit = checker.determineSupportedCiphertextFileNameLength(getPath());
|
|
||||||
if (ciphertextLimit < shorteningThreshold) {
|
|
||||||
int cleartextLimit = checker.determineSupportedCleartextFileNameLength(getPath());
|
|
||||||
vaultSettings.maxCleartextFilenameLength().set(cleartextLimit);
|
|
||||||
} else {
|
|
||||||
vaultSettings.maxCleartextFilenameLength().setValue(UNLIMITED_FILENAME_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!flags.contains(FileSystemFlags.READONLY) && vaultSettings.filenameLengthLimit().get() == -1) {
|
||||||
if (vaultSettings.maxCleartextFilenameLength().get() < UNLIMITED_FILENAME_LENGTH) {
|
LOG.debug("Determining file name length limitations...");
|
||||||
LOG.warn("Limiting cleartext filename length on this device to {}.", vaultSettings.maxCleartextFilenameLength().get());
|
int limit = new FileSystemCapabilityChecker().determineSupportedFileNameLength(getPath());
|
||||||
|
vaultSettings.filenameLengthLimit().set(limit);
|
||||||
|
LOG.info("Storing file name length limit of {}", limit);
|
||||||
}
|
}
|
||||||
|
assert vaultSettings.filenameLengthLimit().get() > 0;
|
||||||
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
|
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
|
||||||
.withKeyLoader(keyLoader) //
|
.withPassphrase(passphrase) //
|
||||||
.withFlags(flags) //
|
.withFlags(flags) //
|
||||||
.withMaxCleartextNameLength(vaultSettings.maxCleartextFilenameLength().get()) //
|
.withMasterkeyFilename(MASTERKEY_FILENAME) //
|
||||||
|
.withMaxPathLength(vaultSettings.filenameLengthLimit().get() + Constants.MAX_ADDITIONAL_PATH_LENGTH) //
|
||||||
|
.withMaxNameLength(vaultSettings.filenameLengthLimit().get()) //
|
||||||
.build();
|
.build();
|
||||||
return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
|
return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
|
||||||
}
|
}
|
||||||
@@ -143,51 +133,29 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void unlock(MasterkeyLoader keyLoader) throws CryptoException, IOException, VolumeException, InvalidMountPointException {
|
public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException, VolumeException, InvalidMountPointException {
|
||||||
if (cryptoFileSystem.get() != null) {
|
if (cryptoFileSystem.get() == null) {
|
||||||
|
CryptoFileSystem fs = createCryptoFileSystem(passphrase);
|
||||||
|
cryptoFileSystem.set(fs);
|
||||||
|
try {
|
||||||
|
volume = volumeProvider.get();
|
||||||
|
volume.mount(fs, getEffectiveMountFlags());
|
||||||
|
} catch (Exception e) {
|
||||||
|
destroyCryptoFileSystem();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
throw new IllegalStateException("Already unlocked.");
|
throw new IllegalStateException("Already unlocked.");
|
||||||
}
|
}
|
||||||
CryptoFileSystem fs = createCryptoFileSystem(keyLoader);
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
cryptoFileSystem.set(fs);
|
|
||||||
volume = volumeProvider.get();
|
|
||||||
volume.mount(fs, getEffectiveMountFlags(), this::lockOnVolumeExit);
|
|
||||||
success = true;
|
|
||||||
} finally {
|
|
||||||
if (!success) {
|
|
||||||
destroyCryptoFileSystem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockOnVolumeExit(Throwable t) {
|
public synchronized void lock(boolean forced) throws VolumeException {
|
||||||
LOG.info("Unmounted vault '{}'", getDisplayName());
|
|
||||||
destroyCryptoFileSystem();
|
|
||||||
state.set(VaultState.Value.LOCKED);
|
|
||||||
if (t != null) {
|
|
||||||
LOG.warn("Unexpected unmount and lock of vault " + getDisplayName(), t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void lock(boolean forced) throws VolumeException, LockNotCompletedException {
|
|
||||||
//initiate unmount
|
|
||||||
if (forced && volume.supportsForcedUnmount()) {
|
if (forced && volume.supportsForcedUnmount()) {
|
||||||
volume.unmountForced();
|
volume.unmountForced();
|
||||||
} else {
|
} else {
|
||||||
volume.unmount();
|
volume.unmount();
|
||||||
}
|
}
|
||||||
|
destroyCryptoFileSystem();
|
||||||
//wait for lockOnVolumeExit to be executed
|
|
||||||
try {
|
|
||||||
boolean locked = state.awaitState(VaultState.Value.LOCKED, 3000, TimeUnit.MILLISECONDS);
|
|
||||||
if (!locked) {
|
|
||||||
throw new LockNotCompletedException("Locking of vault " + this.getDisplayName() + " still in progress.");
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
throw new LockNotCompletedException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reveal(Volume.Revealer vaultRevealer) throws VolumeException {
|
public void reveal(Volume.Revealer vaultRevealer) throws VolumeException {
|
||||||
@@ -198,12 +166,16 @@ public class Vault {
|
|||||||
// Observable Properties
|
// Observable Properties
|
||||||
// *******************************************************************************
|
// *******************************************************************************
|
||||||
|
|
||||||
public VaultState stateProperty() {
|
public ObjectProperty<VaultState> stateProperty() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VaultState.Value getState() {
|
public VaultState getState() {
|
||||||
return state.getValue();
|
return state.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(VaultState value) {
|
||||||
|
state.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<Exception> lastKnownExceptionProperty() {
|
public ObjectProperty<Exception> lastKnownExceptionProperty() {
|
||||||
@@ -223,7 +195,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLocked() {
|
public boolean isLocked() {
|
||||||
return state.get() == VaultState.Value.LOCKED;
|
return state.get() == VaultState.LOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding processingProperty() {
|
public BooleanBinding processingProperty() {
|
||||||
@@ -231,7 +203,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isProcessing() {
|
public boolean isProcessing() {
|
||||||
return state.get() == VaultState.Value.PROCESSING;
|
return state.get() == VaultState.PROCESSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding unlockedProperty() {
|
public BooleanBinding unlockedProperty() {
|
||||||
@@ -239,7 +211,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnlocked() {
|
public boolean isUnlocked() {
|
||||||
return state.get() == VaultState.Value.UNLOCKED;
|
return state.get() == VaultState.UNLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding missingProperty() {
|
public BooleanBinding missingProperty() {
|
||||||
@@ -247,7 +219,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMissing() {
|
public boolean isMissing() {
|
||||||
return state.get() == VaultState.Value.MISSING;
|
return state.get() == VaultState.MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding needsMigrationProperty() {
|
public BooleanBinding needsMigrationProperty() {
|
||||||
@@ -255,7 +227,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNeedsMigration() {
|
public boolean isNeedsMigration() {
|
||||||
return state.get() == VaultState.Value.NEEDS_MIGRATION;
|
return state.get() == VaultState.NEEDS_MIGRATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding unknownErrorProperty() {
|
public BooleanBinding unknownErrorProperty() {
|
||||||
@@ -263,7 +235,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnknownError() {
|
public boolean isUnknownError() {
|
||||||
return state.get() == VaultState.Value.ERROR;
|
return state.get() == VaultState.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringBinding displayNameProperty() {
|
public StringBinding displayNameProperty() {
|
||||||
@@ -279,7 +251,7 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getAccessPoint() {
|
public String getAccessPoint() {
|
||||||
if (state.getValue() == VaultState.Value.UNLOCKED) {
|
if (state.get() == VaultState.UNLOCKED) {
|
||||||
assert volume != null;
|
assert volume != null;
|
||||||
return volume.getMountPoint().orElse(Path.of("")).toString();
|
return volume.getMountPoint().orElse(Path.of("")).toString();
|
||||||
} else {
|
} else {
|
||||||
@@ -327,12 +299,6 @@ public class Vault {
|
|||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnverifiedVaultConfig getUnverifiedVaultConfig() throws IOException {
|
|
||||||
Path configPath = getPath().resolve(org.cryptomator.common.Constants.VAULTCONFIG_FILENAME);
|
|
||||||
String token = Files.readString(configPath, StandardCharsets.US_ASCII);
|
|
||||||
return VaultConfig.decode(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable[] observables() {
|
public Observable[] observables() {
|
||||||
return new Observable[]{state};
|
return new Observable[]{state};
|
||||||
}
|
}
|
||||||
+1
-1
@@ -26,7 +26,7 @@ public interface VaultComponent {
|
|||||||
Builder vaultSettings(VaultSettings vaultSettings);
|
Builder vaultSettings(VaultSettings vaultSettings);
|
||||||
|
|
||||||
@BindsInstance
|
@BindsInstance
|
||||||
Builder initialVaultState(VaultState.Value vaultState);
|
Builder initialVaultState(VaultState vaultState);
|
||||||
|
|
||||||
@BindsInstance
|
@BindsInstance
|
||||||
Builder initialErrorCause(@Nullable @Named("lastKnownException") Exception initialErrorCause);
|
Builder initialErrorCause(@Nullable @Named("lastKnownException") Exception initialErrorCause);
|
||||||
+32
-35
@@ -11,7 +11,6 @@ package org.cryptomator.common.vaults;
|
|||||||
import org.cryptomator.common.settings.Settings;
|
import org.cryptomator.common.settings.Settings;
|
||||||
import org.cryptomator.common.settings.VaultSettings;
|
import org.cryptomator.common.settings.VaultSettings;
|
||||||
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
||||||
import org.cryptomator.cryptofs.DirStructure;
|
|
||||||
import org.cryptomator.cryptofs.migration.Migrators;
|
import org.cryptomator.cryptofs.migration.Migrators;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -21,51 +20,51 @@ import javax.inject.Singleton;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
|
||||||
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class VaultListManager {
|
public class VaultListManager {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
|
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
|
||||||
|
|
||||||
private final AutoLocker autoLocker;
|
|
||||||
private final VaultComponent.Builder vaultComponentBuilder;
|
private final VaultComponent.Builder vaultComponentBuilder;
|
||||||
private final ObservableList<Vault> vaultList;
|
private final ObservableList<Vault> vaultList;
|
||||||
private final String defaultVaultName;
|
private final String defaultVaultName;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) {
|
public VaultListManager(VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) {
|
||||||
this.vaultList = vaultList;
|
|
||||||
this.autoLocker = autoLocker;
|
|
||||||
this.vaultComponentBuilder = vaultComponentBuilder;
|
this.vaultComponentBuilder = vaultComponentBuilder;
|
||||||
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
|
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
|
||||||
|
this.vaultList = FXCollections.observableArrayList(Vault::observables);
|
||||||
|
|
||||||
addAll(settings.getDirectories());
|
addAll(settings.getDirectories());
|
||||||
vaultList.addListener(new VaultListChangeListener(settings.getDirectories()));
|
vaultList.addListener(new VaultListChangeListener(settings.getDirectories()));
|
||||||
autoLocker.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vault add(Path pathToVault) throws IOException {
|
public ObservableList<Vault> getVaultList() {
|
||||||
|
return vaultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vault add(Path pathToVault) throws NoSuchFileException {
|
||||||
Path normalizedPathToVault = pathToVault.normalize().toAbsolutePath();
|
Path normalizedPathToVault = pathToVault.normalize().toAbsolutePath();
|
||||||
if (CryptoFileSystemProvider.checkDirStructureForVault(normalizedPathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) == DirStructure.UNRELATED) {
|
if (!CryptoFileSystemProvider.containsVault(normalizedPathToVault, MASTERKEY_FILENAME)) {
|
||||||
throw new NoSuchFileException(normalizedPathToVault.toString(), null, "Not a vault directory");
|
throw new NoSuchFileException(normalizedPathToVault.toString(), null, "Not a vault directory");
|
||||||
}
|
}
|
||||||
|
Optional<Vault> alreadyExistingVault = get(normalizedPathToVault);
|
||||||
return get(normalizedPathToVault) //
|
if (alreadyExistingVault.isPresent()) {
|
||||||
.orElseGet(() -> {
|
return alreadyExistingVault.get();
|
||||||
Vault newVault = create(newVaultSettings(normalizedPathToVault));
|
} else {
|
||||||
vaultList.add(newVault);
|
Vault newVault = create(newVaultSettings(normalizedPathToVault));
|
||||||
return newVault;
|
vaultList.add(newVault);
|
||||||
});
|
return newVault;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private VaultSettings newVaultSettings(Path path) {
|
private VaultSettings newVaultSettings(Path path) {
|
||||||
@@ -95,45 +94,43 @@ public class VaultListManager {
|
|||||||
private Vault create(VaultSettings vaultSettings) {
|
private Vault create(VaultSettings vaultSettings) {
|
||||||
VaultComponent.Builder compBuilder = vaultComponentBuilder.vaultSettings(vaultSettings);
|
VaultComponent.Builder compBuilder = vaultComponentBuilder.vaultSettings(vaultSettings);
|
||||||
try {
|
try {
|
||||||
VaultState.Value vaultState = determineVaultState(vaultSettings.path().get());
|
VaultState vaultState = determineVaultState(vaultSettings.path().get());
|
||||||
compBuilder.initialVaultState(vaultState);
|
compBuilder.initialVaultState(vaultState);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Failed to determine vault state for " + vaultSettings.path().get(), e);
|
LOG.warn("Failed to determine vault state for " + vaultSettings.path().get(), e);
|
||||||
compBuilder.initialVaultState(ERROR);
|
compBuilder.initialVaultState(VaultState.ERROR);
|
||||||
compBuilder.initialErrorCause(e);
|
compBuilder.initialErrorCause(e);
|
||||||
}
|
}
|
||||||
return compBuilder.build().vault();
|
return compBuilder.build().vault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VaultState.Value redetermineVaultState(Vault vault) {
|
public static VaultState redetermineVaultState(Vault vault) {
|
||||||
VaultState state = vault.stateProperty();
|
VaultState previousState = vault.getState();
|
||||||
VaultState.Value previousState = state.getValue();
|
|
||||||
return switch (previousState) {
|
return switch (previousState) {
|
||||||
case LOCKED, NEEDS_MIGRATION, MISSING -> {
|
case LOCKED, NEEDS_MIGRATION, MISSING -> {
|
||||||
try {
|
try {
|
||||||
var determinedState = determineVaultState(vault.getPath());
|
VaultState determinedState = determineVaultState(vault.getPath());
|
||||||
state.set(determinedState);
|
vault.setState(determinedState);
|
||||||
yield determinedState;
|
yield determinedState;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Failed to determine vault state for " + vault.getPath(), e);
|
LOG.warn("Failed to determine vault state for " + vault.getPath(), e);
|
||||||
state.set(ERROR);
|
vault.setState(VaultState.ERROR);
|
||||||
vault.setLastKnownException(e);
|
vault.setLastKnownException(e);
|
||||||
yield ERROR;
|
yield VaultState.ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ERROR, UNLOCKED, PROCESSING -> previousState;
|
case ERROR, UNLOCKED, PROCESSING -> previousState;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VaultState.Value determineVaultState(Path pathToVault) throws IOException {
|
private static VaultState determineVaultState(Path pathToVault) throws IOException {
|
||||||
if (!Files.exists(pathToVault)) {
|
if (!CryptoFileSystemProvider.containsVault(pathToVault, MASTERKEY_FILENAME)) {
|
||||||
return VaultState.Value.MISSING;
|
return VaultState.MISSING;
|
||||||
|
} else if (Migrators.get().needsMigration(pathToVault, MASTERKEY_FILENAME)) {
|
||||||
|
return VaultState.NEEDS_MIGRATION;
|
||||||
|
} else {
|
||||||
|
return VaultState.LOCKED;
|
||||||
}
|
}
|
||||||
return switch (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME)) {
|
|
||||||
case VAULT -> VaultState.Value.LOCKED;
|
|
||||||
case UNRELATED -> VaultState.Value.MISSING;
|
|
||||||
case MAYBE_LEGACY -> Migrators.get().needsMigration(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) ? VaultState.Value.NEEDS_MIGRATION : VaultState.Value.MISSING;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+9
-1
@@ -40,6 +40,12 @@ public class VaultModule {
|
|||||||
return new AtomicReference<>();
|
return new AtomicReference<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@PerVault
|
||||||
|
public ObjectProperty<VaultState> provideVaultState(VaultState initialState) {
|
||||||
|
return new SimpleObjectProperty<>(initialState);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Named("lastKnownException")
|
@Named("lastKnownException")
|
||||||
@PerVault
|
@PerVault
|
||||||
@@ -47,6 +53,7 @@ public class VaultModule {
|
|||||||
return new SimpleObjectProperty<>(initialErrorCause);
|
return new SimpleObjectProperty<>(initialErrorCause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) {
|
public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) {
|
||||||
VolumeImpl preferredImpl = settings.preferredVolumeImpl().get();
|
VolumeImpl preferredImpl = settings.preferredVolumeImpl().get();
|
||||||
@@ -98,6 +105,7 @@ public class VaultModule {
|
|||||||
flags.append(" -oatomic_o_trunc");
|
flags.append(" -oatomic_o_trunc");
|
||||||
flags.append(" -oauto_xattr");
|
flags.append(" -oauto_xattr");
|
||||||
flags.append(" -oauto_cache");
|
flags.append(" -oauto_cache");
|
||||||
|
flags.append(" -omodules=iconv,from_code=UTF-8,to_code=UTF-8-MAC"); // show files names in Unicode NFD encoding
|
||||||
flags.append(" -onoappledouble"); // vastly impacts performance for some reason...
|
flags.append(" -onoappledouble"); // vastly impacts performance for some reason...
|
||||||
flags.append(" -odefault_permissions"); // let the kernel assume permissions based on file attributes etc
|
flags.append(" -odefault_permissions"); // let the kernel assume permissions based on file attributes etc
|
||||||
|
|
||||||
@@ -138,7 +146,7 @@ public class VaultModule {
|
|||||||
|
|
||||||
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse_main.c#L53-L62 for syntax guide
|
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse_main.c#L53-L62 for syntax guide
|
||||||
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse.c#L295-L319 for options (-o <...>)
|
// see https://github.com/billziss-gh/winfsp/blob/5d0b10d0b643652c00ebb4704dc2bb28e7244973/src/dll/fuse/fuse.c#L295-L319 for options (-o <...>)
|
||||||
// see https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions/5ba00e4be4f5e938eaae6ef1500b331de12dee77 (FUSE 4.) on why the given defaults were chosen
|
// see https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions/5ba00e4be4f5e938eaae6ef1500b331de12dee77 (FUSE 4.) on why the given defaults were choosen
|
||||||
private String getWindowsFuseDefaultMountFlags(StringBinding mountName, ReadOnlyBooleanProperty readOnly) {
|
private String getWindowsFuseDefaultMountFlags(StringBinding mountName, ReadOnlyBooleanProperty readOnly) {
|
||||||
assert SystemUtils.IS_OS_WINDOWS;
|
assert SystemUtils.IS_OS_WINDOWS;
|
||||||
StringBuilder flags = new StringBuilder();
|
StringBuilder flags = new StringBuilder();
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.cryptomator.common.vaults;
|
||||||
|
|
||||||
|
public enum VaultState {
|
||||||
|
/**
|
||||||
|
* No vault found at the provided path
|
||||||
|
*/
|
||||||
|
MISSING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault requires migration to a newer vault format
|
||||||
|
*/
|
||||||
|
NEEDS_MIGRATION,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault ready to be unlocked
|
||||||
|
*/
|
||||||
|
LOCKED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault in transition between two other states
|
||||||
|
*/
|
||||||
|
PROCESSING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault is unlocked
|
||||||
|
*/
|
||||||
|
UNLOCKED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unknown state due to preceeding unrecoverable exceptions.
|
||||||
|
*/
|
||||||
|
ERROR;
|
||||||
|
|
||||||
|
}
|
||||||
+14
-34
@@ -13,11 +13,9 @@ import javafx.beans.property.LongProperty;
|
|||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.beans.property.SimpleLongProperty;
|
import javafx.beans.property.SimpleLongProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
import javafx.concurrent.ScheduledService;
|
import javafx.concurrent.ScheduledService;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
@@ -28,23 +26,22 @@ public class VaultStats {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(VaultStats.class);
|
private static final Logger LOG = LoggerFactory.getLogger(VaultStats.class);
|
||||||
|
|
||||||
private final AtomicReference<CryptoFileSystem> fs;
|
private final AtomicReference<CryptoFileSystem> fs;
|
||||||
private final VaultState state;
|
private final ObjectProperty<VaultState> state;
|
||||||
private final ScheduledService<Optional<CryptoFileSystemStats>> updateService;
|
private final ScheduledService<Optional<CryptoFileSystemStats>> updateService;
|
||||||
private final LongProperty bytesPerSecondRead = new SimpleLongProperty();
|
private final LongProperty bytesPerSecondRead = new SimpleLongProperty();
|
||||||
private final LongProperty bytesPerSecondWritten = new SimpleLongProperty();
|
private final LongProperty bytesPerSecondWritten = new SimpleLongProperty();
|
||||||
private final LongProperty bytesPerSecondEncrypted = new SimpleLongProperty();
|
private final LongProperty bytesPerSecondEncrypted = new SimpleLongProperty();
|
||||||
private final LongProperty bytesPerSecondDecrypted = new SimpleLongProperty();
|
private final LongProperty bytesPerSecondDecrypted = new SimpleLongProperty();
|
||||||
private final DoubleProperty cacheHitRate = new SimpleDoubleProperty();
|
private final DoubleProperty cacheHitRate = new SimpleDoubleProperty();
|
||||||
private final LongProperty totalBytesRead = new SimpleLongProperty();
|
private final LongProperty toalBytesRead = new SimpleLongProperty();
|
||||||
private final LongProperty totalBytesWritten = new SimpleLongProperty();
|
private final LongProperty toalBytesWritten = new SimpleLongProperty();
|
||||||
private final LongProperty totalBytesEncrypted = new SimpleLongProperty();
|
private final LongProperty totalBytesEncrypted = new SimpleLongProperty();
|
||||||
private final LongProperty totalBytesDecrypted = new SimpleLongProperty();
|
private final LongProperty totalBytesDecrypted = new SimpleLongProperty();
|
||||||
private final LongProperty filesRead = new SimpleLongProperty();
|
private final LongProperty filesRead = new SimpleLongProperty();
|
||||||
private final LongProperty filesWritten = new SimpleLongProperty();
|
private final LongProperty filesWritten = new SimpleLongProperty();
|
||||||
private final ObjectProperty<Instant> lastActivity = new SimpleObjectProperty<>();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VaultStats(AtomicReference<CryptoFileSystem> fs, VaultState state, ExecutorService executor) {
|
VaultStats(AtomicReference<CryptoFileSystem> fs, ObjectProperty<VaultState> state, ExecutorService executor) {
|
||||||
this.fs = fs;
|
this.fs = fs;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.updateService = new UpdateStatsService();
|
this.updateService = new UpdateStatsService();
|
||||||
@@ -55,16 +52,13 @@ public class VaultStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void vaultStateChanged(@SuppressWarnings("unused") Observable observable) {
|
private void vaultStateChanged(@SuppressWarnings("unused") Observable observable) {
|
||||||
if (VaultState.Value.UNLOCKED == state.get()) {
|
if (VaultState.UNLOCKED.equals(state.get())) {
|
||||||
assert fs.get() != null;
|
assert fs.get() != null;
|
||||||
LOG.debug("start recording stats");
|
LOG.debug("start recording stats");
|
||||||
Platform.runLater(() -> {
|
updateService.restart();
|
||||||
lastActivity.set(Instant.now());
|
|
||||||
updateService.restart();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("stop recording stats");
|
LOG.debug("stop recording stats");
|
||||||
Platform.runLater(() -> updateService.cancel());
|
updateService.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,19 +69,13 @@ public class VaultStats {
|
|||||||
cacheHitRate.set(stats.map(this::getCacheHitRate).orElse(0.0));
|
cacheHitRate.set(stats.map(this::getCacheHitRate).orElse(0.0));
|
||||||
bytesPerSecondDecrypted.set(stats.map(CryptoFileSystemStats::pollBytesDecrypted).orElse(0L));
|
bytesPerSecondDecrypted.set(stats.map(CryptoFileSystemStats::pollBytesDecrypted).orElse(0L));
|
||||||
bytesPerSecondEncrypted.set(stats.map(CryptoFileSystemStats::pollBytesEncrypted).orElse(0L));
|
bytesPerSecondEncrypted.set(stats.map(CryptoFileSystemStats::pollBytesEncrypted).orElse(0L));
|
||||||
totalBytesRead.set(stats.map(CryptoFileSystemStats::pollTotalBytesRead).orElse(0L));
|
toalBytesRead.set(stats.map(CryptoFileSystemStats::pollTotalBytesRead).orElse(0L));
|
||||||
totalBytesWritten.set(stats.map(CryptoFileSystemStats::pollTotalBytesWritten).orElse(0L));
|
toalBytesWritten.set(stats.map(CryptoFileSystemStats::pollTotalBytesWritten).orElse(0L));
|
||||||
totalBytesEncrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesEncrypted).orElse(0L));
|
totalBytesEncrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesEncrypted).orElse(0L));
|
||||||
totalBytesDecrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesDecrypted).orElse(0L));
|
totalBytesDecrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesDecrypted).orElse(0L));
|
||||||
var oldAccessCount = filesRead.get() + filesWritten.get();
|
|
||||||
filesRead.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesRead).orElse(0L));
|
filesRead.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesRead).orElse(0L));
|
||||||
filesWritten.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesWritten).orElse(0L));
|
filesWritten.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesWritten).orElse(0L));
|
||||||
var newAccessCount = filesRead.get() + filesWritten.get();
|
|
||||||
|
|
||||||
// check for any I/O activity
|
|
||||||
if (newAccessCount > oldAccessCount) {
|
|
||||||
lastActivity.set(Instant.now());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getCacheHitRate(CryptoFileSystemStats stats) {
|
private double getCacheHitRate(CryptoFileSystemStats stats) {
|
||||||
@@ -146,7 +134,7 @@ public class VaultStats {
|
|||||||
return bytesPerSecondEncrypted;
|
return bytesPerSecondEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getBytesPerSecondEncrypted() {
|
public long getBytesPerSecondEnrypted() {
|
||||||
return bytesPerSecondEncrypted.get();
|
return bytesPerSecondEncrypted.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,13 +152,13 @@ public class VaultStats {
|
|||||||
return cacheHitRate.get();
|
return cacheHitRate.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LongProperty totalBytesReadProperty() {return totalBytesRead;}
|
public LongProperty toalBytesReadProperty() {return toalBytesRead;}
|
||||||
|
|
||||||
public long getTotalBytesRead() { return totalBytesRead.get();}
|
public long getTotalBytesRead() { return toalBytesRead.get();}
|
||||||
|
|
||||||
public LongProperty totalBytesWrittenProperty() {return totalBytesWritten;}
|
public LongProperty toalBytesWrittenProperty() {return toalBytesWritten;}
|
||||||
|
|
||||||
public long getTotalBytesWritten() { return totalBytesWritten.get();}
|
public long getTotalBytesWritten() { return toalBytesWritten.get();}
|
||||||
|
|
||||||
public LongProperty totalBytesEncryptedProperty() {return totalBytesEncrypted;}
|
public LongProperty totalBytesEncryptedProperty() {return totalBytesEncrypted;}
|
||||||
|
|
||||||
@@ -187,12 +175,4 @@ public class VaultStats {
|
|||||||
public LongProperty filesWritten() {return filesWritten;}
|
public LongProperty filesWritten() {return filesWritten;}
|
||||||
|
|
||||||
public long getFilesWritten() {return filesWritten.get();}
|
public long getFilesWritten() {return filesWritten.get();}
|
||||||
|
|
||||||
public ObjectProperty<Instant> lastActivityProperty() {
|
|
||||||
return lastActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instant getLastActivity() {
|
|
||||||
return lastActivity.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+3
-5
@@ -7,12 +7,10 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletionStage;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a Volume and uses it to mount an unlocked vault
|
* Takes a Volume and usess it to mount an unlocked vault
|
||||||
*/
|
*/
|
||||||
public interface Volume {
|
public interface Volume {
|
||||||
|
|
||||||
@@ -24,7 +22,7 @@ public interface Volume {
|
|||||||
boolean isSupported();
|
boolean isSupported();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the corresponding enum type of the {@link VolumeImpl volume implementation ("VolumeImpl")} that is implemented by this Volume.
|
* Gets the coresponding enum type of the {@link VolumeImpl volume implementation ("VolumeImpl")} that is implemented by this Volume.
|
||||||
*
|
*
|
||||||
* @return the type of implementation as defined by the {@link VolumeImpl VolumeImpl enum}
|
* @return the type of implementation as defined by the {@link VolumeImpl VolumeImpl enum}
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +32,7 @@ public interface Volume {
|
|||||||
* @param fs
|
* @param fs
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws IOException, VolumeException, InvalidMountPointException;
|
void mount(CryptoFileSystem fs, String mountFlags) throws IOException, VolumeException, InvalidMountPointException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reveals the mounted volume.
|
* Reveals the mounted volume.
|
||||||
+4
-9
@@ -17,7 +17,6 @@ import java.net.InetAddress;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class WebDavVolume implements Volume {
|
public class WebDavVolume implements Volume {
|
||||||
@@ -32,7 +31,6 @@ public class WebDavVolume implements Volume {
|
|||||||
private WebDavServer server;
|
private WebDavServer server;
|
||||||
private WebDavServletController servlet;
|
private WebDavServletController servlet;
|
||||||
private Mounter.Mount mount;
|
private Mounter.Mount mount;
|
||||||
private Consumer<Throwable> onExitAction;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public WebDavVolume(Provider<WebDavServer> serverProvider, VaultSettings vaultSettings, Settings settings, WindowsDriveLetters windowsDriveLetters) {
|
public WebDavVolume(Provider<WebDavServer> serverProvider, VaultSettings vaultSettings, Settings settings, WindowsDriveLetters windowsDriveLetters) {
|
||||||
@@ -43,13 +41,12 @@ public class WebDavVolume implements Volume {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mount(CryptoFileSystem fs, String mountFlags, Consumer<Throwable> onExitAction) throws VolumeException {
|
public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException {
|
||||||
startServlet(fs);
|
startServlet(fs);
|
||||||
mountServlet();
|
mountServlet();
|
||||||
this.onExitAction = onExitAction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startServlet(CryptoFileSystem fs) {
|
private void startServlet(CryptoFileSystem fs){
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
server = serverProvider.get();
|
server = serverProvider.get();
|
||||||
}
|
}
|
||||||
@@ -67,9 +64,9 @@ public class WebDavVolume implements Volume {
|
|||||||
throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
|
throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//on windows, prevent an automatic drive letter selection in the upstream library. Either we choose already a specific one or there is no free.
|
//on windows, prevent an automatic drive letter selection in the upstream library. Either we choose already a specifc one or there is no free.
|
||||||
Supplier<String> driveLetterSupplier;
|
Supplier<String> driveLetterSupplier;
|
||||||
if (System.getProperty("os.name").toLowerCase().contains("windows") && vaultSettings.winDriveLetter().isEmpty().get()) {
|
if(System.getProperty("os.name").toLowerCase().contains("windows") && vaultSettings.winDriveLetter().isEmpty().get()) {
|
||||||
driveLetterSupplier = () -> windowsDriveLetters.getAvailableDriveLetter().orElse(null);
|
driveLetterSupplier = () -> windowsDriveLetters.getAvailableDriveLetter().orElse(null);
|
||||||
} else {
|
} else {
|
||||||
driveLetterSupplier = () -> vaultSettings.winDriveLetter().get();
|
driveLetterSupplier = () -> vaultSettings.winDriveLetter().get();
|
||||||
@@ -104,7 +101,6 @@ public class WebDavVolume implements Volume {
|
|||||||
throw new VolumeException(e);
|
throw new VolumeException(e);
|
||||||
}
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
onExitAction.accept(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,7 +111,6 @@ public class WebDavVolume implements Volume {
|
|||||||
throw new VolumeException(e);
|
throw new VolumeException(e);
|
||||||
}
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
onExitAction.accept(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+3
-3
@@ -17,12 +17,12 @@ import java.util.Optional;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@DisplayName("Environment Variables Test")
|
@DisplayName("Environment Variables Test")
|
||||||
public class EnvironmentTest {
|
class EnvironmentTest {
|
||||||
|
|
||||||
private Environment env;
|
private Environment env;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void init() {
|
void init() {
|
||||||
env = Mockito.spy(new Environment());
|
env = Mockito.spy(new Environment());
|
||||||
Mockito.when(env.getHomeDir()).thenReturn(Path.of("/home/testuser"));
|
Mockito.when(env.getHomeDir()).thenReturn(Path.of("/home/testuser"));
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ public class EnvironmentTest {
|
|||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Path Lists")
|
@DisplayName("Path Lists")
|
||||||
public class SettingsPath {
|
class SettingsPath {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("test.path.property=")
|
@DisplayName("test.path.property=")
|
||||||
+1
-6
@@ -7,9 +7,8 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class LicenseCheckerTest {
|
class LicenseCheckerTest {
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
private static final String PUBLIC_KEY = """
|
private static final String PUBLIC_KEY = """
|
||||||
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
|
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
|
||||||
PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
|
PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
|
||||||
@@ -26,7 +25,6 @@ public class LicenseCheckerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckValidLicense() {
|
public void testCheckValidLicense() {
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
||||||
|
|
||||||
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
||||||
@@ -37,7 +35,6 @@ public class LicenseCheckerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckInvalidLicenseHeader() {
|
public void testCheckInvalidLicenseHeader() {
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
String license = "EyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
String license = "EyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
||||||
|
|
||||||
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
||||||
@@ -47,7 +44,6 @@ public class LicenseCheckerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckInvalidLicensePayload() {
|
public void testCheckInvalidLicensePayload() {
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.EyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.EyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
||||||
|
|
||||||
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
||||||
@@ -57,7 +53,6 @@ public class LicenseCheckerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckInvalidLicenseSignature() {
|
public void testCheckInvalidLicenseSignature() {
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.aQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.aQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
|
||||||
|
|
||||||
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
Optional<DecodedJWT> decoded = licenseChecker.check(license);
|
||||||
-1
@@ -44,7 +44,6 @@ public class SettingsJsonAdapterTest {
|
|||||||
Assertions.assertEquals(VolumeImpl.FUSE, settings.preferredVolumeImpl().get());
|
Assertions.assertEquals(VolumeImpl.FUSE, settings.preferredVolumeImpl().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
@ParameterizedTest(name = "fromJson() should throw IOException for input: {0}")
|
@ParameterizedTest(name = "fromJson() should throw IOException for input: {0}")
|
||||||
@ValueSource(strings = { //
|
@ValueSource(strings = { //
|
||||||
"", //
|
"", //
|
||||||
+19
-26
@@ -7,6 +7,9 @@ package org.cryptomator.common.settings;
|
|||||||
|
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -14,11 +17,6 @@ import java.io.StringReader;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
public class VaultSettingsJsonAdapterTest {
|
public class VaultSettingsJsonAdapterTest {
|
||||||
|
|
||||||
private final VaultSettingsJsonAdapter adapter = new VaultSettingsJsonAdapter();
|
private final VaultSettingsJsonAdapter adapter = new VaultSettingsJsonAdapter();
|
||||||
@@ -29,18 +27,16 @@ public class VaultSettingsJsonAdapterTest {
|
|||||||
JsonReader jsonReader = new JsonReader(new StringReader(json));
|
JsonReader jsonReader = new JsonReader(new StringReader(json));
|
||||||
|
|
||||||
VaultSettings vaultSettings = adapter.read(jsonReader);
|
VaultSettings vaultSettings = adapter.read(jsonReader);
|
||||||
|
Assertions.assertEquals("foo", vaultSettings.getId());
|
||||||
|
Assertions.assertEquals(Paths.get("/foo/bar"), vaultSettings.path().get());
|
||||||
|
Assertions.assertEquals("test", vaultSettings.displayName().get());
|
||||||
|
Assertions.assertEquals("X", vaultSettings.winDriveLetter().get());
|
||||||
|
Assertions.assertEquals("/home/test/crypto", vaultSettings.customMountPath().get());
|
||||||
|
Assertions.assertEquals("--foo --bar", vaultSettings.mountFlags().get());
|
||||||
|
|
||||||
|
|
||||||
assertAll(
|
|
||||||
() -> assertEquals("foo", vaultSettings.getId()),
|
|
||||||
() -> assertEquals(Paths.get("/foo/bar"), vaultSettings.path().get()),
|
|
||||||
() -> assertEquals("test", vaultSettings.displayName().get()),
|
|
||||||
() -> assertEquals("X", vaultSettings.winDriveLetter().get()),
|
|
||||||
() -> assertEquals("/home/test/crypto", vaultSettings.customMountPath().get()),
|
|
||||||
() -> assertEquals("--foo --bar", vaultSettings.mountFlags().get())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerialize() throws IOException {
|
public void testSerialize() throws IOException {
|
||||||
VaultSettings vaultSettings = new VaultSettings("test");
|
VaultSettings vaultSettings = new VaultSettings("test");
|
||||||
@@ -53,17 +49,14 @@ public class VaultSettingsJsonAdapterTest {
|
|||||||
adapter.write(jsonWriter, vaultSettings);
|
adapter.write(jsonWriter, vaultSettings);
|
||||||
String result = buf.toString();
|
String result = buf.toString();
|
||||||
|
|
||||||
assertAll(
|
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"id\":\"test\""));
|
||||||
() -> assertThat(result, containsString("\"id\":\"test\"")),
|
if (System.getProperty("os.name").contains("Windows")) {
|
||||||
() -> {
|
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"\\\\foo\\\\bar\""));
|
||||||
if (System.getProperty("os.name").contains("Windows")) {
|
} else {
|
||||||
assertThat(result, containsString("\"path\":\"\\\\foo\\\\bar\""));
|
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\""));
|
||||||
} else {
|
}
|
||||||
assertThat(result, containsString("\"path\":\"/foo/bar\""));
|
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"displayName\":\"mountyMcMountFace\""));
|
||||||
}
|
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":\"--foo --bar\""));
|
||||||
},
|
|
||||||
() -> assertThat(result, containsString("\"displayName\":\"mountyMcMountFace\"")),
|
|
||||||
() -> assertThat(result, containsString("\"mountFlags\":\"--foo --bar\""))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>main</artifactId>
|
||||||
|
<version>1.6.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>launcher</artifactId>
|
||||||
|
<name>Cryptomator Launcher</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>commons</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>ui</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Libs -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DI -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.dagger</groupId>
|
||||||
|
<artifactId>dagger</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
+2
-2
@@ -11,12 +11,12 @@ import java.io.File;
|
|||||||
*
|
*
|
||||||
* @param <E> Event type the policy possibly reacts to
|
* @param <E> Event type the policy possibly reacts to
|
||||||
*/
|
*/
|
||||||
public class LaunchAndSizeBasedTriggeringPolicy<E> extends TriggeringPolicyBase<E> {
|
public class LaunchAndSizeBasedTriggerinPolicy<E> extends TriggeringPolicyBase<E> {
|
||||||
|
|
||||||
LaunchBasedTriggeringPolicy<E> launchBasedTriggeringPolicy;
|
LaunchBasedTriggeringPolicy<E> launchBasedTriggeringPolicy;
|
||||||
SizeBasedTriggeringPolicy<E> sizeBasedTriggeringPolicy;
|
SizeBasedTriggeringPolicy<E> sizeBasedTriggeringPolicy;
|
||||||
|
|
||||||
public LaunchAndSizeBasedTriggeringPolicy(FileSize threshold) {
|
public LaunchAndSizeBasedTriggerinPolicy(FileSize threshold) {
|
||||||
this.launchBasedTriggeringPolicy = new LaunchBasedTriggeringPolicy<>();
|
this.launchBasedTriggeringPolicy = new LaunchBasedTriggeringPolicy<>();
|
||||||
this.sizeBasedTriggeringPolicy = new SizeBasedTriggeringPolicy<>();
|
this.sizeBasedTriggeringPolicy = new SizeBasedTriggeringPolicy<>();
|
||||||
sizeBasedTriggeringPolicy.setMaxFileSize(threshold);
|
sizeBasedTriggeringPolicy.setMaxFileSize(threshold);
|
||||||
+1
-1
@@ -85,7 +85,7 @@ public class LoggerModule {
|
|||||||
appender.setContext(context);
|
appender.setContext(context);
|
||||||
appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
|
appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
|
||||||
appender.setEncoder(encoder);
|
appender.setEncoder(encoder);
|
||||||
LaunchAndSizeBasedTriggeringPolicy triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy(FileSize.valueOf(LOG_MAX_SIZE));
|
LaunchAndSizeBasedTriggerinPolicy triggeringPolicy = new LaunchAndSizeBasedTriggerinPolicy(FileSize.valueOf(LOG_MAX_SIZE));
|
||||||
triggeringPolicy.setContext(context);
|
triggeringPolicy.setContext(context);
|
||||||
triggeringPolicy.start();
|
triggeringPolicy.start();
|
||||||
appender.setTriggeringPolicy(triggeringPolicy);
|
appender.setTriggeringPolicy(triggeringPolicy);
|
||||||
+1
-1
@@ -24,7 +24,7 @@ public class IpcFactoryTest {
|
|||||||
private IpcProtocolImpl protocolHandler = Mockito.mock(IpcProtocolImpl.class);
|
private IpcProtocolImpl protocolHandler = Mockito.mock(IpcProtocolImpl.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Without IPC port files")
|
@DisplayName("Wihout IPC port files")
|
||||||
public void testNoIpcWithoutPortFile() throws IOException {
|
public void testNoIpcWithoutPortFile() throws IOException {
|
||||||
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
|
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user