Merge remote-tracking branch 'origin/master' into encrypted-export
This commit is contained in:
@@ -4,6 +4,7 @@ python copy OpenKeychain action white search 24
|
|||||||
python copy OpenKeychain navigation white arrow_back 24
|
python copy OpenKeychain navigation white arrow_back 24
|
||||||
python copy OpenKeychain navigation white close 24
|
python copy OpenKeychain navigation white close 24
|
||||||
python copy OpenKeychain navigation white check 24
|
python copy OpenKeychain navigation white check 24
|
||||||
|
python copy OpenKeychain navigation black check 24
|
||||||
python copy OpenKeychain navigation black expand_less 24
|
python copy OpenKeychain navigation black expand_less 24
|
||||||
python copy OpenKeychain navigation black expand_more 24
|
python copy OpenKeychain navigation black expand_more 24
|
||||||
python copy OpenKeychain navigation white refresh 24
|
python copy OpenKeychain navigation white refresh 24
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ dependencies {
|
|||||||
compile 'com.mikepenz.iconics:meteocons-typeface:1.1.1@aar'
|
compile 'com.mikepenz.iconics:meteocons-typeface:1.1.1@aar'
|
||||||
compile 'com.mikepenz.iconics:community-material-typeface:1.0.0@aar'
|
compile 'com.mikepenz.iconics:community-material-typeface:1.0.0@aar'
|
||||||
compile 'com.nispok:snackbar:2.11.0'
|
compile 'com.nispok:snackbar:2.11.0'
|
||||||
compile 'com.squareup.okhttp:okhttp:2.4.0'
|
compile 'com.squareup.okhttp:okhttp:2.5.0'
|
||||||
|
compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0'
|
||||||
compile 'org.apache.james:apache-mime4j-core:0.7.2'
|
compile 'org.apache.james:apache-mime4j-core:0.7.2'
|
||||||
compile 'org.apache.james:apache-mime4j-dom:0.7.2'
|
compile 'org.apache.james:apache-mime4j-dom:0.7.2'
|
||||||
compile 'org.thoughtcrime.ssl.pinning:AndroidPinning:1.0.0'
|
compile 'org.thoughtcrime.ssl.pinning:AndroidPinning:1.0.0'
|
||||||
@@ -91,31 +92,38 @@ dependencyVerification {
|
|||||||
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
||||||
'com.getbase:floatingactionbutton:052aa2a94e49e5dccc97cb99f2add87e8698b84859f0e3ac181100c0bc7640ca',
|
'com.getbase:floatingactionbutton:052aa2a94e49e5dccc97cb99f2add87e8698b84859f0e3ac181100c0bc7640ca',
|
||||||
'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13',
|
'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13',
|
||||||
|
'org.ocpsoft.prettytime:prettytime:a6bc2641b3ab7873df604b77b6680c75b86d98e78afefb367940972f925591b5',
|
||||||
'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb',
|
'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb',
|
||||||
'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4',
|
'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4',
|
||||||
'org.sufficientlysecure:html-textview:1d3bed31ef837437154de8d2362a0e6b0e59b6c3535d87ee48c2fab12c84f9bb',
|
|
||||||
'com.mikepenz:iconics:c1a02203d8e0d638959463c00af3ab9096e0a7c1ad5928762eb10ef5ce8a63cd',
|
|
||||||
'com.mikepenz:materialdrawer:70c3efb3842461db41df6a918ea93969a7da21e63c092be838b153e5a47a17bf',
|
'com.mikepenz:materialdrawer:70c3efb3842461db41df6a918ea93969a7da21e63c092be838b153e5a47a17bf',
|
||||||
'com.mikepenz.iconics:meteocons-typeface:39a8a9e70cd8287cdb119af57a672a41dd09240dba6697f5a0dbda1ccc33298b',
|
'org.sufficientlysecure:html-textview:1d3bed31ef837437154de8d2362a0e6b0e59b6c3535d87ee48c2fab12c84f9bb',
|
||||||
'com.mikepenz.iconics:octicons-typeface:67ed7d456a9ce5f5307b85f955797bfb3dd674e2f6defb31c6b8bbe2ede290be',
|
'com.mikepenz.iconics:octicons-typeface:67ed7d456a9ce5f5307b85f955797bfb3dd674e2f6defb31c6b8bbe2ede290be',
|
||||||
'com.nispok:snackbar:46b5eb9d630d329e13c2ce00ee9fb115ffb66c23c72cff32ee97eedd76824c6f',
|
'com.mikepenz:iconics:c1a02203d8e0d638959463c00af3ab9096e0a7c1ad5928762eb10ef5ce8a63cd',
|
||||||
'com.mikepenz.iconics:community-material-typeface:f1c5afee5f0f10d66beb3ed0df977246a02a9c46de4e05d7c0264bcde53b6b7f',
|
'com.mikepenz.iconics:community-material-typeface:f1c5afee5f0f10d66beb3ed0df977246a02a9c46de4e05d7c0264bcde53b6b7f',
|
||||||
'com.squareup.okhttp:okhttp:bc0da7ac1f5441619faa2082811938acf7df97e4a8e08f0e043ff4937414d5ad',
|
'com.mikepenz.iconics:meteocons-typeface:39a8a9e70cd8287cdb119af57a672a41dd09240dba6697f5a0dbda1ccc33298b',
|
||||||
// 'OpenKeychain.extern.openkeychain-api-lib:openkeychain-intents:111d7d53b9e920ad3405f8f3eb0ab7bd3aee66d577442452754b83c7c1c1d49a',
|
'com.squareup.okhttp:okhttp:1cc716e29539adcda677949508162796daffedb4794cbf947a6f65e696f0381c',
|
||||||
// 'OpenKeychain.extern.openpgp-api-lib:openpgp-api:544b7b2e20955556b83d1b72763543aa789836ebc1e77b332ed7cd83ef765c4a',
|
'com.nispok:snackbar:46b5eb9d630d329e13c2ce00ee9fb115ffb66c23c72cff32ee97eedd76824c6f',
|
||||||
// 'com.madgag.spongycastle:core:97276487be598747ba78c063c90cea7fc3c7ad9bc7aeba03c0b9c98692052b8a',
|
'org.apache.james:apache-mime4j-core:4d7434c68f94b81a253c12f28e6bbb4d6239c361d6086a46e22e594bb43ac660',
|
||||||
// 'com.madgag.spongycastle:pkix:979aa4b2aaef94866e0f97b05b1922244eaf8b650f3691a3c44760ff0a41562b',
|
'com.squareup.okhttp:okhttp-urlconnection:79ec6f4e79e683105e87fe83278a531c693e538d30e3b9237000ce7c94fcb2cf',
|
||||||
// 'com.madgag.spongycastle:pg:da319de706d946f178140959c74aec126f7803f1104dbad89bb1f55a53f6e1a9',
|
'org.thoughtcrime.ssl.pinning:AndroidPinning:afa1d74e699257fa75cb109ff29bac50726ef269c6e306bdeffe8223cee06ef4',
|
||||||
// 'OpenKeychain.extern:minidns:8274d50124d9584e95df0c5da7798269ac9caf0eab560df929c2c658ca624037',
|
'org.apache.james:apache-mime4j-dom:7e6b06ee164a1c21b7e477249ea0b74a18fddce44764e5764085f58dd8c34633',
|
||||||
// 'com.madgag.spongycastle:prov:902a484219bbf4e395a1c32da65b2453133e195bcc92336dc8c33b7c58edcd60',
|
// 'OpenKeychain.extern.openpgp-api-lib:openpgp-api:a3f8b2ed40aaf12169e2a4e1f25e3764aa5ccb430683e1e7ca7867471eaf2bba',
|
||||||
|
'com.cocosw:bottomsheet:871f5f4d6c10936569caf3528271efd77594a67aa5511765c96d7096c9b05f96',
|
||||||
|
// 'OpenKeychain.extern.spongycastle:core:6006a83fa427f4e5c8c93458176ab5e3b54d8dba7942171cb76cb134fc574c58',
|
||||||
|
// 'OpenKeychain.extern.openkeychain-api-lib:openkeychain-intents:8582442aa26e13c5a4bdf3588a22cb94b2fa5de6c79b84244fb575aa401fc330',
|
||||||
|
// 'OpenKeychain.extern.spongycastle:pg:0fd64a60311c5557f230bec9b2b162c9e6e690ccc83ac6b5af6a8d616309da98',
|
||||||
|
// 'OpenKeychain.extern.spongycastle:pkix:2348474aa27cb0461a368191d4d8fe7479a212b6365b177da131f4efa4c57f24',
|
||||||
|
// 'OpenKeychain.extern.spongycastle:prov:85c9ed6e24c5c7e5f7ff7c22d367bb553d020693350bd1c75555e6895311bb69',
|
||||||
|
// 'OpenKeychain.extern.safeslinger-exchange:safeslinger-exchange:274b71f8a1c383fb506342fd0f614b4a0cdb25517b5b2a1dfef9a4a2575477ed',
|
||||||
'com.android.support:support-annotations:beac5cae60bdb597df9af9c916f785c2f71f8c8ae4be9a32d4298dea85496a42',
|
'com.android.support:support-annotations:beac5cae60bdb597df9af9c916f785c2f71f8c8ae4be9a32d4298dea85496a42',
|
||||||
// 'OpenKeychain.extern.KeybaseLib:Lib:d52e7888cea6de9e077501bb533270b2a86b52cb8af49e5f44ee8c4bb19ea017',
|
// 'OpenKeychain.extern:minidns:25e351fa4145e2a9b0a76658c48619b307f71432db7492e9e8a6b34aa2e9bdcf',
|
||||||
// 'OpenKeychain.extern.safeslinger-exchange:safeslinger-exchange:76e5da6b4f5f8835b12649e17569f0d0d8d89552815a61383c128545632689d1',
|
// 'OpenKeychain.extern.KeybaseLib:Lib:79c78c1054b58200028211e21f2c89012dc4a1eafdb00cc99a5ce1f61ad16937',
|
||||||
'com.squareup.okio:okio:b53c1760864e1c39b5275d9023e2a6fbe8f3189e6e67b4c87877b8ec8f92e05a',
|
'com.squareup.okio:okio:114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||||
|
|||||||
@@ -263,9 +263,7 @@
|
|||||||
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT_DATA" />
|
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT_DATA" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
<data android:scheme="file" />
|
|
||||||
<data android:scheme="content" />
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<!-- DECRYPT_TEXT -->
|
<!-- DECRYPT_TEXT -->
|
||||||
|
|||||||
38
OpenKeychain/src/main/assets/api.keybase.io.CA.cer
Normal file
38
OpenKeychain/src/main/assets/api.keybase.io.CA.cer
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGmzCCBIOgAwIBAgIJAPzhpcIBaOeNMA0GCSqGSIb3DQEBBQUAMIGPMQswCQYD
|
||||||
|
VQQGEwJVUzELMAkGA1UECBMCTlkxETAPBgNVBAcTCE5ldyBZb3JrMRQwEgYDVQQK
|
||||||
|
EwtLZXliYXNlIExMQzEXMBUGA1UECxMOQ2VydCBBdXRob3JpdHkxEzARBgNVBAMT
|
||||||
|
CmtleWJhc2UuaW8xHDAaBgkqhkiG9w0BCQEWDWNhQGtleWJhc2UuaW8wHhcNMTQw
|
||||||
|
MTAyMTY0MjMzWhcNMjMxMjMxMTY0MjMzWjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV
|
||||||
|
BAgTAk5ZMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UEChMLS2V5YmFzZSBMTEMx
|
||||||
|
FzAVBgNVBAsTDkNlcnQgQXV0aG9yaXR5MRMwEQYDVQQDEwprZXliYXNlLmlvMRww
|
||||||
|
GgYJKoZIhvcNAQkBFg1jYUBrZXliYXNlLmlvMIICIjANBgkqhkiG9w0BAQEFAAOC
|
||||||
|
Ag8AMIICCgKCAgEA3sLA6ZG8uOvmlFvFLVIOURmcQrZyMFKbVu9/TeDiemls3w3/
|
||||||
|
JzVTduD+7KiUi9R7QcCW/V1ZpReTfunm7rfACiJ1fpIkjSQrgsvKDLghIzxIS5FM
|
||||||
|
I8utet5p6QtuJhaAwmmXn8xX05FvqWNbrcXRdpL4goFdigPsFK2xhTUiWatLMste
|
||||||
|
oShI7+zmrgkx75LeLMD0bL2uOf87JjOzbY8x2sUIZLGwPoATyG8WS38ey6KkJxRj
|
||||||
|
AhG3p+OTYEjYSrsAtQA6ImbeDpfSHKOB8HF3nVp//Eb4HEiEsWwBRbQXvAWh3DYL
|
||||||
|
GukFW0wiO0HVCoWY+bHL/Mqa0NdRGOlLsbL4Z4pLrhqKgSDU8umX9YuNRRaB0P5n
|
||||||
|
TkzyU6axHqzq990Gep/I62bjsBdYYp+DjSPK43mXRrfWJl2NTcl8xKAyfsOW+9hQ
|
||||||
|
9vwK0tpSicNxfYuUZs0BhfjSZ/Tc6Z1ERdgUYRiXTtohl+SRA2IgZMloHCllVMNj
|
||||||
|
EjXhguvHgLAOrcuyhVBupiUQGUHQvkMsr1Uz8VPNDFOJedwucRU2AaR881bknnSb
|
||||||
|
ds9+zNLsvUFV+BK7Qdnt/WkFpYL78rGwY47msi9Ooddx6fPyeg3qkJGM6cwn/boy
|
||||||
|
w9lQeleYDq8kyJdixIAxtAskNzRPJ4nDu2izTfByQoM8epwAWboc/gNFObMCAwEA
|
||||||
|
AaOB9zCB9DAdBgNVHQ4EFgQURqpATOw1gVVrzlqqFKbkfaKXvwowgcQGA1UdIwSB
|
||||||
|
vDCBuYAURqpATOw1gVVrzlqqFKbkfaKXvwqhgZWkgZIwgY8xCzAJBgNVBAYTAlVT
|
||||||
|
MQswCQYDVQQIEwJOWTERMA8GA1UEBxMITmV3IFlvcmsxFDASBgNVBAoTC0tleWJh
|
||||||
|
c2UgTExDMRcwFQYDVQQLEw5DZXJ0IEF1dGhvcml0eTETMBEGA1UEAxMKa2V5YmFz
|
||||||
|
ZS5pbzEcMBoGCSqGSIb3DQEJARYNY2FAa2V5YmFzZS5pb4IJAPzhpcIBaOeNMAwG
|
||||||
|
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggIBAA3Z5FIhulYghMuHdcHYTYWc
|
||||||
|
7xT5WD4hXQ0WALZs4p5Y+b2Af54o6v1wUE1Au97FORq5CsFXX/kGl/JzzTimeucn
|
||||||
|
YJwGuXMpilrlHCBAL5/lSQjA7qbYIolQ3SB9ON+LYuF1jKB9k8SqNp7qzucxT3tO
|
||||||
|
b8ZMDEPNsseC7NE2uwNtcW3yrTh6WZnSqg/jwswiWjHYDdG7U8FjMYlRol3wPux2
|
||||||
|
PizGbSgiR+ztI2OthxtxNWMrT9XKxNQTpcxOXnLuhiSwqH8PoY17ecP8VPpaa0K6
|
||||||
|
zym0zSkbroqydazaxcXRk3eSlc02Ktk7HzRzuqQQXhRMkxVnHbFHgGsz03L533pm
|
||||||
|
mlIEgBMggZkHwNvs1LR7f3v2McdKulDH7Mv8yyfguuQ5Jxxt7RJhUuqSudbEhoaM
|
||||||
|
6jAJwBkMFxsV2YnyFEd3eZ/qBYPf7TYHhyzmHW6WkSypGqSnXd4gYpJ8o7LxSf4F
|
||||||
|
inLjxRD+H9Xn1UVXWLM0gaBB7zZcXd2zjMpRsWgezf5IR5vyakJsc7fxzgor3Qeq
|
||||||
|
Ri6LvdEkhhFVl5rHMQBwNOPngySrq8cs/ikTLTfQVTYXXA4Ba1YyiMOlfaR1LhKw
|
||||||
|
If1AkUV0tfCTNRZ01EotKSK77+o+k214n+BAu+7mO+9B5Kb7lMFQcuWCHXKYB2Md
|
||||||
|
cT7Yh09F0QpFUd0ymEfv
|
||||||
|
-----END CERTIFICATE-----
|
||||||
33
OpenKeychain/src/main/assets/pgp.mit.edu.cer
Normal file
33
OpenKeychain/src/main/assets/pgp.mit.edu.cer
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFpzCCBI+gAwIBAgIQSCQjuTbnogvWCWWHeCDMbzANBgkqhkiG9w0BAQsFADB2
|
||||||
|
MQswCQYDVQQGEwJVUzELMAkGA1UECBMCTUkxEjAQBgNVBAcTCUFubiBBcmJvcjES
|
||||||
|
MBAGA1UEChMJSW50ZXJuZXQyMREwDwYDVQQLEwhJbkNvbW1vbjEfMB0GA1UEAxMW
|
||||||
|
SW5Db21tb24gUlNBIFNlcnZlciBDQTAeFw0xNDEwMDkwMDAwMDBaFw0xNzEwMDgy
|
||||||
|
MzU5NTlaMIHlMQswCQYDVQQGEwJVUzEOMAwGA1UEERMFMDIxMzkxCzAJBgNVBAgT
|
||||||
|
Ak1hMRIwEAYDVQQHEwlDYW1icmlkZ2UxHTAbBgNVBAkTFDc3IE1hc3NhY2h1c2V0
|
||||||
|
dHMgQXZlMS4wLAYDVQQKEyVNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNo
|
||||||
|
bm9sb2d5MSowKAYDVQQLFCFJbmZvcm1hdGlvbiBTZXJ2aWNlcyAmIFRlY2hub2xv
|
||||||
|
Z3kxFDASBgNVBAsTC1BsYXRpbnVtU1NMMRQwEgYDVQQDEwtwZ3AubWl0LmVkdTCC
|
||||||
|
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOXCQWXwK1O/saHfUEJjeE6w
|
||||||
|
VvTMe8xgl5qmkU+9U2TS6HdyVItD9fHZ3sAwVHo7mYtLGXp0S8F2hiiyLgQeQo84
|
||||||
|
F/owinPaPU8c+2Ogw464HbROmjU7Vc/iHQklA0kR+lZsFwZuWd+nYjmPrNfm87Ik
|
||||||
|
k9Wenco7wwFUquoJ8XZW1RVTr9WRWWlyNKwPnil5aBUGtbG6CP1+IFN75xfJYjz5
|
||||||
|
g+JcLHYsKyb6JhPYxT42ZdgTPKVRJNuIpyOMXMIPB/qFgUyU+2T/g7vxoa3THllq
|
||||||
|
vkp/ds5lpDe+uu6H9mbtMYvX5w9TBqt7YPegWcTUhGERnytXxeNpncYkzGMMUN0C
|
||||||
|
AwEAAaOCAb8wggG7MB8GA1UdIwQYMBaAFB4Fo3ePbJbiW4dLprSGrHEADOc4MB0G
|
||||||
|
A1UdDgQWBBRISoMA6cVQE5089wT6LFO4aiNnzTAOBgNVHQ8BAf8EBAMCBaAwDAYD
|
||||||
|
VR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwZwYDVR0g
|
||||||
|
BGAwXjBSBgwrBgEEAa4jAQQDAQEwQjBABggrBgEFBQcCARY0aHR0cHM6Ly93d3cu
|
||||||
|
aW5jb21tb24ub3JnL2NlcnQvcmVwb3NpdG9yeS9jcHNfc3NsLnBkZjAIBgZngQwB
|
||||||
|
AgIwRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC5pbmNvbW1vbi1yc2Eub3Jn
|
||||||
|
L0luQ29tbW9uUlNBU2VydmVyQ0EuY3JsMHUGCCsGAQUFBwEBBGkwZzA+BggrBgEF
|
||||||
|
BQcwAoYyaHR0cDovL2NydC51c2VydHJ1c3QuY29tL0luQ29tbW9uUlNBU2VydmVy
|
||||||
|
Q0FfMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w
|
||||||
|
FgYDVR0RBA8wDYILcGdwLm1pdC5lZHUwDQYJKoZIhvcNAQELBQADggEBAHbQqv2o
|
||||||
|
LrRD8rMzaHvPHVa92gfi6bpEsiRsVw3kpH4D4k+PL9LWkgtgTWpM+MvskiUvS9ay
|
||||||
|
FbWdXiy/peOj421fwnL/re9gmWs1g7FtUrDgIpz2T2jonPqbnIJPMHxI+ICWZMYH
|
||||||
|
V/dO844geRKAiGs/UZbG4Uf1Jo0PxtPtD5puaUk4l9Va8WHU2OLq0kzS9K+iu/sx
|
||||||
|
z0XG+fAMneyiXm5jtfjYE2W8/h61RhZulSUmYBkiMLzKr5eqe2VIkMqyTfyZ5zms
|
||||||
|
1LZ1GWaouMsTBN1+2TXssQ71L1tIZg/lXJVlfVRkwOIV5Mp3ohxLSBZT8qNSef1v
|
||||||
|
mFNa+DGU1sdl6m4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -98,7 +98,9 @@ public class KeychainApplication extends Application {
|
|||||||
// Update keyserver list as needed
|
// Update keyserver list as needed
|
||||||
Preferences.getPreferences(this).upgradePreferences(this);
|
Preferences.getPreferences(this).upgradePreferences(this);
|
||||||
|
|
||||||
TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer");
|
TlsHelper.addPinnedCertificate("hkps.pool.sks-keyservers.net", getAssets(), "hkps.pool.sks-keyservers.net.CA.cer");
|
||||||
|
TlsHelper.addPinnedCertificate("pgp.mit.edu", getAssets(), "pgp.mit.edu.cer");
|
||||||
|
TlsHelper.addPinnedCertificate("api.keybase.io", getAssets(), "api.keybase.io.CA.cer");
|
||||||
|
|
||||||
TemporaryStorageProvider.cleanUp(this);
|
TemporaryStorageProvider.cleanUp(this);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Andreas Jakl
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sufficientlysecure.keychain.experimental;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BitInputStream allows reading individual bits from a
|
||||||
|
* general Java InputStream.
|
||||||
|
* Like the various Stream-classes from Java, the BitInputStream
|
||||||
|
* has to be created based on another Input stream. It provides
|
||||||
|
* a function to read the next bit from the sream, as well as to read multiple
|
||||||
|
* bits at once and write the resulting data into an integer value.
|
||||||
|
* <p/>
|
||||||
|
* source: http://developer.nokia.com/Community/Wiki/Bit_Input/Output_Stream_utility_classes_for_efficient_data_transfer
|
||||||
|
*/
|
||||||
|
public class BitInputStream {
|
||||||
|
/**
|
||||||
|
* The Java InputStream this class is working on.
|
||||||
|
*/
|
||||||
|
private InputStream iIs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer containing the currently processed
|
||||||
|
* byte of the input stream.
|
||||||
|
*/
|
||||||
|
private int iBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Next bit of the current byte value that the user will
|
||||||
|
* get. If it's 8, the next bit will be read from the
|
||||||
|
* next byte of the InputStream.
|
||||||
|
*/
|
||||||
|
private int iNextBit = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new bit input stream based on an existing Java InputStream.
|
||||||
|
*
|
||||||
|
* @param aIs the input stream this class should read the bits from.
|
||||||
|
*/
|
||||||
|
public BitInputStream(InputStream aIs) {
|
||||||
|
iIs = aIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a specified number of bits and return them combined as
|
||||||
|
* an integer value. The bits are written to the integer
|
||||||
|
* starting at the highest bit ( << aNumberOfBits ), going down
|
||||||
|
* to the lowest bit ( << 0 )
|
||||||
|
*
|
||||||
|
* @param aNumberOfBits defines how many bits to read from the stream.
|
||||||
|
* @return integer value containing the bits read from the stream.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
synchronized public int readBits(final int aNumberOfBits)
|
||||||
|
throws IOException {
|
||||||
|
int value = 0;
|
||||||
|
for (int i = aNumberOfBits - 1; i >= 0; i--) {
|
||||||
|
value |= (readBit() << i);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public int available() {
|
||||||
|
try {
|
||||||
|
return (8 - iNextBit) + iIs.available() * 8; // bytestream to bitstream available
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the next bit from the stream.
|
||||||
|
*
|
||||||
|
* @return 0 if the bit is 0, 1 if the bit is 1.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
synchronized public int readBit() throws IOException {
|
||||||
|
if (iIs == null)
|
||||||
|
throw new IOException("Already closed");
|
||||||
|
|
||||||
|
if (iNextBit == 8) {
|
||||||
|
iBuffer = iIs.read();
|
||||||
|
|
||||||
|
if (iBuffer == -1)
|
||||||
|
throw new EOFException();
|
||||||
|
|
||||||
|
iNextBit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bit = iBuffer & (1 << iNextBit);
|
||||||
|
iNextBit++;
|
||||||
|
|
||||||
|
bit = (bit == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the underlying input stream.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
iIs.close();
|
||||||
|
iIs = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
* Copyright (C) 2014 Jake McGinty (Open Whisper Systems)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sufficientlysecure.keychain.experimental;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From https://github.com/mcginty/TextSecure/tree/mnemonic-poem
|
||||||
|
*/
|
||||||
|
public class SentenceConfirm {
|
||||||
|
Context context;
|
||||||
|
List<String> n, vi, vt, adj, adv, p, art;
|
||||||
|
|
||||||
|
public SentenceConfirm(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
try {
|
||||||
|
n = readFile(R.raw.fp_sentence_nouns);
|
||||||
|
vi = readFile(R.raw.fp_sentence_verbs_i);
|
||||||
|
vt = readFile(R.raw.fp_sentence_verbs_t);
|
||||||
|
adj = readFile(R.raw.fp_sentence_adjectives);
|
||||||
|
adv = readFile(R.raw.fp_sentence_adverbs);
|
||||||
|
p = readFile(R.raw.fp_sentence_prepositions);
|
||||||
|
art = readFile(R.raw.fp_sentence_articles);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(Constants.TAG, "Reading sentence files failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> readFile(int resId) throws IOException {
|
||||||
|
if (context.getApplicationContext() == null) {
|
||||||
|
throw new AssertionError("app context can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(
|
||||||
|
context.getApplicationContext()
|
||||||
|
.getResources()
|
||||||
|
.openRawResource(resId)));
|
||||||
|
List<String> words = new ArrayList<>();
|
||||||
|
String word = in.readLine();
|
||||||
|
while (word != null) {
|
||||||
|
words.add(word);
|
||||||
|
word = in.readLine();
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String fromBytes(final byte[] bytes, int desiredBytes) throws IOException {
|
||||||
|
BitInputStream bin = new BitInputStream(new ByteArrayInputStream(bytes));
|
||||||
|
EntropyString fingerprint = new EntropyString();
|
||||||
|
|
||||||
|
while (fingerprint.getBits() < (desiredBytes * 8)) {
|
||||||
|
if (!fingerprint.isEmpty()) {
|
||||||
|
fingerprint.append("\n\n");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fingerprint.append(getSentence(bin));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(Constants.TAG, "IOException when creating the sentence");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fingerprint.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab a word for a list of them using the necessary bits to choose from a BitInputStream
|
||||||
|
*
|
||||||
|
* @param words the list of words to select from
|
||||||
|
* @param bin the bit input stream to encode from
|
||||||
|
* @return A Pair of the word and the number of bits consumed from the stream
|
||||||
|
*/
|
||||||
|
private EntropyString getWord(List<String> words, BitInputStream bin) throws IOException {
|
||||||
|
final int neededBits = log(words.size(), 2);
|
||||||
|
Log.d(Constants.TAG, "need " + neededBits + " bits of entropy");
|
||||||
|
int bits = bin.readBits(neededBits);
|
||||||
|
Log.d(Constants.TAG, "got word " + words.get(bits) + " with " + neededBits + " bits of entropy");
|
||||||
|
return new EntropyString(words.get(bits), neededBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntropyString getNounPhrase(BitInputStream bits) throws IOException {
|
||||||
|
final EntropyString phrase = new EntropyString();
|
||||||
|
phrase.append(getWord(art, bits)).append(" ");
|
||||||
|
if (bits.readBit() != 0) {
|
||||||
|
phrase.append(getWord(adj, bits)).append(" ");
|
||||||
|
}
|
||||||
|
phrase.incBits();
|
||||||
|
|
||||||
|
phrase.append(getWord(n, bits));
|
||||||
|
Log.d(Constants.TAG, "got phrase " + phrase + " with " + phrase.getBits() + " bits of entropy");
|
||||||
|
return phrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntropyString getSentence(BitInputStream bits) throws IOException {
|
||||||
|
final EntropyString sentence = new EntropyString();
|
||||||
|
sentence.append(getNounPhrase(bits)); // Subject
|
||||||
|
if (bits.readBit() != 0) {
|
||||||
|
sentence.append(" ").append(getWord(vt, bits)); // Transitive verb
|
||||||
|
sentence.append(" ").append(getNounPhrase(bits)); // Object of transitive verb
|
||||||
|
} else {
|
||||||
|
sentence.append(" ").append(getWord(vi, bits)); // Intransitive verb
|
||||||
|
}
|
||||||
|
sentence.incBits();
|
||||||
|
|
||||||
|
if (bits.readBit() != 0) {
|
||||||
|
sentence.append(" ").append(getWord(adv, bits)); // Adverb
|
||||||
|
}
|
||||||
|
|
||||||
|
sentence.incBits();
|
||||||
|
if (bits.readBit() != 0) {
|
||||||
|
sentence.append(" ").append(getWord(p, bits)); // Preposition
|
||||||
|
sentence.append(" ").append(getNounPhrase(bits)); // Object of preposition
|
||||||
|
}
|
||||||
|
sentence.incBits();
|
||||||
|
Log.d(Constants.TAG, "got sentence " + sentence + " with " + sentence.getBits() + " bits of entropy");
|
||||||
|
|
||||||
|
// uppercase first character, end with dot (without increasing the bits)
|
||||||
|
sentence.getBuilder().replace(0, 1,
|
||||||
|
Character.toString(Character.toUpperCase(sentence.getBuilder().charAt(0))));
|
||||||
|
sentence.getBuilder().append(".");
|
||||||
|
|
||||||
|
return sentence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EntropyString {
|
||||||
|
private StringBuilder builder;
|
||||||
|
private int bits;
|
||||||
|
|
||||||
|
public EntropyString(String phrase, int bits) {
|
||||||
|
this.builder = new StringBuilder(phrase);
|
||||||
|
this.bits = bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntropyString() {
|
||||||
|
this("", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilder getBuilder() {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return builder.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntropyString append(EntropyString phrase) {
|
||||||
|
builder.append(phrase);
|
||||||
|
bits += phrase.getBits();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntropyString append(String string) {
|
||||||
|
builder.append(string);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBits() {
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBits(int bits) {
|
||||||
|
this.bits = bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incBits() {
|
||||||
|
bits += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int log(int x, int base) {
|
||||||
|
return (int) (Math.log(x) / Math.log(base));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,12 +15,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.util;
|
package org.sufficientlysecure.keychain.experimental;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.spongycastle.util.Arrays;
|
import org.spongycastle.util.Arrays;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@@ -29,7 +30,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
public class ExperimentalWordConfirm {
|
public class WordConfirm {
|
||||||
|
|
||||||
public static String getWords(Context context, byte[] fingerprintBlob) {
|
public static String getWords(Context context, byte[] fingerprintBlob) {
|
||||||
ArrayList<String> words = new ArrayList<>();
|
ArrayList<String> words = new ArrayList<>();
|
||||||
@@ -37,7 +38,7 @@ public class ExperimentalWordConfirm {
|
|||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
try {
|
try {
|
||||||
reader = new BufferedReader(new InputStreamReader(
|
reader = new BufferedReader(new InputStreamReader(
|
||||||
context.getAssets().open("word_confirm_list.txt"),
|
context.getResources().openRawResource(R.raw.fp_word_list),
|
||||||
"UTF-8"
|
"UTF-8"
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ public class CloudSearch {
|
|||||||
// kill threads that haven't returned yet
|
// kill threads that haven't returned yet
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.squareup.okhttp.OkHttpClient;
|
|||||||
import com.squareup.okhttp.Request;
|
import com.squareup.okhttp.Request;
|
||||||
import com.squareup.okhttp.RequestBody;
|
import com.squareup.okhttp.RequestBody;
|
||||||
import com.squareup.okhttp.Response;
|
import com.squareup.okhttp.Response;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
@@ -198,17 +199,21 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
*
|
*
|
||||||
* @param url url to be queried by client
|
* @param url url to be queried by client
|
||||||
* @param proxy proxy to be used by client
|
* @param proxy proxy to be used by client
|
||||||
* @return client with a pinned certificate if necesary
|
* @return client with a pinned certificate if necessary
|
||||||
*/
|
*/
|
||||||
public static OkHttpClient getClient(URL url, Proxy proxy) throws IOException {
|
public static OkHttpClient getClient(URL url, Proxy proxy) throws IOException {
|
||||||
OkHttpClient client = new OkHttpClient();
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TlsHelper.pinCertificateIfNecessary(client, url);
|
TlsHelper.usePinnedCertificateIfAvailable(client, url);
|
||||||
} catch (TlsHelper.TlsHelperException e) {
|
} catch (TlsHelper.TlsHelperException e) {
|
||||||
Log.w(Constants.TAG, e);
|
Log.w(Constants.TAG, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't follow any redirects
|
||||||
|
client.setFollowRedirects(false);
|
||||||
|
client.setFollowSslRedirects(false);
|
||||||
|
|
||||||
if (proxy != null) {
|
if (proxy != null) {
|
||||||
client.setProxy(proxy);
|
client.setProxy(proxy);
|
||||||
client.setConnectTimeout(30000, TimeUnit.MILLISECONDS);
|
client.setConnectTimeout(30000, TimeUnit.MILLISECONDS);
|
||||||
@@ -238,17 +243,12 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(Constants.TAG, "IOException at HkpKeyserver", e);
|
Log.e(Constants.TAG, "IOException at HkpKeyserver", e);
|
||||||
throw new QueryFailedException("Keyserver '" + mHost + "' is unavailable. Check your Internet connection!" +
|
throw new QueryFailedException("Keyserver '" + mHost + "' is unavailable. Check your Internet connection!" +
|
||||||
proxy == null?"":" Using proxy " + proxy);
|
(proxy == null ? "" : " Using proxy " + proxy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Results are sorted by creation date of key!
|
* Results are sorted by creation date of key!
|
||||||
*
|
|
||||||
* @param query
|
|
||||||
* @return
|
|
||||||
* @throws QueryFailedException
|
|
||||||
* @throws QueryNeedsRepairException
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<ImportKeysListEntry> search(String query, Proxy proxy) throws QueryFailedException,
|
public ArrayList<ImportKeysListEntry> search(String query, Proxy proxy) throws QueryFailedException,
|
||||||
@@ -299,30 +299,46 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
entry.setQuery(query);
|
entry.setQuery(query);
|
||||||
entry.addOrigin(getUrlPrefix() + mHost + ":" + mPort);
|
entry.addOrigin(getUrlPrefix() + mHost + ":" + mPort);
|
||||||
|
|
||||||
|
// group 1 contains the full fingerprint (v4) or the long key id if available
|
||||||
|
// see https://bitbucket.org/skskeyserver/sks-keyserver/pull-request/12/fixes-for-machine-readable-indexes/diff
|
||||||
|
String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.ENGLISH);
|
||||||
|
if (fingerprintOrKeyId.length() == 40) {
|
||||||
|
entry.setFingerprintHex(fingerprintOrKeyId);
|
||||||
|
entry.setKeyIdHex("0x" + fingerprintOrKeyId.substring(fingerprintOrKeyId.length()
|
||||||
|
- 16, fingerprintOrKeyId.length()));
|
||||||
|
} else if (fingerprintOrKeyId.length() == 16) {
|
||||||
|
// set key id only
|
||||||
|
entry.setKeyIdHex("0x" + fingerprintOrKeyId);
|
||||||
|
} else {
|
||||||
|
Log.e(Constants.TAG, "Wrong length for fingerprint/long key id.");
|
||||||
|
// skip this key
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
int bitSize = Integer.parseInt(matcher.group(3));
|
int bitSize = Integer.parseInt(matcher.group(3));
|
||||||
entry.setBitStrength(bitSize);
|
entry.setBitStrength(bitSize);
|
||||||
int algorithmId = Integer.decode(matcher.group(2));
|
int algorithmId = Integer.decode(matcher.group(2));
|
||||||
entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitSize, null));
|
entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitSize, null));
|
||||||
|
|
||||||
// group 1 contains the full fingerprint (v4) or the long key id if available
|
|
||||||
// see https://bitbucket.org/skskeyserver/sks-keyserver/pull-request/12/fixes-for-machine-readable-indexes/diff
|
|
||||||
String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.ENGLISH);
|
|
||||||
if (fingerprintOrKeyId.length() > 16) {
|
|
||||||
entry.setFingerprintHex(fingerprintOrKeyId);
|
|
||||||
entry.setKeyIdHex("0x" + fingerprintOrKeyId.substring(fingerprintOrKeyId.length()
|
|
||||||
- 16, fingerprintOrKeyId.length()));
|
|
||||||
} else {
|
|
||||||
// set key id only
|
|
||||||
entry.setKeyIdHex("0x" + fingerprintOrKeyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
final long creationDate = Long.parseLong(matcher.group(4));
|
final long creationDate = Long.parseLong(matcher.group(4));
|
||||||
final GregorianCalendar tmpGreg = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
final GregorianCalendar tmpGreg = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||||
tmpGreg.setTimeInMillis(creationDate * 1000);
|
tmpGreg.setTimeInMillis(creationDate * 1000);
|
||||||
entry.setDate(tmpGreg.getTime());
|
entry.setDate(tmpGreg.getTime());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Log.e(Constants.TAG, "Conversation for bit size, algorithm, or creation date failed.", e);
|
||||||
|
// skip this key
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
entry.setRevoked(matcher.group(6).contains("r"));
|
entry.setRevoked(matcher.group(6).contains("r"));
|
||||||
entry.setExpired(matcher.group(6).contains("e"));
|
entry.setExpired(matcher.group(6).contains("e"));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
Log.e(Constants.TAG, "Check for revocation or expiry failed.", e);
|
||||||
|
// skip this key
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList<String> userIds = new ArrayList<>();
|
ArrayList<String> userIds = new ArrayList<>();
|
||||||
final String uidLines = matcher.group(7);
|
final String uidLines = matcher.group(7);
|
||||||
@@ -340,6 +356,10 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
tmp = URLDecoder.decode(tmp, "UTF8");
|
tmp = URLDecoder.decode(tmp, "UTF8");
|
||||||
} catch (UnsupportedEncodingException ignored) {
|
} catch (UnsupportedEncodingException ignored) {
|
||||||
// will never happen, because "UTF8" is supported
|
// will never happen, because "UTF8" is supported
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(Constants.TAG, "User ID encoding broken", e);
|
||||||
|
// skip this user id
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userIds.add(tmp);
|
userIds.add(tmp);
|
||||||
@@ -363,11 +383,14 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
Log.d(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
|
Log.d(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
|
||||||
throw new QueryFailedException("not found");
|
throw new QueryFailedException("not found");
|
||||||
}
|
}
|
||||||
|
if (data == null) {
|
||||||
|
throw new QueryFailedException("data is null");
|
||||||
|
}
|
||||||
Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data);
|
Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
}
|
}
|
||||||
return null;
|
throw new QueryFailedException("data is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -418,7 +441,7 @@ public class HkpKeyserver extends Keyserver {
|
|||||||
* Tries to find a server responsible for a given domain
|
* Tries to find a server responsible for a given domain
|
||||||
*
|
*
|
||||||
* @return A responsible Keyserver or null if not found.
|
* @return A responsible Keyserver or null if not found.
|
||||||
* TODO: PHILIP Add proxy functionality
|
* TODO: Add proxy functionality
|
||||||
*/
|
*/
|
||||||
public static HkpKeyserver resolve(String domain) {
|
public static HkpKeyserver resolve(String domain) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ package org.sufficientlysecure.keychain.keyimport;
|
|||||||
|
|
||||||
import com.textuality.keybase.lib.KeybaseException;
|
import com.textuality.keybase.lib.KeybaseException;
|
||||||
import com.textuality.keybase.lib.Match;
|
import com.textuality.keybase.lib.Match;
|
||||||
import com.textuality.keybase.lib.Search;
|
import com.textuality.keybase.lib.KeybaseQuery;
|
||||||
import com.textuality.keybase.lib.User;
|
import com.textuality.keybase.lib.User;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.OkHttpKeybaseClient;
|
||||||
|
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -49,7 +50,9 @@ public class KeybaseKeyserver extends Keyserver {
|
|||||||
mQuery = query;
|
mQuery = query;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Iterable<Match> matches = Search.search(query, proxy);
|
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
|
||||||
|
keybaseQuery.setProxy(proxy);
|
||||||
|
Iterable<Match> matches = keybaseQuery.search(query);
|
||||||
for (Match match : matches) {
|
for (Match match : matches) {
|
||||||
results.add(makeEntry(match));
|
results.add(makeEntry(match));
|
||||||
}
|
}
|
||||||
@@ -101,7 +104,9 @@ public class KeybaseKeyserver extends Keyserver {
|
|||||||
@Override
|
@Override
|
||||||
public String get(String id, Proxy proxy) throws QueryFailedException {
|
public String get(String id, Proxy proxy) throws QueryFailedException {
|
||||||
try {
|
try {
|
||||||
return User.keyForUsername(id, proxy);
|
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
|
||||||
|
keybaseQuery.setProxy(proxy);
|
||||||
|
return User.keyForUsername(keybaseQuery, id);
|
||||||
} catch (KeybaseException e) {
|
} catch (KeybaseException e) {
|
||||||
throw new QueryFailedException(e.getMessage());
|
throw new QueryFailedException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,15 +62,15 @@ public abstract class Keyserver {
|
|||||||
* query too short _or_ too many responses
|
* query too short _or_ too many responses
|
||||||
*/
|
*/
|
||||||
public static class QueryTooShortOrTooManyResponsesException extends QueryNeedsRepairException {
|
public static class QueryTooShortOrTooManyResponsesException extends QueryNeedsRepairException {
|
||||||
private static final long serialVersionUID = 2703768928624654514L;
|
private static final long serialVersionUID = 2703768928624654518L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AddKeyException extends Exception {
|
public static class AddKeyException extends Exception {
|
||||||
private static final long serialVersionUID = -507574859137295530L;
|
private static final long serialVersionUID = -507574859137295530L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract List<ImportKeysListEntry> search(String query, Proxy proxy) throws QueryFailedException,
|
public abstract List<ImportKeysListEntry> search(String query, Proxy proxy)
|
||||||
QueryNeedsRepairException;
|
throws QueryFailedException, QueryNeedsRepairException;
|
||||||
|
|
||||||
public abstract String get(String keyIdHex, Proxy proxy) throws QueryFailedException;
|
public abstract String get(String keyIdHex, Proxy proxy) throws QueryFailedException;
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.apache.james.mime4j.MimeException;
|
import org.apache.james.mime4j.MimeException;
|
||||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||||
@@ -86,6 +87,11 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
|||||||
DecryptVerifyResult decryptResult = null;
|
DecryptVerifyResult decryptResult = null;
|
||||||
|
|
||||||
PgpDecryptVerifyInputParcel decryptInput = input.getDecryptInput();
|
PgpDecryptVerifyInputParcel decryptInput = input.getDecryptInput();
|
||||||
|
|
||||||
|
if (!input.getMimeDecode() && decryptInput == null) {
|
||||||
|
throw new AssertionError("no decryption or mime decoding, this is probably a bug");
|
||||||
|
}
|
||||||
|
|
||||||
if (decryptInput != null) {
|
if (decryptInput != null) {
|
||||||
|
|
||||||
log.add(LogType.MSG_DATA_OPENPGP, 1);
|
log.add(LogType.MSG_DATA_OPENPGP, 1);
|
||||||
@@ -109,16 +115,33 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
|||||||
return new InputDataResult(InputDataResult.RESULT_ERROR, log);
|
return new InputDataResult(InputDataResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inform the storage provider about the mime type for this uri
|
||||||
|
if (decryptResult.getDecryptionMetadata() != null) {
|
||||||
|
TemporaryStorageProvider.setMimeType(mContext, currentInputUri,
|
||||||
|
decryptResult.getDecryptionMetadata().getMimeType());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
currentInputUri = input.getInputUri();
|
currentInputUri = input.getInputUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't supposed to attempt mime decode, we are done here
|
// don't even attempt if we know the data isn't suitable for mime content, or if we have a filename
|
||||||
if (!input.getMimeDecode()) {
|
boolean skipMimeParsing = false;
|
||||||
|
if (decryptResult != null && decryptResult.getDecryptionMetadata() != null) {
|
||||||
if (decryptInput == null) {
|
OpenPgpMetadata metadata = decryptResult.getDecryptionMetadata();
|
||||||
throw new AssertionError("no decryption or mime decoding, this is probably a bug");
|
String fileName = metadata.getFilename();
|
||||||
|
String contentType = metadata.getMimeType();
|
||||||
|
if (!TextUtils.isEmpty(fileName)
|
||||||
|
|| contentType != null
|
||||||
|
&& !contentType.startsWith("multipart/")
|
||||||
|
&& !contentType.startsWith("text/")
|
||||||
|
&& !contentType.startsWith("application/")) {
|
||||||
|
skipMimeParsing = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we aren't supposed to attempt mime decode after decryption, we are done here
|
||||||
|
if (skipMimeParsing || !input.getMimeDecode()) {
|
||||||
|
|
||||||
log.add(LogType.MSG_DATA_SKIP_MIME, 1);
|
log.add(LogType.MSG_DATA_SKIP_MIME, 1);
|
||||||
|
|
||||||
@@ -309,6 +332,8 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
|||||||
|
|
||||||
log.add(LogType.MSG_DATA_MIME, 1);
|
log.add(LogType.MSG_DATA_MIME, 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
// open current uri for input
|
// open current uri for input
|
||||||
InputStream in = mContext.getContentResolver().openInputStream(currentInputUri);
|
InputStream in = mContext.getContentResolver().openInputStream(currentInputUri);
|
||||||
parser.parse(in);
|
parser.parse(in);
|
||||||
@@ -329,6 +354,11 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
|||||||
parser.parse(in);
|
parser.parse(in);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} catch (MimeException e) {
|
||||||
|
// a mime error likely means that this wasn't mime data, after all
|
||||||
|
e.printStackTrace();
|
||||||
|
log.add(LogType.MSG_DATA_MIME_BAD, 2);
|
||||||
|
}
|
||||||
|
|
||||||
// if we found data, return success
|
// if we found data, return success
|
||||||
if (!outputUris.isEmpty()) {
|
if (!outputUris.isEmpty()) {
|
||||||
@@ -363,10 +393,6 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.add(LogType.MSG_DATA_ERROR_IO, 2);
|
log.add(LogType.MSG_DATA_ERROR_IO, 2);
|
||||||
return new InputDataResult(InputDataResult.RESULT_ERROR, log);
|
return new InputDataResult(InputDataResult.RESULT_ERROR, log);
|
||||||
} catch (MimeException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
log.add(LogType.MSG_DATA_MIME_ERROR, 2);
|
|
||||||
return new InputDataResult(InputDataResult.RESULT_ERROR, log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,39 +20,43 @@
|
|||||||
package org.sufficientlysecure.keychain.operations;
|
package org.sufficientlysecure.keychain.operations;
|
||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.textuality.keybase.lib.KeybaseQuery;
|
||||||
import com.textuality.keybase.lib.Proof;
|
import com.textuality.keybase.lib.Proof;
|
||||||
import com.textuality.keybase.lib.prover.Prover;
|
import com.textuality.keybase.lib.prover.Prover;
|
||||||
import de.measite.minidns.Client;
|
|
||||||
import de.measite.minidns.DNSMessage;
|
|
||||||
import de.measite.minidns.Question;
|
|
||||||
import de.measite.minidns.Record;
|
|
||||||
import de.measite.minidns.record.Data;
|
|
||||||
import de.measite.minidns.record.TXT;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
|
import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
|
import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
|
import org.sufficientlysecure.keychain.util.OkHttpKeybaseClient;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
|
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.measite.minidns.Client;
|
||||||
|
import de.measite.minidns.DNSMessage;
|
||||||
|
import de.measite.minidns.Question;
|
||||||
|
import de.measite.minidns.Record;
|
||||||
|
import de.measite.minidns.record.Data;
|
||||||
|
import de.measite.minidns.record.TXT;
|
||||||
|
|
||||||
public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificationParcel> {
|
public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificationParcel> {
|
||||||
|
|
||||||
public KeybaseVerificationOperation(Context context, ProviderHelper providerHelper,
|
public KeybaseVerificationOperation(Context context, ProviderHelper providerHelper,
|
||||||
@@ -83,6 +87,9 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
|
|||||||
log.add(OperationResult.LogType.MSG_KEYBASE_VERIFICATION, 0, requiredFingerprint);
|
log.add(OperationResult.LogType.MSG_KEYBASE_VERIFICATION, 0, requiredFingerprint);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
|
||||||
|
keybaseQuery.setProxy(proxy);
|
||||||
|
|
||||||
String keybaseProof = keybaseInput.mKeybaseProof;
|
String keybaseProof = keybaseInput.mKeybaseProof;
|
||||||
Proof proof = new Proof(new JSONObject(keybaseProof));
|
Proof proof = new Proof(new JSONObject(keybaseProof));
|
||||||
mProgressable.setProgress(R.string.keybase_message_fetching_data, 0, 100);
|
mProgressable.setProgress(R.string.keybase_message_fetching_data, 0, 100);
|
||||||
@@ -95,7 +102,7 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
|
|||||||
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
|
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prover.fetchProofData(proxy)) {
|
if (!prover.fetchProofData(keybaseQuery)) {
|
||||||
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FETCH_PROOF, 1);
|
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FETCH_PROOF, 1);
|
||||||
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
|
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,6 +474,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_KC_UID_BAD (LogLevel.WARN, R.string.msg_kc_uid_bad),
|
MSG_KC_UID_BAD (LogLevel.WARN, R.string.msg_kc_uid_bad),
|
||||||
MSG_KC_UID_CERT_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_cert_dup),
|
MSG_KC_UID_CERT_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_cert_dup),
|
||||||
MSG_KC_UID_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_dup),
|
MSG_KC_UID_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_dup),
|
||||||
|
MSG_KC_UID_TOO_MANY (LogLevel.DEBUG, R.string.msg_kc_uid_too_many),
|
||||||
MSG_KC_UID_FOREIGN (LogLevel.DEBUG, R.string.msg_kc_uid_foreign),
|
MSG_KC_UID_FOREIGN (LogLevel.DEBUG, R.string.msg_kc_uid_foreign),
|
||||||
MSG_KC_UID_NO_CERT (LogLevel.DEBUG, R.string.msg_kc_uid_no_cert),
|
MSG_KC_UID_NO_CERT (LogLevel.DEBUG, R.string.msg_kc_uid_no_cert),
|
||||||
MSG_KC_UID_REVOKE_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_revoke_dup),
|
MSG_KC_UID_REVOKE_DUP (LogLevel.DEBUG, R.string.msg_kc_uid_revoke_dup),
|
||||||
@@ -832,7 +833,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_DATA_DETACHED_NESTED(LogLevel.WARN, R.string.msg_data_detached_nested),
|
MSG_DATA_DETACHED_NESTED(LogLevel.WARN, R.string.msg_data_detached_nested),
|
||||||
MSG_DATA_DETACHED_TRAILING (LogLevel.WARN, R.string.msg_data_detached_trailing),
|
MSG_DATA_DETACHED_TRAILING (LogLevel.WARN, R.string.msg_data_detached_trailing),
|
||||||
MSG_DATA_DETACHED_UNSUPPORTED (LogLevel.WARN, R.string.msg_data_detached_unsupported),
|
MSG_DATA_DETACHED_UNSUPPORTED (LogLevel.WARN, R.string.msg_data_detached_unsupported),
|
||||||
MSG_DATA_MIME_ERROR (LogLevel.ERROR, R.string.msg_data_mime_error),
|
MSG_DATA_MIME_BAD(LogLevel.INFO, R.string.msg_data_mime_bad),
|
||||||
MSG_DATA_MIME_FILENAME (LogLevel.DEBUG, R.string.msg_data_mime_filename),
|
MSG_DATA_MIME_FILENAME (LogLevel.DEBUG, R.string.msg_data_mime_filename),
|
||||||
MSG_DATA_MIME_LENGTH (LogLevel.DEBUG, R.string.msg_data_mime_length),
|
MSG_DATA_MIME_LENGTH (LogLevel.DEBUG, R.string.msg_data_mime_length),
|
||||||
MSG_DATA_MIME (LogLevel.DEBUG, R.string.msg_data_mime),
|
MSG_DATA_MIME (LogLevel.DEBUG, R.string.msg_data_mime),
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ import org.sufficientlysecure.keychain.Constants;
|
|||||||
import org.sufficientlysecure.keychain.Constants.key;
|
import org.sufficientlysecure.keychain.Constants.key;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.BaseOperation;
|
import org.sufficientlysecure.keychain.operations.BaseOperation;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
|
||||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
@@ -512,8 +512,9 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
PGPLiteralData literalData = (PGPLiteralData) dataChunk;
|
PGPLiteralData literalData = (PGPLiteralData) dataChunk;
|
||||||
|
|
||||||
String originalFilename = literalData.getFileName();
|
String originalFilename = literalData.getFileName();
|
||||||
|
// reject filenames with slashes completely (path traversal issue)
|
||||||
if (originalFilename.contains("/")) {
|
if (originalFilename.contains("/")) {
|
||||||
originalFilename = originalFilename.substring(originalFilename.lastIndexOf('/'));
|
originalFilename = "";
|
||||||
}
|
}
|
||||||
String mimeType = null;
|
String mimeType = null;
|
||||||
if (literalData.getFormat() == PGPLiteralData.TEXT
|
if (literalData.getFormat() == PGPLiteralData.TEXT
|
||||||
|
|||||||
@@ -456,11 +456,15 @@ public class UncachedKeyRing {
|
|||||||
|
|
||||||
// check for duplicate user ids
|
// check for duplicate user ids
|
||||||
if (processedUserIds.contains(userId)) {
|
if (processedUserIds.contains(userId)) {
|
||||||
log.add(LogType.MSG_KC_UID_DUP,
|
log.add(LogType.MSG_KC_UID_DUP, indent, userId);
|
||||||
indent, userId);
|
|
||||||
// strip out the first found user id with this name
|
// strip out the first found user id with this name
|
||||||
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||||
}
|
}
|
||||||
|
if (processedUserIds.size() > 100) {
|
||||||
|
log.add(LogType.MSG_KC_UID_TOO_MANY, indent, userId);
|
||||||
|
// strip out the user id
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||||
|
}
|
||||||
processedUserIds.add(userId);
|
processedUserIds.add(userId);
|
||||||
|
|
||||||
PGPSignature selfCert = null;
|
PGPSignature selfCert = null;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class KeychainDatabase extends SQLiteOpenHelper {
|
public class KeychainDatabase extends SQLiteOpenHelper {
|
||||||
private static final String DATABASE_NAME = "openkeychain.db";
|
private static final String DATABASE_NAME = "openkeychain.db";
|
||||||
private static final int DATABASE_VERSION = 12;
|
private static final int DATABASE_VERSION = 13;
|
||||||
static Boolean apgHack = false;
|
static Boolean apgHack = false;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@@ -296,6 +296,8 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
|||||||
// the api_accounts fix and the new update keys table
|
// the api_accounts fix and the new update keys table
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 13:
|
||||||
|
// do nothing here, just consolidate
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,6 +308,13 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
|||||||
mContext.getApplicationContext().startActivity(consolidateIntent);
|
mContext.getApplicationContext().startActivity(consolidateIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
// NOTE: downgrading the database is explicitly not allowed to prevent
|
||||||
|
// someone from exploiting old bugs to export the database
|
||||||
|
throw new RuntimeException("Downgrading the database is not allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
/** This method tries to import data from a provided database.
|
/** This method tries to import data from a provided database.
|
||||||
*
|
*
|
||||||
* The sole assumptions made on this db are that there is a key_rings table
|
* The sole assumptions made on this db are that there is a key_rings table
|
||||||
|
|||||||
@@ -33,12 +33,14 @@ import android.widget.TextView;
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||||
|
import org.sufficientlysecure.keychain.experimental.SentenceConfirm;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.ui.util.ExperimentalWordConfirm;
|
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
public class CertifyFingerprintFragment extends LoaderFragment implements
|
public class CertifyFingerprintFragment extends LoaderFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@@ -46,24 +48,26 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
static final int REQUEST_CERTIFY = 1;
|
static final int REQUEST_CERTIFY = 1;
|
||||||
|
|
||||||
public static final String ARG_DATA_URI = "uri";
|
public static final String ARG_DATA_URI = "uri";
|
||||||
public static final String ARG_ENABLE_WORD_CONFIRM = "enable_word_confirm";
|
public static final String ARG_ENABLE_PHRASES_CONFIRM = "enable_word_confirm";
|
||||||
|
|
||||||
|
private TextView mActionYes;
|
||||||
private TextView mFingerprint;
|
private TextView mFingerprint;
|
||||||
private TextView mIntro;
|
private TextView mIntro;
|
||||||
|
private TextView mHeader;
|
||||||
|
|
||||||
private static final int LOADER_ID_UNIFIED = 0;
|
private static final int LOADER_ID_UNIFIED = 0;
|
||||||
|
|
||||||
private Uri mDataUri;
|
private Uri mDataUri;
|
||||||
private boolean mEnableWordConfirm;
|
private boolean mEnablePhrasesConfirm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this fragment
|
* Creates new instance of this fragment
|
||||||
*/
|
*/
|
||||||
public static CertifyFingerprintFragment newInstance(Uri dataUri, boolean enableWordConfirm) {
|
public static CertifyFingerprintFragment newInstance(Uri dataUri, boolean enablePhrasesConfirm) {
|
||||||
CertifyFingerprintFragment frag = new CertifyFingerprintFragment();
|
CertifyFingerprintFragment frag = new CertifyFingerprintFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putParcelable(ARG_DATA_URI, dataUri);
|
args.putParcelable(ARG_DATA_URI, dataUri);
|
||||||
args.putBoolean(ARG_ENABLE_WORD_CONFIRM, enableWordConfirm);
|
args.putBoolean(ARG_ENABLE_PHRASES_CONFIRM, enablePhrasesConfirm);
|
||||||
|
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
@@ -75,11 +79,12 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
|
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
|
||||||
View view = inflater.inflate(R.layout.certify_fingerprint_fragment, getContainer());
|
View view = inflater.inflate(R.layout.certify_fingerprint_fragment, getContainer());
|
||||||
|
|
||||||
View actionNo = view.findViewById(R.id.certify_fingerprint_button_no);
|
TextView actionNo = (TextView) view.findViewById(R.id.certify_fingerprint_button_no);
|
||||||
View actionYes = view.findViewById(R.id.certify_fingerprint_button_yes);
|
mActionYes = (TextView) view.findViewById(R.id.certify_fingerprint_button_yes);
|
||||||
|
|
||||||
mFingerprint = (TextView) view.findViewById(R.id.certify_fingerprint_fingerprint);
|
mFingerprint = (TextView) view.findViewById(R.id.certify_fingerprint_fingerprint);
|
||||||
mIntro = (TextView) view.findViewById(R.id.certify_fingerprint_intro);
|
mIntro = (TextView) view.findViewById(R.id.certify_fingerprint_intro);
|
||||||
|
mHeader = (TextView) view.findViewById(R.id.certify_fingerprint_fingerprint_header);
|
||||||
|
|
||||||
actionNo.setOnClickListener(new View.OnClickListener() {
|
actionNo.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -87,7 +92,7 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
actionYes.setOnClickListener(new View.OnClickListener() {
|
mActionYes.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
certify(mDataUri);
|
certify(mDataUri);
|
||||||
@@ -107,10 +112,12 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mEnableWordConfirm = getArguments().getBoolean(ARG_ENABLE_WORD_CONFIRM);
|
mEnablePhrasesConfirm = getArguments().getBoolean(ARG_ENABLE_PHRASES_CONFIRM);
|
||||||
|
|
||||||
if (mEnableWordConfirm) {
|
if (mEnablePhrasesConfirm) {
|
||||||
mIntro.setText(R.string.certify_fingerprint_text_words);
|
mIntro.setText(R.string.certify_fingerprint_text_phrases);
|
||||||
|
mHeader.setText(R.string.section_phrases);
|
||||||
|
mActionYes.setText(R.string.btn_match_phrases);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData(dataUri);
|
loadData(dataUri);
|
||||||
@@ -160,7 +167,7 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
if (data.moveToFirst()) {
|
if (data.moveToFirst()) {
|
||||||
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
|
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
|
||||||
|
|
||||||
if (mEnableWordConfirm) {
|
if (mEnablePhrasesConfirm) {
|
||||||
displayWordConfirm(fingerprintBlob);
|
displayWordConfirm(fingerprintBlob);
|
||||||
} else {
|
} else {
|
||||||
displayHexConfirm(fingerprintBlob);
|
displayHexConfirm(fingerprintBlob);
|
||||||
@@ -180,9 +187,16 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void displayWordConfirm(byte[] fingerprintBlob) {
|
private void displayWordConfirm(byte[] fingerprintBlob) {
|
||||||
String fingerprint = ExperimentalWordConfirm.getWords(getActivity(), fingerprintBlob);
|
// String fingerprint = ExperimentalWordConfirm.getWords(getActivity(), fingerprintBlob);
|
||||||
|
|
||||||
mFingerprint.setTextSize(24);
|
String fingerprint;
|
||||||
|
try {
|
||||||
|
fingerprint = new SentenceConfirm(getActivity()).fromBytes(fingerprintBlob, 16);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
fingerprint = "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
mFingerprint.setTextSize(18);
|
||||||
mFingerprint.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
|
mFingerprint.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
|
||||||
mFingerprint.setText(fingerprint);
|
mFingerprint.setText(fingerprint);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uris.add(intent.getData());
|
uris.add(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,6 @@ public class DecryptListFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpenPgpMetadata metadata = result.mMetadata.get(index);
|
OpenPgpMetadata metadata = result.mMetadata.get(index);
|
||||||
Uri saveUri = Uri.fromFile(activity.getExternalFilesDir(metadata.getMimeType()));
|
|
||||||
mCurrentSaveFileUri = result.getOutputUris().get(index);
|
mCurrentSaveFileUri = result.getOutputUris().get(index);
|
||||||
|
|
||||||
String filename = metadata.getFilename();
|
String filename = metadata.getFilename();
|
||||||
@@ -266,8 +265,8 @@ public class DecryptListFragment
|
|||||||
filename = "decrypted" + (ext != null ? "."+ext : "");
|
filename = "decrypted" + (ext != null ? "."+ext : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHelper.saveDocument(this, filename, saveUri, metadata.getMimeType(),
|
FileHelper.saveDocument(this, filename, metadata.getMimeType(),
|
||||||
R.string.title_decrypt_to_file, R.string.specify_file_to_decrypt_to, REQUEST_CODE_OUTPUT);
|
REQUEST_CODE_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveFile(Uri saveUri) {
|
private void saveFile(Uri saveUri) {
|
||||||
@@ -376,10 +375,12 @@ public class DecryptListFragment
|
|||||||
// noinspection deprecation, this should be called from Context, but not available in minSdk
|
// noinspection deprecation, this should be called from Context, but not available in minSdk
|
||||||
icon = getResources().getDrawable(R.drawable.ic_chat_black_24dp);
|
icon = getResources().getDrawable(R.drawable.ic_chat_black_24dp);
|
||||||
} else if (ClipDescription.compareMimeTypes(type, "image/*")) {
|
} else if (ClipDescription.compareMimeTypes(type, "image/*")) {
|
||||||
int px = FormattingUtils.dpToPx(context, 48);
|
int px = FormattingUtils.dpToPx(context, 32);
|
||||||
Bitmap bitmap = FileHelper.getThumbnail(context, outputUri, new Point(px, px));
|
Bitmap bitmap = FileHelper.getThumbnail(context, outputUri, new Point(px, px));
|
||||||
icon = new BitmapDrawable(context.getResources(), bitmap);
|
icon = new BitmapDrawable(context.getResources(), bitmap);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (icon == null) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setDataAndType(outputUri, type);
|
intent.setDataAndType(outputUri, type);
|
||||||
|
|
||||||
@@ -445,6 +446,7 @@ public class DecryptListFragment
|
|||||||
displayWithViewIntent(result, index, true, true);
|
displayWithViewIntent(result, index, true, true);
|
||||||
break;
|
break;
|
||||||
case R.id.decrypt_save:
|
case R.id.decrypt_save:
|
||||||
|
// only inside the menu xml for Android >= 4.4
|
||||||
saveFileDialog(result, index);
|
saveFileDialog(result, index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -224,9 +225,8 @@ public class EncryptFilesFragment
|
|||||||
String targetName =
|
String targetName =
|
||||||
(mEncryptFilenames ? "1" : FileHelper.getFilename(getActivity(), model.inputUri))
|
(mEncryptFilenames ? "1" : FileHelper.getFilename(getActivity(), model.inputUri))
|
||||||
+ (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
|
+ (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
|
||||||
Uri inputUri = model.inputUri;
|
FileHelper.saveDocument(this, targetName,
|
||||||
FileHelper.saveDocument(this, targetName, inputUri,
|
REQUEST_CODE_OUTPUT);
|
||||||
R.string.title_encrypt_to_file, R.string.specify_file_to_encrypt_to, REQUEST_CODE_OUTPUT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addFile(Intent data) {
|
public void addFile(Intent data) {
|
||||||
@@ -308,6 +308,17 @@ public class EncryptFilesFragment
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
|
super.onPrepareOptionsMenu(menu);
|
||||||
|
|
||||||
|
// Show save only on Android >= 4.4 (Document Provider)
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||||
|
MenuItem save = menu.findItem(R.id.encrypt_save);
|
||||||
|
save.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void toggleUseArmor(MenuItem item, final boolean useArmor) {
|
public void toggleUseArmor(MenuItem item, final boolean useArmor) {
|
||||||
|
|
||||||
mUseArmor = useArmor;
|
mUseArmor = useArmor;
|
||||||
@@ -441,9 +452,29 @@ public class EncryptFilesFragment
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepares mOutputUris, either directly and returns false, or indirectly
|
/**
|
||||||
// which returns true and will call cryptoOperation after mOutputUris has
|
* Checks that the input uris are not linked to our own internal storage.
|
||||||
// been set at a later point.
|
* This prevents the encryption of our own database (-> export of whole database)
|
||||||
|
*/
|
||||||
|
private void securityCheckInternalStorage() {
|
||||||
|
for (FilesAdapter.ViewModel model : mFilesAdapter.mDataset) {
|
||||||
|
File fileInput = new File(model.inputUri.getPath());
|
||||||
|
try {
|
||||||
|
// the canonical path of the file must not start with /data/data/org.sufficientlysecure.keychain/
|
||||||
|
if (fileInput.getCanonicalPath().startsWith(getActivity().getApplicationInfo().dataDir)) {
|
||||||
|
throw new RuntimeException("Encrypting OpenKeychain's private files is not allowed!");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(Constants.TAG, "Getting canonical path failed!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares mOutputUris, either directly and returns false, or indirectly
|
||||||
|
* which returns true and will call cryptoOperation after mOutputUris has
|
||||||
|
* been set at a later point.
|
||||||
|
*/
|
||||||
private boolean prepareOutputStreams() {
|
private boolean prepareOutputStreams() {
|
||||||
|
|
||||||
switch (mAfterEncryptAction) {
|
switch (mAfterEncryptAction) {
|
||||||
@@ -519,6 +550,8 @@ public class EncryptFilesFragment
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
securityCheckInternalStorage();
|
||||||
|
|
||||||
return actionsParcel;
|
return actionsParcel;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
|
|||||||
data.getBoolean(AddEditKeyserverDialogFragment.MESSAGE_VERIFIED);
|
data.getBoolean(AddEditKeyserverDialogFragment.MESSAGE_VERIFIED);
|
||||||
if (verified) {
|
if (verified) {
|
||||||
Notify.create(getActivity(),
|
Notify.create(getActivity(),
|
||||||
R.string.add_keyserver_verified, Notify.Style.OK).show();
|
R.string.add_keyserver_connection_verified, Notify.Style.OK).show();
|
||||||
} else {
|
} else {
|
||||||
Notify.create(getActivity(),
|
Notify.create(getActivity(),
|
||||||
R.string.add_keyserver_without_verification,
|
R.string.add_keyserver_without_verification,
|
||||||
@@ -177,26 +177,6 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AddEditKeyserverDialogFragment.MESSAGE_VERIFICATION_FAILED: {
|
|
||||||
AddEditKeyserverDialogFragment.FailureReason failureReason =
|
|
||||||
(AddEditKeyserverDialogFragment.FailureReason) data.getSerializable(
|
|
||||||
AddEditKeyserverDialogFragment.MESSAGE_FAILURE_REASON);
|
|
||||||
switch (failureReason) {
|
|
||||||
case CONNECTION_FAILED: {
|
|
||||||
Notify.create(getActivity(),
|
|
||||||
R.string.add_keyserver_connection_failed,
|
|
||||||
Notify.Style.ERROR).show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INVALID_URL: {
|
|
||||||
Notify.create(getActivity(),
|
|
||||||
R.string.add_keyserver_invalid_url,
|
|
||||||
Notify.Style.ERROR).show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
|||||||
View vFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
|
View vFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
|
||||||
View vFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
|
View vFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
|
||||||
View vKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
|
View vKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
|
||||||
View vKeySafeButton = view.findViewById(R.id.view_key_action_key_export);
|
View vKeySaveButton = view.findViewById(R.id.view_key_action_key_export);
|
||||||
View vKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc);
|
View vKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc);
|
||||||
View vKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
|
View vKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
|
||||||
ImageButton vKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
|
ImageButton vKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
|
||||||
@@ -133,7 +133,11 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
|||||||
share(false, false);
|
share(false, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
vKeySafeButton.setOnClickListener(new View.OnClickListener() {
|
// Show save only on Android >= 4.4 (Document Provider)
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||||
|
vKeySaveButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
vKeySaveButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
exportToFile();
|
exportToFile();
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import android.widget.TableRow;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.textuality.keybase.lib.KeybaseException;
|
import com.textuality.keybase.lib.KeybaseException;
|
||||||
|
import com.textuality.keybase.lib.KeybaseQuery;
|
||||||
import com.textuality.keybase.lib.Proof;
|
import com.textuality.keybase.lib.Proof;
|
||||||
import com.textuality.keybase.lib.User;
|
import com.textuality.keybase.lib.User;
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
|
|||||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.OkHttpKeybaseClient;
|
||||||
import org.sufficientlysecure.keychain.util.ParcelableProxy;
|
import org.sufficientlysecure.keychain.util.ParcelableProxy;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
|
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
|
||||||
@@ -224,8 +226,9 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for evidence from keybase in the background, make tabular version of result
|
/**
|
||||||
//
|
* look for evidence from keybase in the background, make tabular version of result
|
||||||
|
*/
|
||||||
private class DescribeKey extends AsyncTask<String, Void, ResultPage> {
|
private class DescribeKey extends AsyncTask<String, Void, ResultPage> {
|
||||||
ParcelableProxy mParcelableProxy;
|
ParcelableProxy mParcelableProxy;
|
||||||
|
|
||||||
@@ -240,7 +243,9 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
final ArrayList<CharSequence> proofList = new ArrayList<CharSequence>();
|
final ArrayList<CharSequence> proofList = new ArrayList<CharSequence>();
|
||||||
final Hashtable<Integer, ArrayList<Proof>> proofs = new Hashtable<Integer, ArrayList<Proof>>();
|
final Hashtable<Integer, ArrayList<Proof>> proofs = new Hashtable<Integer, ArrayList<Proof>>();
|
||||||
try {
|
try {
|
||||||
User keybaseUser = User.findByFingerprint(fingerprint, mParcelableProxy.getProxy());
|
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
|
||||||
|
keybaseQuery.setProxy(mParcelableProxy.getProxy());
|
||||||
|
User keybaseUser = User.findByFingerprint(keybaseQuery, fingerprint);
|
||||||
for (Proof proof : keybaseUser.getProofs()) {
|
for (Proof proof : keybaseUser.getProofs()) {
|
||||||
Integer proofType = proof.getType();
|
Integer proofType = proof.getType();
|
||||||
appendIfOK(proofs, proofType, proof);
|
appendIfOK(proofs, proofType, proof);
|
||||||
@@ -266,7 +271,12 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
} catch (KeybaseException ignored) {
|
} catch (KeybaseException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResultPage(getString(R.string.key_trust_results_prefix), proofList);
|
String prefix = "";
|
||||||
|
if (isAdded()) {
|
||||||
|
prefix = getString(R.string.key_trust_results_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ResultPage(prefix, proofList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpannableStringBuilder formatSpannableString(SpannableStringBuilder proofLinks, String proofType) {
|
private SpannableStringBuilder formatSpannableString(SpannableStringBuilder proofLinks, String proofType) {
|
||||||
@@ -291,7 +301,10 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
if (haveProofFor(proof.getType())) {
|
if (haveProofFor(proof.getType())) {
|
||||||
ssb.append("\u00a0[");
|
ssb.append("\u00a0[");
|
||||||
startAt = ssb.length();
|
startAt = ssb.length();
|
||||||
String verify = getString(R.string.keybase_verify);
|
String verify = "";
|
||||||
|
if (isAdded()) {
|
||||||
|
verify = getString(R.string.keybase_verify);
|
||||||
|
}
|
||||||
ssb.append(verify);
|
ssb.append(verify);
|
||||||
ClickableSpan clicker = new ClickableSpan() {
|
ClickableSpan clicker = new ClickableSpan() {
|
||||||
@Override
|
@Override
|
||||||
@@ -308,6 +321,11 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(ResultPage result) {
|
protected void onPostExecute(ResultPage result) {
|
||||||
super.onPostExecute(result);
|
super.onPostExecute(result);
|
||||||
|
// stop if fragment is no longer added to an activity
|
||||||
|
if(!isAdded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.mProofs.isEmpty()) {
|
if (result.mProofs.isEmpty()) {
|
||||||
result.mHeader = getActivity().getString(R.string.key_trust_no_cloud_evidence);
|
result.mHeader = getActivity().getString(R.string.key_trust_no_cloud_evidence);
|
||||||
}
|
}
|
||||||
@@ -356,7 +374,12 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
|
|||||||
default:
|
default:
|
||||||
stringIndex = R.string.keybase_narrative_unknown;
|
stringIndex = R.string.keybase_narrative_unknown;
|
||||||
}
|
}
|
||||||
return getActivity().getString(stringIndex);
|
|
||||||
|
if (isAdded()) {
|
||||||
|
return getString(stringIndex);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) throws KeybaseException {
|
private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) throws KeybaseException {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.net.URI;
|
|||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
@@ -44,6 +45,7 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
@@ -54,6 +56,7 @@ import com.squareup.okhttp.Request;
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
|
import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
|
||||||
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import org.sufficientlysecure.keychain.util.TlsHelper;
|
import org.sufficientlysecure.keychain.util.TlsHelper;
|
||||||
@@ -68,11 +71,9 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
private static final String ARG_KEYSERVER = "arg_keyserver";
|
private static final String ARG_KEYSERVER = "arg_keyserver";
|
||||||
|
|
||||||
public static final int MESSAGE_OKAY = 1;
|
public static final int MESSAGE_OKAY = 1;
|
||||||
public static final int MESSAGE_VERIFICATION_FAILED = 2;
|
|
||||||
|
|
||||||
public static final String MESSAGE_KEYSERVER = "new_keyserver";
|
public static final String MESSAGE_KEYSERVER = "new_keyserver";
|
||||||
public static final String MESSAGE_VERIFIED = "verified";
|
public static final String MESSAGE_VERIFIED = "verified";
|
||||||
public static final String MESSAGE_FAILURE_REASON = "failure_reason";
|
|
||||||
public static final String MESSAGE_KEYSERVER_DELETED = "keyserver_deleted";
|
public static final String MESSAGE_KEYSERVER_DELETED = "keyserver_deleted";
|
||||||
public static final String MESSAGE_DIALOG_ACTION = "message_dialog_action";
|
public static final String MESSAGE_DIALOG_ACTION = "message_dialog_action";
|
||||||
public static final String MESSAGE_EDIT_POSITION = "keyserver_edited_position";
|
public static final String MESSAGE_EDIT_POSITION = "keyserver_edited_position";
|
||||||
@@ -82,7 +83,9 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
private int mPosition;
|
private int mPosition;
|
||||||
|
|
||||||
private EditText mKeyserverEditText;
|
private EditText mKeyserverEditText;
|
||||||
|
private TextInputLayout mKeyserverEditTextLayout;
|
||||||
private CheckBox mVerifyKeyserverCheckBox;
|
private CheckBox mVerifyKeyserverCheckBox;
|
||||||
|
private CheckBox mOnlyTrustedKeyserverCheckBox;
|
||||||
|
|
||||||
public enum DialogAction {
|
public enum DialogAction {
|
||||||
ADD,
|
ADD,
|
||||||
@@ -91,7 +94,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
|
|
||||||
public enum FailureReason {
|
public enum FailureReason {
|
||||||
INVALID_URL,
|
INVALID_URL,
|
||||||
CONNECTION_FAILED
|
CONNECTION_FAILED,
|
||||||
|
NO_PINNED_CERTIFICATE
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AddEditKeyserverDialogFragment newInstance(Messenger messenger,
|
public static AddEditKeyserverDialogFragment newInstance(Messenger messenger,
|
||||||
@@ -126,7 +130,15 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
alert.setView(view);
|
alert.setView(view);
|
||||||
|
|
||||||
mKeyserverEditText = (EditText) view.findViewById(R.id.keyserver_url_edit_text);
|
mKeyserverEditText = (EditText) view.findViewById(R.id.keyserver_url_edit_text);
|
||||||
mVerifyKeyserverCheckBox = (CheckBox) view.findViewById(R.id.verify_keyserver_checkbox);
|
mKeyserverEditTextLayout = (TextInputLayout) view.findViewById(R.id.keyserver_url_edit_text_layout);
|
||||||
|
mVerifyKeyserverCheckBox = (CheckBox) view.findViewById(R.id.verify_connection_checkbox);
|
||||||
|
mOnlyTrustedKeyserverCheckBox = (CheckBox) view.findViewById(R.id.only_trusted_keyserver_checkbox);
|
||||||
|
mVerifyKeyserverCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
mOnlyTrustedKeyserverCheckBox.setEnabled(isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
switch (mDialogAction) {
|
switch (mDialogAction) {
|
||||||
case ADD: {
|
case ADD: {
|
||||||
@@ -212,6 +224,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
positiveButton.setOnClickListener(new View.OnClickListener() {
|
positiveButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
mKeyserverEditTextLayout.setErrorEnabled(false);
|
||||||
|
|
||||||
// behaviour same for edit and add
|
// behaviour same for edit and add
|
||||||
final String keyserverUrl = mKeyserverEditText.getText().toString();
|
final String keyserverUrl = mKeyserverEditText.getText().toString();
|
||||||
if (mVerifyKeyserverCheckBox.isChecked()) {
|
if (mVerifyKeyserverCheckBox.isChecked()) {
|
||||||
@@ -220,13 +234,20 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
|
OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
|
||||||
@Override
|
@Override
|
||||||
public void onOrbotStarted() {
|
public void onOrbotStarted() {
|
||||||
verifyConnection(keyserverUrl,
|
verifyConnection(
|
||||||
proxyPrefs.parcelableProxy.getProxy());
|
keyserverUrl,
|
||||||
|
proxyPrefs.parcelableProxy.getProxy(),
|
||||||
|
mOnlyTrustedKeyserverCheckBox.isChecked()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNeutralButton() {
|
public void onNeutralButton() {
|
||||||
verifyConnection(keyserverUrl, null);
|
verifyConnection(
|
||||||
|
keyserverUrl,
|
||||||
|
null,
|
||||||
|
mOnlyTrustedKeyserverCheckBox.isChecked()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -236,7 +257,11 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
|
if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
|
||||||
verifyConnection(keyserverUrl, proxyPrefs.parcelableProxy.getProxy());
|
verifyConnection(
|
||||||
|
keyserverUrl,
|
||||||
|
proxyPrefs.parcelableProxy.getProxy(),
|
||||||
|
mOnlyTrustedKeyserverCheckBox.isChecked()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dismiss();
|
dismiss();
|
||||||
@@ -272,14 +297,28 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
sendMessageToHandler(MESSAGE_OKAY, data);
|
sendMessageToHandler(MESSAGE_OKAY, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verificationFailed(FailureReason reason) {
|
public void verificationFailed(FailureReason failureReason) {
|
||||||
Bundle data = new Bundle();
|
switch (failureReason) {
|
||||||
data.putSerializable(MESSAGE_FAILURE_REASON, reason);
|
case CONNECTION_FAILED: {
|
||||||
|
mKeyserverEditTextLayout.setError(
|
||||||
sendMessageToHandler(MESSAGE_VERIFICATION_FAILED, data);
|
getString(R.string.add_keyserver_connection_failed));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INVALID_URL: {
|
||||||
|
mKeyserverEditTextLayout.setError(
|
||||||
|
getString(R.string.add_keyserver_invalid_url));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NO_PINNED_CERTIFICATE: {
|
||||||
|
mKeyserverEditTextLayout.setError(
|
||||||
|
getString(R.string.add_keyserver_keyserver_not_trusted));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyConnection(String keyserver, final Proxy proxy) {
|
}
|
||||||
|
|
||||||
|
public void verifyConnection(String keyserver, final Proxy proxy, final boolean onlyTrustedKeyserver) {
|
||||||
|
|
||||||
new AsyncTask<String, Void, FailureReason>() {
|
new AsyncTask<String, Void, FailureReason>() {
|
||||||
ProgressDialog mProgressDialog;
|
ProgressDialog mProgressDialog;
|
||||||
@@ -288,7 +327,7 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
mProgressDialog = new ProgressDialog(getActivity());
|
mProgressDialog = new ProgressDialog(getActivity());
|
||||||
mProgressDialog.setMessage(getString(R.string.progress_verifying_keyserver_url));
|
mProgressDialog.setMessage(getString(R.string.progress_verifying_keyserver_connection));
|
||||||
mProgressDialog.setCancelable(false);
|
mProgressDialog.setCancelable(false);
|
||||||
mProgressDialog.show();
|
mProgressDialog.show();
|
||||||
}
|
}
|
||||||
@@ -316,7 +355,18 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
|
|||||||
Log.d("Converted URL", newKeyserver.toString());
|
Log.d("Converted URL", newKeyserver.toString());
|
||||||
|
|
||||||
OkHttpClient client = HkpKeyserver.getClient(newKeyserver.toURL(), proxy);
|
OkHttpClient client = HkpKeyserver.getClient(newKeyserver.toURL(), proxy);
|
||||||
TlsHelper.pinCertificateIfNecessary(client, newKeyserver.toURL());
|
|
||||||
|
// don't follow any redirects
|
||||||
|
client.setFollowRedirects(false);
|
||||||
|
client.setFollowSslRedirects(false);
|
||||||
|
|
||||||
|
if (onlyTrustedKeyserver
|
||||||
|
&& !TlsHelper.usePinnedCertificateIfAvailable(client, newKeyserver.toURL())) {
|
||||||
|
Log.w(Constants.TAG, "No pinned certificate for this host in OpenKeychain's assets.");
|
||||||
|
reason = FailureReason.NO_PINNED_CERTIFICATE;
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
client.newCall(new Request.Builder().url(newKeyserver.toURL()).build()).execute();
|
client.newCall(new Request.Builder().url(newKeyserver.toURL()).build()).execute();
|
||||||
} catch (TlsHelper.TlsHelperException e) {
|
} catch (TlsHelper.TlsHelperException e) {
|
||||||
reason = FailureReason.CONNECTION_FAILED;
|
reason = FailureReason.CONNECTION_FAILED;
|
||||||
|
|||||||
@@ -1,234 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.Messenger;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.support.v4.app.DialogFragment;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
|
||||||
import org.sufficientlysecure.keychain.util.FileHelper;
|
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a file chooser dialog no longer used with KitKat
|
|
||||||
*/
|
|
||||||
public class FileDialogFragment extends DialogFragment {
|
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
|
||||||
private static final String ARG_TITLE = "title";
|
|
||||||
private static final String ARG_MESSAGE = "message";
|
|
||||||
private static final String ARG_DEFAULT_FILE = "default_file";
|
|
||||||
private static final String ARG_CHECKBOX_TEXT = "checkbox_text";
|
|
||||||
|
|
||||||
public static final int MESSAGE_OKAY = 1;
|
|
||||||
|
|
||||||
public static final String MESSAGE_DATA_FILE = "file";
|
|
||||||
public static final String MESSAGE_DATA_CHECKED = "checked";
|
|
||||||
|
|
||||||
private Messenger mMessenger;
|
|
||||||
|
|
||||||
private EditText mFilename;
|
|
||||||
private ImageButton mBrowse;
|
|
||||||
private CheckBox mCheckBox;
|
|
||||||
private TextView mMessageTextView;
|
|
||||||
|
|
||||||
private File mFile;
|
|
||||||
|
|
||||||
private static final int REQUEST_CODE = 0x00007004;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new instance of this file dialog fragment
|
|
||||||
*/
|
|
||||||
public static FileDialogFragment newInstance(Messenger messenger, String title, String message,
|
|
||||||
File defaultFile, String checkboxText) {
|
|
||||||
FileDialogFragment frag = new FileDialogFragment();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putParcelable(ARG_MESSENGER, messenger);
|
|
||||||
|
|
||||||
args.putString(ARG_TITLE, title);
|
|
||||||
args.putString(ARG_MESSAGE, message);
|
|
||||||
args.putString(ARG_DEFAULT_FILE, defaultFile.getAbsolutePath());
|
|
||||||
args.putString(ARG_CHECKBOX_TEXT, checkboxText);
|
|
||||||
|
|
||||||
frag.setArguments(args);
|
|
||||||
|
|
||||||
return frag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates dialog
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
final Activity activity = getActivity();
|
|
||||||
|
|
||||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
|
||||||
|
|
||||||
String title = getArguments().getString(ARG_TITLE);
|
|
||||||
String message = getArguments().getString(ARG_MESSAGE);
|
|
||||||
mFile = new File(getArguments().getString(ARG_DEFAULT_FILE));
|
|
||||||
if (!mFile.isAbsolute()) {
|
|
||||||
// We use OK dir by default
|
|
||||||
mFile = new File(Constants.Path.APP_DIR.getAbsolutePath(), mFile.getName());
|
|
||||||
}
|
|
||||||
String checkboxText = getArguments().getString(ARG_CHECKBOX_TEXT);
|
|
||||||
|
|
||||||
LayoutInflater inflater = (LayoutInflater) activity
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
|
||||||
alert.setTitle(title);
|
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.file_dialog, null);
|
|
||||||
|
|
||||||
mMessageTextView = (TextView) view.findViewById(R.id.message);
|
|
||||||
mMessageTextView.setText(message);
|
|
||||||
|
|
||||||
mFilename = (EditText) view.findViewById(R.id.input);
|
|
||||||
mFilename.setText(mFile.getName());
|
|
||||||
mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
|
||||||
mBrowse.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
mBrowse.setOnClickListener(new View.OnClickListener() {
|
|
||||||
public void onClick(View v) {
|
|
||||||
// only .asc or .gpg files
|
|
||||||
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
|
|
||||||
// or gpg types!
|
|
||||||
FileHelper.saveDocumentKitKat(
|
|
||||||
FileDialogFragment.this, "*/*", mFile.getName(), REQUEST_CODE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mCheckBox = (CheckBox) view.findViewById(R.id.checkbox);
|
|
||||||
if (checkboxText == null) {
|
|
||||||
mCheckBox.setEnabled(false);
|
|
||||||
mCheckBox.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
mCheckBox.setEnabled(true);
|
|
||||||
mCheckBox.setVisibility(View.VISIBLE);
|
|
||||||
mCheckBox.setText(checkboxText);
|
|
||||||
mCheckBox.setChecked(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
alert.setView(view);
|
|
||||||
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
dismiss();
|
|
||||||
|
|
||||||
String currentFilename = mFilename.getText().toString();
|
|
||||||
if (currentFilename == null || currentFilename.isEmpty()) {
|
|
||||||
// No file is like pressing cancel, UI: maybe disable positive button in this case?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFile == null || currentFilename.startsWith("/")) {
|
|
||||||
mFile = new File(currentFilename);
|
|
||||||
} else if (!mFile.getName().equals(currentFilename)) {
|
|
||||||
// We update our File object if user changed name!
|
|
||||||
mFile = new File(mFile.getParentFile(), currentFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean checked = mCheckBox.isEnabled() && mCheckBox.isChecked();
|
|
||||||
|
|
||||||
// return resulting data back to activity
|
|
||||||
Bundle data = new Bundle();
|
|
||||||
data.putString(MESSAGE_DATA_FILE, mFile.getAbsolutePath());
|
|
||||||
data.putBoolean(MESSAGE_DATA_CHECKED, checked);
|
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_OKAY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return alert.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
switch (requestCode & 0xFFFF) {
|
|
||||||
case REQUEST_CODE: {
|
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
||||||
File file = new File(data.getData().getPath());
|
|
||||||
if (file.getParentFile().exists()) {
|
|
||||||
mFile = file;
|
|
||||||
mFilename.setText(mFile.getName());
|
|
||||||
} else {
|
|
||||||
Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send message back to handler which is initialized in a activity
|
|
||||||
*
|
|
||||||
* @param what Message integer you want to send
|
|
||||||
*/
|
|
||||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
|
||||||
Message msg = Message.obtain();
|
|
||||||
msg.what = what;
|
|
||||||
if (data != null) {
|
|
||||||
msg.setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
mMessenger.send(msg);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,6 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
|
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
|
||||||
@@ -35,7 +34,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
import org.sufficientlysecure.keychain.util.FileHelper;
|
import org.sufficientlysecure.keychain.util.FileHelper;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@@ -134,9 +132,10 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
|
|||||||
|
|
||||||
String targetName = "pgpkey.txt";
|
String targetName = "pgpkey.txt";
|
||||||
|
|
||||||
|
// TODO: not supported on Android < 4.4
|
||||||
FileHelper.saveDocument(this,
|
FileHelper.saveDocument(this,
|
||||||
targetName, Uri.fromFile(new File(Constants.Path.APP_DIR, targetName)),
|
targetName,
|
||||||
"text/plain", R.string.title_decrypt_to_file, R.string.specify_file_to_decrypt_to,
|
"text/plain",
|
||||||
REQUEST_CODE_OUTPUT);
|
REQUEST_CODE_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,8 +103,7 @@ public class EmailKeyHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Keyserver.QueryFailedException ignored) {
|
} catch (Keyserver.CloudSearchFailureException ignored) {
|
||||||
} catch (Keyserver.QueryNeedsRepairException ignored) {
|
|
||||||
}
|
}
|
||||||
return new ArrayList<>(keys);
|
return new ArrayList<>(keys);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,13 +69,14 @@ public class ExportHelper
|
|||||||
: R.string.specify_backup_dest_single);
|
: R.string.specify_backup_dest_single);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHelper.saveDocumentDialog(new FileHelper.FileDialogCallback() {
|
// TODO: for valodim
|
||||||
@Override
|
// FileHelper.saveDocumentDialog(new FileHelper.FileDialogCallback() {
|
||||||
public void onFileSelected(File file, boolean checked) {
|
// @Override
|
||||||
mExportFile = file;
|
// public void onFileSelected(File file, boolean checked) {
|
||||||
exportKeys(masterKeyId == null ? null : new long[] { masterKeyId }, exportSecret);
|
// mExportFile = file;
|
||||||
}
|
// exportKeys(masterKeyId == null ? null : new long[] { masterKeyId }, exportSecret);
|
||||||
}, mActivity.getSupportFragmentManager(), title, message, exportFile, null);
|
// }
|
||||||
|
// }, mActivity.getSupportFragmentManager(), title, message, exportFile, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: If ExportHelper requires pending data (see CryptoOPerationHelper), activities using
|
// TODO: If ExportHelper requires pending data (see CryptoOPerationHelper), activities using
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.sufficientlysecure.keychain.util;
|
package org.sufficientlysecure.keychain.util;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -30,20 +29,13 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.Messenger;
|
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -82,52 +74,26 @@ import java.text.DecimalFormat;
|
|||||||
public class FileHelper {
|
public class FileHelper {
|
||||||
|
|
||||||
public static void openDocument(Fragment fragment, Uri last, String mimeType, boolean multiple, int requestCode) {
|
public static void openDocument(Fragment fragment, Uri last, String mimeType, boolean multiple, int requestCode) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
openDocumentPreKitKat(fragment, last, mimeType, multiple, requestCode);
|
|
||||||
} else {
|
|
||||||
openDocumentKitKat(fragment, mimeType, multiple, requestCode);
|
openDocumentKitKat(fragment, mimeType, multiple, requestCode);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveDocument(Fragment fragment, String targetName, Uri inputUri,
|
|
||||||
@StringRes int title, @StringRes int message, int requestCode) {
|
|
||||||
saveDocument(fragment, targetName, inputUri, "*/*", title, message, requestCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveDocument(Fragment fragment, String targetName, Uri inputUri, String mimeType,
|
|
||||||
@StringRes int title, @StringRes int message, int requestCode) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
|
||||||
saveDocumentDialog(fragment, targetName, inputUri, title, message, requestCode);
|
|
||||||
} else {
|
} else {
|
||||||
|
openDocumentPreKitKat(fragment, last, mimeType, multiple, requestCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveDocument(Fragment fragment, String targetName, int requestCode) {
|
||||||
|
saveDocument(fragment, targetName, "*/*", requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveDocument(Fragment fragment, String targetName, String mimeType,
|
||||||
|
int requestCode) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
saveDocumentKitKat(fragment, mimeType, targetName, requestCode);
|
saveDocumentKitKat(fragment, mimeType, targetName, requestCode);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("saveDocument does not support Android < 4.4!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
|
|
||||||
@StringRes int title, @StringRes int message, final int requestCode) {
|
|
||||||
|
|
||||||
saveDocumentDialog(fragment, targetName, inputUri, title, message, new FileDialogCallback() {
|
|
||||||
// is this a good idea? seems hacky...
|
|
||||||
@Override
|
|
||||||
public void onFileSelected(File file, boolean checked) {
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setData(Uri.fromFile(file));
|
|
||||||
fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
|
|
||||||
@StringRes int title, @StringRes int message, FileDialogCallback callback) {
|
|
||||||
|
|
||||||
File file = inputUri == null ? null : new File(inputUri.getPath());
|
|
||||||
File parentDir = file != null && file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
|
|
||||||
File targetFile = new File(parentDir, targetName);
|
|
||||||
saveDocumentDialog(callback, fragment.getActivity().getSupportFragmentManager(),
|
|
||||||
fragment.getString(title), fragment.getString(message), targetFile, null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Opens the preferred installed file manager on Android and shows a toast
|
/** Opens the preferred installed file manager on Android and shows a toast
|
||||||
* if no manager is installed. */
|
* if no manager is installed. */
|
||||||
private static void openDocumentPreKitKat(
|
private static void openDocumentPreKitKat(
|
||||||
@@ -172,36 +138,6 @@ public class FileHelper {
|
|||||||
fragment.startActivityForResult(intent, requestCode);
|
fragment.startActivityForResult(intent, requestCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveDocumentDialog(
|
|
||||||
final FileDialogCallback callback, final FragmentManager fragmentManager,
|
|
||||||
final String title, final String message, final File defaultFile,
|
|
||||||
final String checkMsg) {
|
|
||||||
// Message is received after file is selected
|
|
||||||
Handler returnHandler = new Handler() {
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message message) {
|
|
||||||
if (message.what == FileDialogFragment.MESSAGE_OKAY) {
|
|
||||||
callback.onFileSelected(
|
|
||||||
new File(message.getData().getString(FileDialogFragment.MESSAGE_DATA_FILE)),
|
|
||||||
message.getData().getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a new Messenger for the communication back
|
|
||||||
final Messenger messenger = new Messenger(returnHandler);
|
|
||||||
|
|
||||||
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
FileDialogFragment fileDialog = FileDialogFragment.newInstance(messenger, title, message,
|
|
||||||
defaultFile, checkMsg);
|
|
||||||
|
|
||||||
fileDialog.show(fragmentManager, "fileDialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFilename(Context context, Uri uri) {
|
public static String getFilename(Context context, Uri uri) {
|
||||||
String filename = null;
|
String filename = null;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.sufficientlysecure.keychain.util;
|
package org.sufficientlysecure.keychain.util;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ public class NfcHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void onPostExecute(Void unused) {
|
protected void onPostExecute(Void unused) {
|
||||||
|
if (mActivity.isFinishing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Register callback to set NDEF message
|
// Register callback to set NDEF message
|
||||||
mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
|
mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
|
||||||
mActivity);
|
mActivity);
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sufficientlysecure.keychain.util;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
|
import com.squareup.okhttp.OkUrlFactory;
|
||||||
|
import com.textuality.keybase.lib.KeybaseUrlConnectionClient;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for Keybase Lib
|
||||||
|
*/
|
||||||
|
public class OkHttpKeybaseClient implements KeybaseUrlConnectionClient {
|
||||||
|
|
||||||
|
private final OkUrlFactory factory;
|
||||||
|
|
||||||
|
private static OkUrlFactory generateUrlFactory() {
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
return new OkUrlFactory(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OkHttpKeybaseClient() {
|
||||||
|
factory = generateUrlFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URLConnection openConnection(URL url) throws IOException {
|
||||||
|
return openConnection(url, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URLConnection openConnection(URL url, Proxy proxy) throws IOException {
|
||||||
|
if (proxy != null) {
|
||||||
|
factory.client().setProxy(proxy);
|
||||||
|
factory.client().setConnectTimeout(30000, TimeUnit.MILLISECONDS);
|
||||||
|
factory.client().setReadTimeout(40000, TimeUnit.MILLISECONDS);
|
||||||
|
} else {
|
||||||
|
factory.client().setConnectTimeout(5000, TimeUnit.MILLISECONDS);
|
||||||
|
factory.client().setReadTimeout(25000, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.client().setFollowSslRedirects(false);
|
||||||
|
|
||||||
|
// forced the usage of keybase.io pinned certificate
|
||||||
|
try {
|
||||||
|
if (!TlsHelper.usePinnedCertificateIfAvailable(factory.client(), url)) {
|
||||||
|
throw new IOException("no pinned certificate found for URL!");
|
||||||
|
}
|
||||||
|
} catch (TlsHelper.TlsHelperException e) {
|
||||||
|
Log.e(Constants.TAG, "TlsHelper failed", e);
|
||||||
|
throw new IOException("TlsHelper failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory.open(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
* Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.util;
|
|||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@@ -37,7 +38,6 @@ import java.security.cert.CertificateFactory;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
@@ -49,15 +49,14 @@ public class TlsHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, byte[]> sStaticCA = new HashMap<>();
|
private static Map<String, byte[]> sPinnedCertificates = new HashMap<>();
|
||||||
|
|
||||||
public static void addStaticCA(String domain, byte[] certificate) {
|
/**
|
||||||
sStaticCA.put(domain, certificate);
|
* Add certificate from assets to pinned certificate map.
|
||||||
}
|
*/
|
||||||
|
public static void addPinnedCertificate(String host, AssetManager assetManager, String cerFilename) {
|
||||||
public static void addStaticCA(String domain, AssetManager assetManager, String name) {
|
|
||||||
try {
|
try {
|
||||||
InputStream is = assetManager.open(name);
|
InputStream is = assetManager.open(cerFilename);
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
int reads = is.read();
|
int reads = is.read();
|
||||||
|
|
||||||
@@ -68,27 +67,36 @@ public class TlsHelper {
|
|||||||
|
|
||||||
is.close();
|
is.close();
|
||||||
|
|
||||||
addStaticCA(domain, baos.toByteArray());
|
sPinnedCertificates.put(host, baos.toByteArray());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(Constants.TAG, e);
|
Log.w(Constants.TAG, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pinCertificateIfNecessary(OkHttpClient client, URL url) throws TlsHelperException, IOException {
|
/**
|
||||||
|
* Use pinned certificate for OkHttpClient if we have one.
|
||||||
|
*
|
||||||
|
* @return true, if certificate is available, false if not
|
||||||
|
* @throws TlsHelperException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static boolean usePinnedCertificateIfAvailable(OkHttpClient client, URL url) throws TlsHelperException, IOException {
|
||||||
if (url.getProtocol().equals("https")) {
|
if (url.getProtocol().equals("https")) {
|
||||||
for (String domain : sStaticCA.keySet()) {
|
// use certificate PIN from assets if we have one
|
||||||
if (url.getHost().endsWith(domain)) {
|
for (String host : sPinnedCertificates.keySet()) {
|
||||||
pinCertificate(sStaticCA.get(domain), client);
|
if (url.getHost().endsWith(host)) {
|
||||||
|
pinCertificate(sPinnedCertificates.get(host), client);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifies the client to accept only requests with a given certificate. Applies to all URLs requested by the
|
* Modifies the client to accept only requests with a given certificate. Applies to all URLs requested by the
|
||||||
* client.
|
* client.
|
||||||
* Therefore a client that is pinned this way should be used to only make requests to URLs with passed certificate.
|
* Therefore a client that is pinned this way should be used to only make requests to URLs with passed certificate.
|
||||||
* TODO: Refactor - More like SSH StrictHostKeyChecking than pinning?
|
|
||||||
*
|
*
|
||||||
* @param certificate certificate to pin
|
* @param certificate certificate to pin
|
||||||
* @param client OkHttpClient to enforce pinning on
|
* @param client OkHttpClient to enforce pinning on
|
||||||
@@ -97,8 +105,10 @@ public class TlsHelper {
|
|||||||
*/
|
*/
|
||||||
private static void pinCertificate(byte[] certificate, OkHttpClient client)
|
private static void pinCertificate(byte[] certificate, OkHttpClient client)
|
||||||
throws TlsHelperException, IOException {
|
throws TlsHelperException, IOException {
|
||||||
// We don't use OkHttp's CertificatePinner since it depends on a TrustManager to verify it too. Refer to
|
// We don't use OkHttp's CertificatePinner since it can not be used to pin self-signed
|
||||||
// note at end of description: http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html
|
// certificate if such certificate is not accepted by TrustManager.
|
||||||
|
// (Refer to note at end of description:
|
||||||
|
// http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html )
|
||||||
// Creating our own TrustManager that trusts only our certificate eliminates the need for certificate pinning
|
// Creating our own TrustManager that trusts only our certificate eliminates the need for certificate pinning
|
||||||
try {
|
try {
|
||||||
// Load CA
|
// Load CA
|
||||||
@@ -126,42 +136,4 @@ public class TlsHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens a Connection that will only accept certificates signed with a specific CA and skips common name check.
|
|
||||||
* This is required for some distributed Keyserver networks like sks-keyservers.net
|
|
||||||
*
|
|
||||||
* @param certificate The X.509 certificate used to sign the servers certificate
|
|
||||||
* @param url Connection target
|
|
||||||
*/
|
|
||||||
public static HttpsURLConnection openCAConnection(byte[] certificate, URL url)
|
|
||||||
throws TlsHelperException, IOException {
|
|
||||||
try {
|
|
||||||
// Load CA
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate));
|
|
||||||
|
|
||||||
// Create a KeyStore containing our trusted CAs
|
|
||||||
String keyStoreType = KeyStore.getDefaultType();
|
|
||||||
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
|
|
||||||
keyStore.load(null, null);
|
|
||||||
keyStore.setCertificateEntry("ca", ca);
|
|
||||||
|
|
||||||
// Create a TrustManager that trusts the CAs in our KeyStore
|
|
||||||
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
|
||||||
tmf.init(keyStore);
|
|
||||||
|
|
||||||
// Create an SSLContext that uses our TrustManager
|
|
||||||
SSLContext context = SSLContext.getInstance("TLS");
|
|
||||||
context.init(null, tmf.getTrustManagers(), null);
|
|
||||||
|
|
||||||
// Tell the URLConnection to use a SocketFactory from our SSLContext
|
|
||||||
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
|
|
||||||
urlConnection.setSSLSocketFactory(context.getSocketFactory());
|
|
||||||
|
|
||||||
return urlConnection;
|
|
||||||
} catch (CertificateException | KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) {
|
|
||||||
throw new TlsHelperException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
OpenKeychain/src/main/res/drawable-hdpi/ic_check_black_24dp.png
Normal file
BIN
OpenKeychain/src/main/res/drawable-hdpi/ic_check_black_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 169 B |
BIN
OpenKeychain/src/main/res/drawable-mdpi/ic_check_black_24dp.png
Normal file
BIN
OpenKeychain/src/main/res/drawable-mdpi/ic_check_black_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 128 B |
BIN
OpenKeychain/src/main/res/drawable-xhdpi/ic_check_black_24dp.png
Normal file
BIN
OpenKeychain/src/main/res/drawable-xhdpi/ic_check_black_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 188 B |
Binary file not shown.
|
After Width: | Height: | Size: 254 B |
Binary file not shown.
|
After Width: | Height: | Size: 277 B |
@@ -9,21 +9,37 @@
|
|||||||
android:paddingRight="24dp"
|
android:paddingRight="24dp"
|
||||||
android:paddingTop="16dp">
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
|
<android.support.design.widget.TextInputLayout
|
||||||
|
android:id="@+id/keyserver_url_edit_text_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/keyserver_url_edit_text"
|
android:id="@+id/keyserver_url_edit_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
android:hint="@string/label_enter_keyserver_url"
|
android:hint="@string/label_enter_keyserver_url"
|
||||||
android:imeOptions="actionDone" />
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="textUri" />
|
||||||
|
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/verify_keyserver_checkbox"
|
android:id="@+id/verify_connection_checkbox"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/label_verify_keyserver"
|
android:checked="true"
|
||||||
android:checked="true"/>
|
android:text="@string/label_verify_keyserver_connection" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/only_trusted_keyserver_checkbox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/label_only_trusted_keyserver" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_above="@+id/certify_fingerprint_buttons_divider">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -19,20 +14,21 @@
|
|||||||
android:id="@+id/certify_fingerprint_intro"
|
android:id="@+id/certify_fingerprint_intro"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="32dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:text="@string/certify_fingerprint_text"
|
||||||
android:text="@string/certify_fingerprint_text" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
android:id="@+id/certify_fingerprint_card"
|
android:id="@+id/certify_fingerprint_card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="top"
|
||||||
app:cardBackgroundColor="?attr/colorCardViewBackground"
|
app:cardBackgroundColor="?attr/colorCardViewBackground"
|
||||||
app:cardUseCompatPadding="true"
|
|
||||||
app:cardCornerRadius="4dp"
|
app:cardCornerRadius="4dp"
|
||||||
android:layout_gravity="top">
|
app:cardElevation="8dp"
|
||||||
|
app:cardUseCompatPadding="true">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -40,6 +36,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/certify_fingerprint_fingerprint_header"
|
||||||
style="@style/CardViewHeader"
|
style="@style/CardViewHeader"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -47,109 +44,64 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/certify_fingerprint_fingerprint"
|
android:id="@+id/certify_fingerprint_fingerprint"
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:typeface="monospace"
|
android:gravity="center_vertical"
|
||||||
android:gravity="center_vertical" />
|
android:paddingBottom="24dp"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:typeface="monospace" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dip"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/certify_fingerprint_button_no"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:textColor="@color/android_red_dark"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawableLeft="@drawable/ic_close_black_24dp"
|
||||||
|
android:drawablePadding="8dp"
|
||||||
|
android:gravity="left|center_vertical"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:text="@string/btn_not_matching"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dip"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/certify_fingerprint_button_yes"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:textColor="@color/android_green_dark"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawableLeft="@drawable/ic_check_black_24dp"
|
||||||
|
android:drawablePadding="8dp"
|
||||||
|
android:gravity="left|center_vertical"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:text="@string/btn_match"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</android.support.v7.widget.CardView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:id="@+id/certify_fingerprint_buttons">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/certify_fingerprint_button_no"
|
|
||||||
android:paddingLeft="8dp"
|
|
||||||
android:paddingRight="8dp"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/btn_no"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:clickable="true"
|
|
||||||
style="?android:attr/borderlessButtonStyle"
|
|
||||||
android:layout_gravity="center_vertical" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/listDivider" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/certify_fingerprint_button_yes"
|
|
||||||
android:paddingLeft="8dp"
|
|
||||||
android:paddingRight="8dp"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/btn_match"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:drawablePadding="8dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:clickable="true"
|
|
||||||
style="?android:attr/borderlessButtonStyle"
|
|
||||||
android:layout_gravity="center_vertical" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/certify_fingerprint_buttons_divider2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dip"
|
|
||||||
android:background="?android:attr/listDivider"
|
|
||||||
android:layout_alignBottom="@+id/certify_fingerprint_buttons_text"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/certify_fingerprint_buttons_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="24dp"
|
|
||||||
android:layout_marginRight="24dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:text="@string/certify_fingerprint_text2"
|
|
||||||
android:layout_above="@+id/certify_fingerprint_buttons"
|
|
||||||
android:layout_centerHorizontal="true" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/certify_fingerprint_buttons_divider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dip"
|
|
||||||
android:background="?android:attr/listDivider"
|
|
||||||
android:layout_alignTop="@+id/certify_fingerprint_buttons_text"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|||||||
19
OpenKeychain/src/main/res/menu-v19/decrypt_bottom_sheet.xml
Normal file
19
OpenKeychain/src/main/res/menu-v19/decrypt_bottom_sheet.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/decrypt_open"
|
||||||
|
android:icon="@drawable/ic_apps_black_24dp"
|
||||||
|
android:title="@string/btn_open_with" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/decrypt_share"
|
||||||
|
android:icon="@drawable/ic_share_black_24dp"
|
||||||
|
android:title="@string/btn_share_decrypted_text" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/decrypt_save"
|
||||||
|
android:icon="@drawable/ic_save_black_24dp"
|
||||||
|
android:title="@string/btn_save" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -3,17 +3,12 @@
|
|||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/decrypt_open"
|
android:id="@+id/decrypt_open"
|
||||||
android:title="Open with…"
|
android:icon="@drawable/ic_apps_black_24dp"
|
||||||
android:icon="@drawable/ic_apps_black_24dp" />
|
android:title="@string/btn_open_with" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/decrypt_share"
|
android:id="@+id/decrypt_share"
|
||||||
android:title="@string/btn_share_decrypted_text"
|
android:icon="@drawable/ic_share_black_24dp"
|
||||||
android:icon="@drawable/ic_share_black_24dp" />
|
android:title="@string/btn_share_decrypted_text" />
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/decrypt_save"
|
|
||||||
android:title="@string/btn_save"
|
|
||||||
android:icon="@drawable/ic_save_black_24dp" />
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
android:id="@+id/menu_key_view_certify_fingerprint_word"
|
android:id="@+id/menu_key_view_certify_fingerprint_word"
|
||||||
app:showAsAction="never"
|
app:showAsAction="never"
|
||||||
android:visible="false"
|
android:visible="false"
|
||||||
android:title="@string/menu_certify_fingerprint_word" />
|
android:title="@string/menu_certify_fingerprint_phrases" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_key_view_add_linked_identity"
|
android:id="@+id/menu_key_view_add_linked_identity"
|
||||||
|
|||||||
128
OpenKeychain/src/main/res/raw/fp_sentence_adjectives
Normal file
128
OpenKeychain/src/main/res/raw/fp_sentence_adjectives
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
able
|
||||||
|
angry
|
||||||
|
bad
|
||||||
|
bent
|
||||||
|
bitter
|
||||||
|
black
|
||||||
|
blue
|
||||||
|
boiling
|
||||||
|
bright
|
||||||
|
broken
|
||||||
|
brown
|
||||||
|
certain
|
||||||
|
cheap
|
||||||
|
clean
|
||||||
|
clear
|
||||||
|
cold
|
||||||
|
common
|
||||||
|
complex
|
||||||
|
cruel
|
||||||
|
dark
|
||||||
|
dead
|
||||||
|
dear
|
||||||
|
deep
|
||||||
|
dirty
|
||||||
|
dry
|
||||||
|
early
|
||||||
|
elastic
|
||||||
|
equal
|
||||||
|
false
|
||||||
|
fat
|
||||||
|
feeble
|
||||||
|
female
|
||||||
|
fertile
|
||||||
|
first
|
||||||
|
fixed
|
||||||
|
flat
|
||||||
|
foolish
|
||||||
|
free
|
||||||
|
full
|
||||||
|
future
|
||||||
|
general
|
||||||
|
good
|
||||||
|
great
|
||||||
|
green
|
||||||
|
grey
|
||||||
|
hanging
|
||||||
|
happy
|
||||||
|
hard
|
||||||
|
healthy
|
||||||
|
high
|
||||||
|
hollow
|
||||||
|
kind
|
||||||
|
last
|
||||||
|
late
|
||||||
|
lazy
|
||||||
|
left
|
||||||
|
like
|
||||||
|
living
|
||||||
|
long
|
||||||
|
loose
|
||||||
|
loud
|
||||||
|
low
|
||||||
|
male
|
||||||
|
married
|
||||||
|
medical
|
||||||
|
mixed
|
||||||
|
narrow
|
||||||
|
natural
|
||||||
|
new
|
||||||
|
normal
|
||||||
|
old
|
||||||
|
open
|
||||||
|
past
|
||||||
|
poor
|
||||||
|
present
|
||||||
|
pretty
|
||||||
|
private
|
||||||
|
public
|
||||||
|
quick
|
||||||
|
quiet
|
||||||
|
ready
|
||||||
|
rare
|
||||||
|
red
|
||||||
|
regular
|
||||||
|
right
|
||||||
|
rough
|
||||||
|
round
|
||||||
|
sad
|
||||||
|
safe
|
||||||
|
same
|
||||||
|
second
|
||||||
|
secret
|
||||||
|
serious
|
||||||
|
sharp
|
||||||
|
short
|
||||||
|
shut
|
||||||
|
sick
|
||||||
|
simple
|
||||||
|
slow
|
||||||
|
small
|
||||||
|
smooth
|
||||||
|
soft
|
||||||
|
solid
|
||||||
|
sour
|
||||||
|
special
|
||||||
|
sticky
|
||||||
|
stiff
|
||||||
|
strange
|
||||||
|
strong
|
||||||
|
sudden
|
||||||
|
sweet
|
||||||
|
tall
|
||||||
|
thick
|
||||||
|
thin
|
||||||
|
tight
|
||||||
|
tired
|
||||||
|
true
|
||||||
|
unknown
|
||||||
|
violent
|
||||||
|
waiting
|
||||||
|
warm
|
||||||
|
wet
|
||||||
|
white
|
||||||
|
wide
|
||||||
|
wise
|
||||||
|
wrong
|
||||||
|
yellow
|
||||||
|
young
|
||||||
64
OpenKeychain/src/main/res/raw/fp_sentence_adverbs
Normal file
64
OpenKeychain/src/main/res/raw/fp_sentence_adverbs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
ably
|
||||||
|
angrily
|
||||||
|
badly
|
||||||
|
bitterly
|
||||||
|
brightly
|
||||||
|
brokenly
|
||||||
|
cheaply
|
||||||
|
clearly
|
||||||
|
coldly
|
||||||
|
commonly
|
||||||
|
cruelly
|
||||||
|
darkly
|
||||||
|
dearly
|
||||||
|
deeply
|
||||||
|
drily
|
||||||
|
equally
|
||||||
|
falsely
|
||||||
|
feebly
|
||||||
|
fixedly
|
||||||
|
flatly
|
||||||
|
freely
|
||||||
|
fully
|
||||||
|
greatly
|
||||||
|
happily
|
||||||
|
hardly
|
||||||
|
kindly
|
||||||
|
lately
|
||||||
|
lazily
|
||||||
|
loosely
|
||||||
|
loudly
|
||||||
|
narrowly
|
||||||
|
newly
|
||||||
|
normally
|
||||||
|
openly
|
||||||
|
poorly
|
||||||
|
prettily
|
||||||
|
publicly
|
||||||
|
quickly
|
||||||
|
quietly
|
||||||
|
readily
|
||||||
|
rarely
|
||||||
|
roughly
|
||||||
|
sadly
|
||||||
|
safely
|
||||||
|
secretly
|
||||||
|
sharply
|
||||||
|
simply
|
||||||
|
slowly
|
||||||
|
smoothly
|
||||||
|
softly
|
||||||
|
solidly
|
||||||
|
sourly
|
||||||
|
stiffly
|
||||||
|
strongly
|
||||||
|
suddenly
|
||||||
|
sweetly
|
||||||
|
thickly
|
||||||
|
thinly
|
||||||
|
tightly
|
||||||
|
tiredly
|
||||||
|
truly
|
||||||
|
warmly
|
||||||
|
widely
|
||||||
|
wisely
|
||||||
8
OpenKeychain/src/main/res/raw/fp_sentence_articles
Normal file
8
OpenKeychain/src/main/res/raw/fp_sentence_articles
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
her
|
||||||
|
his
|
||||||
|
my
|
||||||
|
our
|
||||||
|
that
|
||||||
|
the
|
||||||
|
this
|
||||||
|
your
|
||||||
512
OpenKeychain/src/main/res/raw/fp_sentence_nouns
Normal file
512
OpenKeychain/src/main/res/raw/fp_sentence_nouns
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
account
|
||||||
|
air
|
||||||
|
amount
|
||||||
|
angle
|
||||||
|
animal
|
||||||
|
answer
|
||||||
|
ant
|
||||||
|
apple
|
||||||
|
arch
|
||||||
|
arm
|
||||||
|
army
|
||||||
|
attack
|
||||||
|
attempt
|
||||||
|
baby
|
||||||
|
back
|
||||||
|
bag
|
||||||
|
ball
|
||||||
|
band
|
||||||
|
base
|
||||||
|
basin
|
||||||
|
basket
|
||||||
|
bath
|
||||||
|
bed
|
||||||
|
bee
|
||||||
|
belief
|
||||||
|
bell
|
||||||
|
berry
|
||||||
|
bird
|
||||||
|
birth
|
||||||
|
bite
|
||||||
|
blade
|
||||||
|
blood
|
||||||
|
blow
|
||||||
|
board
|
||||||
|
boat
|
||||||
|
body
|
||||||
|
bone
|
||||||
|
book
|
||||||
|
boot
|
||||||
|
bottle
|
||||||
|
box
|
||||||
|
boy
|
||||||
|
brain
|
||||||
|
brake
|
||||||
|
branch
|
||||||
|
bread
|
||||||
|
breath
|
||||||
|
brick
|
||||||
|
bridge
|
||||||
|
brother
|
||||||
|
brush
|
||||||
|
bucket
|
||||||
|
bulb
|
||||||
|
burn
|
||||||
|
butter
|
||||||
|
button
|
||||||
|
cake
|
||||||
|
camera
|
||||||
|
canvas
|
||||||
|
car
|
||||||
|
card
|
||||||
|
cat
|
||||||
|
cause
|
||||||
|
chain
|
||||||
|
chalk
|
||||||
|
chance
|
||||||
|
change
|
||||||
|
cheese
|
||||||
|
chest
|
||||||
|
chin
|
||||||
|
church
|
||||||
|
circle
|
||||||
|
clock
|
||||||
|
cloth
|
||||||
|
cloud
|
||||||
|
coal
|
||||||
|
coat
|
||||||
|
collar
|
||||||
|
colour
|
||||||
|
comb
|
||||||
|
comfort
|
||||||
|
company
|
||||||
|
control
|
||||||
|
cook
|
||||||
|
copper
|
||||||
|
copy
|
||||||
|
cord
|
||||||
|
cork
|
||||||
|
cotton
|
||||||
|
cough
|
||||||
|
country
|
||||||
|
cover
|
||||||
|
cow
|
||||||
|
crack
|
||||||
|
credit
|
||||||
|
crime
|
||||||
|
crush
|
||||||
|
cry
|
||||||
|
cup
|
||||||
|
current
|
||||||
|
curtain
|
||||||
|
curve
|
||||||
|
cushion
|
||||||
|
damage
|
||||||
|
danger
|
||||||
|
day
|
||||||
|
debt
|
||||||
|
degree
|
||||||
|
design
|
||||||
|
desire
|
||||||
|
detail
|
||||||
|
disease
|
||||||
|
disgust
|
||||||
|
dog
|
||||||
|
door
|
||||||
|
doubt
|
||||||
|
drain
|
||||||
|
drawer
|
||||||
|
dress
|
||||||
|
drink
|
||||||
|
drop
|
||||||
|
dust
|
||||||
|
ear
|
||||||
|
earth
|
||||||
|
edge
|
||||||
|
effect
|
||||||
|
egg
|
||||||
|
end
|
||||||
|
engine
|
||||||
|
error
|
||||||
|
event
|
||||||
|
example
|
||||||
|
expert
|
||||||
|
eye
|
||||||
|
face
|
||||||
|
fact
|
||||||
|
fall
|
||||||
|
family
|
||||||
|
farm
|
||||||
|
father
|
||||||
|
fear
|
||||||
|
feather
|
||||||
|
feeling
|
||||||
|
fiction
|
||||||
|
field
|
||||||
|
fight
|
||||||
|
finger
|
||||||
|
fire
|
||||||
|
fish
|
||||||
|
flag
|
||||||
|
flame
|
||||||
|
flight
|
||||||
|
floor
|
||||||
|
flower
|
||||||
|
fly
|
||||||
|
fold
|
||||||
|
food
|
||||||
|
foot
|
||||||
|
force
|
||||||
|
fork
|
||||||
|
form
|
||||||
|
fowl
|
||||||
|
frame
|
||||||
|
friend
|
||||||
|
front
|
||||||
|
fruit
|
||||||
|
garden
|
||||||
|
girl
|
||||||
|
glass
|
||||||
|
glove
|
||||||
|
goat
|
||||||
|
gold
|
||||||
|
grain
|
||||||
|
grass
|
||||||
|
grip
|
||||||
|
group
|
||||||
|
growth
|
||||||
|
guide
|
||||||
|
gun
|
||||||
|
hair
|
||||||
|
hammer
|
||||||
|
hand
|
||||||
|
harbour
|
||||||
|
harmony
|
||||||
|
hat
|
||||||
|
hate
|
||||||
|
head
|
||||||
|
heart
|
||||||
|
heat
|
||||||
|
history
|
||||||
|
hole
|
||||||
|
hook
|
||||||
|
hope
|
||||||
|
horn
|
||||||
|
horse
|
||||||
|
hour
|
||||||
|
house
|
||||||
|
humour
|
||||||
|
ice
|
||||||
|
idea
|
||||||
|
impulse
|
||||||
|
ink
|
||||||
|
insect
|
||||||
|
iron
|
||||||
|
island
|
||||||
|
jelly
|
||||||
|
jewel
|
||||||
|
join
|
||||||
|
journey
|
||||||
|
judge
|
||||||
|
jump
|
||||||
|
kettle
|
||||||
|
key
|
||||||
|
kick
|
||||||
|
kiss
|
||||||
|
knee
|
||||||
|
knife
|
||||||
|
knot
|
||||||
|
land
|
||||||
|
laugh
|
||||||
|
law
|
||||||
|
lead
|
||||||
|
leaf
|
||||||
|
leather
|
||||||
|
leg
|
||||||
|
letter
|
||||||
|
level
|
||||||
|
library
|
||||||
|
lift
|
||||||
|
light
|
||||||
|
limit
|
||||||
|
line
|
||||||
|
linen
|
||||||
|
lip
|
||||||
|
liquid
|
||||||
|
list
|
||||||
|
lock
|
||||||
|
look
|
||||||
|
loss
|
||||||
|
love
|
||||||
|
machine
|
||||||
|
man
|
||||||
|
manager
|
||||||
|
map
|
||||||
|
mark
|
||||||
|
market
|
||||||
|
mass
|
||||||
|
match
|
||||||
|
meal
|
||||||
|
measure
|
||||||
|
meat
|
||||||
|
meeting
|
||||||
|
memory
|
||||||
|
metal
|
||||||
|
middle
|
||||||
|
milk
|
||||||
|
mind
|
||||||
|
mine
|
||||||
|
minute
|
||||||
|
mist
|
||||||
|
money
|
||||||
|
monkey
|
||||||
|
month
|
||||||
|
moon
|
||||||
|
morning
|
||||||
|
mother
|
||||||
|
motion
|
||||||
|
mouth
|
||||||
|
move
|
||||||
|
muscle
|
||||||
|
music
|
||||||
|
nail
|
||||||
|
name
|
||||||
|
nation
|
||||||
|
neck
|
||||||
|
need
|
||||||
|
needle
|
||||||
|
nerve
|
||||||
|
net
|
||||||
|
news
|
||||||
|
night
|
||||||
|
noise
|
||||||
|
nose
|
||||||
|
note
|
||||||
|
number
|
||||||
|
nut
|
||||||
|
offer
|
||||||
|
office
|
||||||
|
oil
|
||||||
|
opinion
|
||||||
|
orange
|
||||||
|
order
|
||||||
|
oven
|
||||||
|
owner
|
||||||
|
page
|
||||||
|
pain
|
||||||
|
paint
|
||||||
|
paper
|
||||||
|
parcel
|
||||||
|
part
|
||||||
|
paste
|
||||||
|
payment
|
||||||
|
peace
|
||||||
|
pen
|
||||||
|
pencil
|
||||||
|
person
|
||||||
|
picture
|
||||||
|
pig
|
||||||
|
pin
|
||||||
|
pipe
|
||||||
|
place
|
||||||
|
plane
|
||||||
|
plant
|
||||||
|
plate
|
||||||
|
play
|
||||||
|
plough
|
||||||
|
pocket
|
||||||
|
point
|
||||||
|
poison
|
||||||
|
polish
|
||||||
|
porter
|
||||||
|
pot
|
||||||
|
potato
|
||||||
|
powder
|
||||||
|
power
|
||||||
|
price
|
||||||
|
print
|
||||||
|
prison
|
||||||
|
process
|
||||||
|
produce
|
||||||
|
profit
|
||||||
|
prose
|
||||||
|
protest
|
||||||
|
pull
|
||||||
|
pump
|
||||||
|
purpose
|
||||||
|
push
|
||||||
|
quality
|
||||||
|
rail
|
||||||
|
rain
|
||||||
|
range
|
||||||
|
rat
|
||||||
|
rate
|
||||||
|
ray
|
||||||
|
reason
|
||||||
|
receipt
|
||||||
|
record
|
||||||
|
regret
|
||||||
|
request
|
||||||
|
respect
|
||||||
|
rest
|
||||||
|
reward
|
||||||
|
rhythm
|
||||||
|
rice
|
||||||
|
ring
|
||||||
|
river
|
||||||
|
road
|
||||||
|
rod
|
||||||
|
roll
|
||||||
|
roof
|
||||||
|
room
|
||||||
|
root
|
||||||
|
rub
|
||||||
|
rule
|
||||||
|
run
|
||||||
|
sail
|
||||||
|
salt
|
||||||
|
sand
|
||||||
|
scale
|
||||||
|
school
|
||||||
|
science
|
||||||
|
screw
|
||||||
|
sea
|
||||||
|
seat
|
||||||
|
seed
|
||||||
|
self
|
||||||
|
sense
|
||||||
|
servant
|
||||||
|
sex
|
||||||
|
shade
|
||||||
|
shake
|
||||||
|
shame
|
||||||
|
sheep
|
||||||
|
shelf
|
||||||
|
ship
|
||||||
|
shirt
|
||||||
|
shock
|
||||||
|
shoe
|
||||||
|
side
|
||||||
|
sign
|
||||||
|
silk
|
||||||
|
silver
|
||||||
|
sister
|
||||||
|
size
|
||||||
|
skin
|
||||||
|
skirt
|
||||||
|
sky
|
||||||
|
sleep
|
||||||
|
slip
|
||||||
|
slope
|
||||||
|
smash
|
||||||
|
smell
|
||||||
|
smile
|
||||||
|
smoke
|
||||||
|
snake
|
||||||
|
sneeze
|
||||||
|
snow
|
||||||
|
soap
|
||||||
|
society
|
||||||
|
sock
|
||||||
|
son
|
||||||
|
song
|
||||||
|
sort
|
||||||
|
sound
|
||||||
|
soup
|
||||||
|
space
|
||||||
|
spade
|
||||||
|
sponge
|
||||||
|
spoon
|
||||||
|
spring
|
||||||
|
square
|
||||||
|
stage
|
||||||
|
stamp
|
||||||
|
star
|
||||||
|
start
|
||||||
|
station
|
||||||
|
steam
|
||||||
|
steel
|
||||||
|
stem
|
||||||
|
step
|
||||||
|
stick
|
||||||
|
stitch
|
||||||
|
stomach
|
||||||
|
stone
|
||||||
|
stop
|
||||||
|
store
|
||||||
|
story
|
||||||
|
street
|
||||||
|
stretch
|
||||||
|
sugar
|
||||||
|
summer
|
||||||
|
sun
|
||||||
|
support
|
||||||
|
swim
|
||||||
|
system
|
||||||
|
table
|
||||||
|
tail
|
||||||
|
talk
|
||||||
|
taste
|
||||||
|
tax
|
||||||
|
test
|
||||||
|
theory
|
||||||
|
thing
|
||||||
|
thought
|
||||||
|
thread
|
||||||
|
throat
|
||||||
|
thumb
|
||||||
|
thunder
|
||||||
|
ticket
|
||||||
|
time
|
||||||
|
tin
|
||||||
|
toe
|
||||||
|
tongue
|
||||||
|
tooth
|
||||||
|
top
|
||||||
|
touch
|
||||||
|
town
|
||||||
|
trade
|
||||||
|
train
|
||||||
|
tray
|
||||||
|
tree
|
||||||
|
trick
|
||||||
|
trouble
|
||||||
|
turn
|
||||||
|
twist
|
||||||
|
unit
|
||||||
|
value
|
||||||
|
verse
|
||||||
|
vessel
|
||||||
|
view
|
||||||
|
voice
|
||||||
|
walk
|
||||||
|
wall
|
||||||
|
war
|
||||||
|
wash
|
||||||
|
waste
|
||||||
|
watch
|
||||||
|
water
|
||||||
|
wave
|
||||||
|
wax
|
||||||
|
way
|
||||||
|
weather
|
||||||
|
week
|
||||||
|
weight
|
||||||
|
wheel
|
||||||
|
whip
|
||||||
|
whistle
|
||||||
|
wind
|
||||||
|
window
|
||||||
|
wine
|
||||||
|
wing
|
||||||
|
winter
|
||||||
|
wire
|
||||||
|
woman
|
||||||
|
wood
|
||||||
|
wool
|
||||||
|
word
|
||||||
|
work
|
||||||
|
worm
|
||||||
|
wound
|
||||||
|
writing
|
||||||
|
year
|
||||||
32
OpenKeychain/src/main/res/raw/fp_sentence_prepositions
Normal file
32
OpenKeychain/src/main/res/raw/fp_sentence_prepositions
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
above
|
||||||
|
across
|
||||||
|
after
|
||||||
|
against
|
||||||
|
along
|
||||||
|
among
|
||||||
|
around
|
||||||
|
at
|
||||||
|
before
|
||||||
|
behind
|
||||||
|
below
|
||||||
|
beneath
|
||||||
|
beside
|
||||||
|
between
|
||||||
|
beyond
|
||||||
|
by
|
||||||
|
from
|
||||||
|
in
|
||||||
|
inside
|
||||||
|
into
|
||||||
|
near
|
||||||
|
on
|
||||||
|
outside
|
||||||
|
over
|
||||||
|
past
|
||||||
|
round
|
||||||
|
through
|
||||||
|
to
|
||||||
|
towards
|
||||||
|
under
|
||||||
|
upon
|
||||||
|
with
|
||||||
128
OpenKeychain/src/main/res/raw/fp_sentence_verbs_i
Normal file
128
OpenKeychain/src/main/res/raw/fp_sentence_verbs_i
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
agrees
|
||||||
|
allows
|
||||||
|
answers
|
||||||
|
arrives
|
||||||
|
asks
|
||||||
|
is
|
||||||
|
becomes
|
||||||
|
begins
|
||||||
|
believes
|
||||||
|
brings
|
||||||
|
burns
|
||||||
|
buys
|
||||||
|
calls
|
||||||
|
changes
|
||||||
|
chooses
|
||||||
|
cleans
|
||||||
|
closes
|
||||||
|
comes
|
||||||
|
compares
|
||||||
|
continues
|
||||||
|
cooks
|
||||||
|
costs
|
||||||
|
counts
|
||||||
|
cries
|
||||||
|
cuts
|
||||||
|
dances
|
||||||
|
decides
|
||||||
|
describes
|
||||||
|
destroys
|
||||||
|
dies
|
||||||
|
does
|
||||||
|
drinks
|
||||||
|
drives
|
||||||
|
eats
|
||||||
|
ends
|
||||||
|
explains
|
||||||
|
falls
|
||||||
|
feels
|
||||||
|
fights
|
||||||
|
fills
|
||||||
|
finds
|
||||||
|
finishes
|
||||||
|
forgets
|
||||||
|
forgives
|
||||||
|
gets
|
||||||
|
gives
|
||||||
|
goes
|
||||||
|
grows
|
||||||
|
hates
|
||||||
|
has
|
||||||
|
hears
|
||||||
|
helps
|
||||||
|
hides
|
||||||
|
holds
|
||||||
|
hurts
|
||||||
|
improves
|
||||||
|
jumps
|
||||||
|
keeps
|
||||||
|
kills
|
||||||
|
knows
|
||||||
|
laughs
|
||||||
|
learns
|
||||||
|
leaves
|
||||||
|
lets
|
||||||
|
lies
|
||||||
|
listens
|
||||||
|
lives
|
||||||
|
looks
|
||||||
|
loses
|
||||||
|
loves
|
||||||
|
makes
|
||||||
|
meets
|
||||||
|
moves
|
||||||
|
needs
|
||||||
|
occurs
|
||||||
|
offers
|
||||||
|
opens
|
||||||
|
pays
|
||||||
|
plays
|
||||||
|
prefers
|
||||||
|
prepares
|
||||||
|
presses
|
||||||
|
promises
|
||||||
|
pulls
|
||||||
|
pushes
|
||||||
|
puts
|
||||||
|
reads
|
||||||
|
receives
|
||||||
|
remembers
|
||||||
|
repeats
|
||||||
|
rests
|
||||||
|
returns
|
||||||
|
runs
|
||||||
|
sees
|
||||||
|
sells
|
||||||
|
sends
|
||||||
|
shouts
|
||||||
|
shows
|
||||||
|
sings
|
||||||
|
sits
|
||||||
|
sleeps
|
||||||
|
smiles
|
||||||
|
speaks
|
||||||
|
starts
|
||||||
|
stays
|
||||||
|
stops
|
||||||
|
studies
|
||||||
|
suggests
|
||||||
|
supports
|
||||||
|
takes
|
||||||
|
talks
|
||||||
|
teaches
|
||||||
|
tells
|
||||||
|
thinks
|
||||||
|
throws
|
||||||
|
touches
|
||||||
|
travels
|
||||||
|
treats
|
||||||
|
tries
|
||||||
|
turns
|
||||||
|
uses
|
||||||
|
visits
|
||||||
|
walks
|
||||||
|
wants
|
||||||
|
washes
|
||||||
|
wins
|
||||||
|
works
|
||||||
|
writes
|
||||||
128
OpenKeychain/src/main/res/raw/fp_sentence_verbs_t
Normal file
128
OpenKeychain/src/main/res/raw/fp_sentence_verbs_t
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
agrees with
|
||||||
|
allows
|
||||||
|
answers
|
||||||
|
arrives at
|
||||||
|
asks
|
||||||
|
is
|
||||||
|
becomes
|
||||||
|
begins
|
||||||
|
believes
|
||||||
|
brings
|
||||||
|
burns
|
||||||
|
buys
|
||||||
|
calls
|
||||||
|
changes
|
||||||
|
chooses
|
||||||
|
cleans
|
||||||
|
closes
|
||||||
|
comes to
|
||||||
|
compares
|
||||||
|
continues
|
||||||
|
cooks
|
||||||
|
costs
|
||||||
|
counts
|
||||||
|
cries for
|
||||||
|
cuts
|
||||||
|
dances with
|
||||||
|
decides on
|
||||||
|
describes
|
||||||
|
destroys
|
||||||
|
dies for
|
||||||
|
does
|
||||||
|
drinks
|
||||||
|
drives
|
||||||
|
eats
|
||||||
|
ends
|
||||||
|
explains
|
||||||
|
falls on
|
||||||
|
feels
|
||||||
|
fights
|
||||||
|
fills
|
||||||
|
finds
|
||||||
|
finishes
|
||||||
|
forgets
|
||||||
|
forgives
|
||||||
|
gets
|
||||||
|
gives
|
||||||
|
goes to
|
||||||
|
grows
|
||||||
|
hates
|
||||||
|
has
|
||||||
|
hears
|
||||||
|
helps
|
||||||
|
hides
|
||||||
|
holds
|
||||||
|
hurts
|
||||||
|
improves
|
||||||
|
jumps over
|
||||||
|
keeps
|
||||||
|
kills
|
||||||
|
knows
|
||||||
|
laughs at
|
||||||
|
learns
|
||||||
|
leaves
|
||||||
|
lets
|
||||||
|
lies to
|
||||||
|
listens to
|
||||||
|
lives with
|
||||||
|
looks at
|
||||||
|
loses
|
||||||
|
loves
|
||||||
|
makes
|
||||||
|
meets
|
||||||
|
moves
|
||||||
|
needs
|
||||||
|
occurs to
|
||||||
|
offers
|
||||||
|
opens
|
||||||
|
pays
|
||||||
|
plays
|
||||||
|
prefers
|
||||||
|
prepares
|
||||||
|
presses
|
||||||
|
promises
|
||||||
|
pulls
|
||||||
|
pushes
|
||||||
|
puts
|
||||||
|
reads
|
||||||
|
receives
|
||||||
|
remembers
|
||||||
|
repeats
|
||||||
|
rests by
|
||||||
|
returns
|
||||||
|
runs to
|
||||||
|
sees
|
||||||
|
sells
|
||||||
|
sends
|
||||||
|
shouts at
|
||||||
|
shows
|
||||||
|
sings to
|
||||||
|
sits by
|
||||||
|
sleeps by
|
||||||
|
smiles at
|
||||||
|
speaks to
|
||||||
|
starts
|
||||||
|
stays with
|
||||||
|
stops
|
||||||
|
studies
|
||||||
|
suggests
|
||||||
|
supports
|
||||||
|
takes
|
||||||
|
talks to
|
||||||
|
teaches
|
||||||
|
tells
|
||||||
|
thinks of
|
||||||
|
throws
|
||||||
|
touches
|
||||||
|
travels to
|
||||||
|
treats
|
||||||
|
tries
|
||||||
|
turns
|
||||||
|
uses
|
||||||
|
visits
|
||||||
|
walks to
|
||||||
|
wants
|
||||||
|
washes
|
||||||
|
wins
|
||||||
|
works for
|
||||||
|
writes to
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
<string name="label_enable_compression">Zapnout kompresi</string>
|
<string name="label_enable_compression">Zapnout kompresi</string>
|
||||||
<string name="label_encrypt_filenames">Zašifrovat jména souborů</string>
|
<string name="label_encrypt_filenames">Zašifrovat jména souborů</string>
|
||||||
<string name="label_hidden_recipients">Skrýt příjemce</string>
|
<string name="label_hidden_recipients">Skrýt příjemce</string>
|
||||||
<string name="label_verify_keyserver">Ověřit keyserver</string>
|
<string name="label_verify_keyserver_connection">Ověřit keyserver</string>
|
||||||
<string name="label_enter_keyserver_url">Zadejte URL keyserveru</string>
|
<string name="label_enter_keyserver_url">Zadejte URL keyserveru</string>
|
||||||
<string name="pref_keyserver">OpenPGP keyserver</string>
|
<string name="pref_keyserver">OpenPGP keyserver</string>
|
||||||
<string name="pref_keyserver_summary">Vyhledat klíče na vybraném OpenPGP keyserveru (protokol HKP)</string>
|
<string name="pref_keyserver_summary">Vyhledat klíče na vybraném OpenPGP keyserveru (protokol HKP)</string>
|
||||||
@@ -496,7 +496,7 @@
|
|||||||
<string name="view_key_fragment_no_system_contact"><žádný></string>
|
<string name="view_key_fragment_no_system_contact"><žádný></string>
|
||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Přidat keyserver</string>
|
<string name="add_keyserver_dialog_title">Přidat keyserver</string>
|
||||||
<string name="add_keyserver_verified">Keyserver ověřen!</string>
|
<string name="add_keyserver_connection_verified">Keyserver ověřen!</string>
|
||||||
<string name="add_keyserver_without_verification">Keyserver přidán bez verifikace.</string>
|
<string name="add_keyserver_without_verification">Keyserver přidán bez verifikace.</string>
|
||||||
<string name="add_keyserver_invalid_url">Neplatná URL!</string>
|
<string name="add_keyserver_invalid_url">Neplatná URL!</string>
|
||||||
<string name="add_keyserver_connection_failed">Nepodařilo se připojit ke key severu. Prosím ověřte URL a vaše připojení k internetu.</string>
|
<string name="add_keyserver_connection_failed">Nepodařilo se připojit ke key severu. Prosím ověřte URL a vaše připojení k internetu.</string>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
<string name="label_enable_compression">Komprimierung aktivieren</string>
|
<string name="label_enable_compression">Komprimierung aktivieren</string>
|
||||||
<string name="label_encrypt_filenames">Dateinamen verschlüsseln</string>
|
<string name="label_encrypt_filenames">Dateinamen verschlüsseln</string>
|
||||||
<string name="label_hidden_recipients">Empfänger verbergen</string>
|
<string name="label_hidden_recipients">Empfänger verbergen</string>
|
||||||
<string name="label_verify_keyserver">Schlüsselserver verifizieren</string>
|
<string name="label_verify_keyserver_connection">Schlüsselserver verifizieren</string>
|
||||||
<string name="label_enter_keyserver_url">Schlüsselserver-URL eingeben</string>
|
<string name="label_enter_keyserver_url">Schlüsselserver-URL eingeben</string>
|
||||||
<string name="label_keyserver_dialog_delete">Schlüsselserver löschen</string>
|
<string name="label_keyserver_dialog_delete">Schlüsselserver löschen</string>
|
||||||
<string name="label_theme">Design</string>
|
<string name="label_theme">Design</string>
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<string name="progress_deleting">Lösche Schlüssel…</string>
|
<string name="progress_deleting">Lösche Schlüssel…</string>
|
||||||
<string name="progress_con_saving">Zusammenführung: Sichere in den Zwischenspeicher...</string>
|
<string name="progress_con_saving">Zusammenführung: Sichere in den Zwischenspeicher...</string>
|
||||||
<string name="progress_con_reimport">Zusammenführung: Reimportiere...</string>
|
<string name="progress_con_reimport">Zusammenführung: Reimportiere...</string>
|
||||||
<string name="progress_verifying_keyserver_url">Schlüsselserver wird verifiziert…</string>
|
<string name="progress_verifying_keyserver_connection">Schlüsselserver wird verifiziert…</string>
|
||||||
<string name="progress_starting_orbot">Orbot wird gestartet…</string>
|
<string name="progress_starting_orbot">Orbot wird gestartet…</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Via Name, E-Mail suchen...</string>
|
<string name="hint_cloud_search_hint">Via Name, E-Mail suchen...</string>
|
||||||
@@ -691,7 +691,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Schlüsselserver hinzufügen</string>
|
<string name="add_keyserver_dialog_title">Schlüsselserver hinzufügen</string>
|
||||||
<string name="edit_keyserver_dialog_title">Schlüsselserver bearbeiten</string>
|
<string name="edit_keyserver_dialog_title">Schlüsselserver bearbeiten</string>
|
||||||
<string name="add_keyserver_verified">Schlüsselserver verifiziert!</string>
|
<string name="add_keyserver_connection_verified">Schlüsselserver verifiziert!</string>
|
||||||
<string name="add_keyserver_without_verification">Schlüsselserver ohne Verifikation hinzugefügt.</string>
|
<string name="add_keyserver_without_verification">Schlüsselserver ohne Verifikation hinzugefügt.</string>
|
||||||
<string name="add_keyserver_invalid_url">Ungültige URL!</string>
|
<string name="add_keyserver_invalid_url">Ungültige URL!</string>
|
||||||
<string name="add_keyserver_connection_failed">Verbindung zum Schlüsselserver fehlgeschlagen. Bitte überprüfe die URL und deine Internetverbindung.</string>
|
<string name="add_keyserver_connection_failed">Verbindung zum Schlüsselserver fehlgeschlagen. Bitte überprüfe die URL und deine Internetverbindung.</string>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
<string name="label_enable_compression">Habilitar compresión</string>
|
<string name="label_enable_compression">Habilitar compresión</string>
|
||||||
<string name="label_encrypt_filenames">Cifrar nombres de ficheros</string>
|
<string name="label_encrypt_filenames">Cifrar nombres de ficheros</string>
|
||||||
<string name="label_hidden_recipients">Ocultar receptores</string>
|
<string name="label_hidden_recipients">Ocultar receptores</string>
|
||||||
<string name="label_verify_keyserver">Verificar servidor de claves</string>
|
<string name="label_verify_keyserver_connection">Verificar servidor de claves</string>
|
||||||
<string name="label_enter_keyserver_url">Introduzca URL de servidor de claves</string>
|
<string name="label_enter_keyserver_url">Introduzca URL de servidor de claves</string>
|
||||||
<string name="label_keyserver_dialog_delete">Borrar servidor de claves</string>
|
<string name="label_keyserver_dialog_delete">Borrar servidor de claves</string>
|
||||||
<string name="label_theme">Tema decorativo</string>
|
<string name="label_theme">Tema decorativo</string>
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<string name="progress_deleting">borrando claves...</string>
|
<string name="progress_deleting">borrando claves...</string>
|
||||||
<string name="progress_con_saving">consolidación: guardando en caché...</string>
|
<string name="progress_con_saving">consolidación: guardando en caché...</string>
|
||||||
<string name="progress_con_reimport">consolidación: reimportando</string>
|
<string name="progress_con_reimport">consolidación: reimportando</string>
|
||||||
<string name="progress_verifying_keyserver_url">verificando servidor de claves...</string>
|
<string name="progress_verifying_keyserver_connection">verificando servidor de claves...</string>
|
||||||
<string name="progress_starting_orbot">Iniciando Orbot...</string>
|
<string name="progress_starting_orbot">Iniciando Orbot...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Buscar mediante Nombre, Correo electrónico...</string>
|
<string name="hint_cloud_search_hint">Buscar mediante Nombre, Correo electrónico...</string>
|
||||||
@@ -691,7 +691,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Añadir servidor de claves</string>
|
<string name="add_keyserver_dialog_title">Añadir servidor de claves</string>
|
||||||
<string name="edit_keyserver_dialog_title">Editar servidor de claves</string>
|
<string name="edit_keyserver_dialog_title">Editar servidor de claves</string>
|
||||||
<string name="add_keyserver_verified">¡Servidor de claves verificado!</string>
|
<string name="add_keyserver_connection_verified">¡Servidor de claves verificado!</string>
|
||||||
<string name="add_keyserver_without_verification">Servidor de claves añadido sin verificación</string>
|
<string name="add_keyserver_without_verification">Servidor de claves añadido sin verificación</string>
|
||||||
<string name="add_keyserver_invalid_url">¡URL no válida!</string>
|
<string name="add_keyserver_invalid_url">¡URL no válida!</string>
|
||||||
<string name="add_keyserver_connection_failed">Fallo al conectar al servidor de claves. Por favor, compuebe la URL y su conexión a Internet.</string>
|
<string name="add_keyserver_connection_failed">Fallo al conectar al servidor de claves. Por favor, compuebe la URL y su conexión a Internet.</string>
|
||||||
|
|||||||
@@ -154,7 +154,7 @@
|
|||||||
<string name="label_enable_compression">Gaitu konpresioa</string>
|
<string name="label_enable_compression">Gaitu konpresioa</string>
|
||||||
<string name="label_encrypt_filenames">Enkriptatu agirizenak</string>
|
<string name="label_encrypt_filenames">Enkriptatu agirizenak</string>
|
||||||
<string name="label_hidden_recipients">Ezkutatu jasotzaileak</string>
|
<string name="label_hidden_recipients">Ezkutatu jasotzaileak</string>
|
||||||
<string name="label_verify_keyserver">Egiaztatu giltza-zerbitzaria</string>
|
<string name="label_verify_keyserver_connection">Egiaztatu giltza-zerbitzaria</string>
|
||||||
<string name="label_enter_keyserver_url">Sartu giltza-zerbitzariaren URL-a</string>
|
<string name="label_enter_keyserver_url">Sartu giltza-zerbitzariaren URL-a</string>
|
||||||
<string name="label_keyserver_dialog_delete">Ezabatu giltza-zerbitzaria</string>
|
<string name="label_keyserver_dialog_delete">Ezabatu giltza-zerbitzaria</string>
|
||||||
<string name="label_theme">Azalgaia</string>
|
<string name="label_theme">Azalgaia</string>
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
<string name="progress_deleting">giltzak ezabatzen...</string>
|
<string name="progress_deleting">giltzak ezabatzen...</string>
|
||||||
<string name="progress_con_saving">sendotu: katxean gordetzen...</string>
|
<string name="progress_con_saving">sendotu: katxean gordetzen...</string>
|
||||||
<string name="progress_con_reimport">sendotu: berrinportatzen...</string>
|
<string name="progress_con_reimport">sendotu: berrinportatzen...</string>
|
||||||
<string name="progress_verifying_keyserver_url">giltza-zerbitzaria egiaztatzen...</string>
|
<string name="progress_verifying_keyserver_connection">giltza-zerbitzaria egiaztatzen...</string>
|
||||||
<string name="progress_starting_orbot">Orbot Abiarazten...</string>
|
<string name="progress_starting_orbot">Orbot Abiarazten...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Bilatu Izena, Post@... bidez</string>
|
<string name="hint_cloud_search_hint">Bilatu Izena, Post@... bidez</string>
|
||||||
@@ -675,7 +675,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Gehitu giltza-zerbitzaria</string>
|
<string name="add_keyserver_dialog_title">Gehitu giltza-zerbitzaria</string>
|
||||||
<string name="edit_keyserver_dialog_title">Editatu giltza-zerbitzaria</string>
|
<string name="edit_keyserver_dialog_title">Editatu giltza-zerbitzaria</string>
|
||||||
<string name="add_keyserver_verified">Giltza-zerbitzaria egiaztatuta!</string>
|
<string name="add_keyserver_connection_verified">Giltza-zerbitzaria egiaztatuta!</string>
|
||||||
<string name="add_keyserver_without_verification">Giltza-zerbitzaria gehituta egiaztapen gabe.</string>
|
<string name="add_keyserver_without_verification">Giltza-zerbitzaria gehituta egiaztapen gabe.</string>
|
||||||
<string name="add_keyserver_invalid_url">URL baliogabea!</string>
|
<string name="add_keyserver_invalid_url">URL baliogabea!</string>
|
||||||
<string name="add_keyserver_connection_failed">Hutsegitea giltza-zerbitzariarekin elkartzerakoan. Mesedez egiaztatu URL-a eta zure internet elkarketa.</string>
|
<string name="add_keyserver_connection_failed">Hutsegitea giltza-zerbitzariarekin elkartzerakoan. Mesedez egiaztatu URL-a eta zure internet elkarketa.</string>
|
||||||
|
|||||||
@@ -146,7 +146,7 @@
|
|||||||
<string name="label_enable_compression">فشردهکردن</string>
|
<string name="label_enable_compression">فشردهکردن</string>
|
||||||
<string name="label_encrypt_filenames">رمزگذاری اسمِ فایلها</string>
|
<string name="label_encrypt_filenames">رمزگذاری اسمِ فایلها</string>
|
||||||
<string name="label_hidden_recipients">مخفیکردن گیرندهها</string>
|
<string name="label_hidden_recipients">مخفیکردن گیرندهها</string>
|
||||||
<string name="label_verify_keyserver">بررسی سرورِ کلیدها</string>
|
<string name="label_verify_keyserver_connection">بررسی سرورِ کلیدها</string>
|
||||||
<string name="label_enter_keyserver_url">آدرس URL سرورِ کلید را وارد کنید</string>
|
<string name="label_enter_keyserver_url">آدرس URL سرورِ کلید را وارد کنید</string>
|
||||||
<string name="label_keyserver_dialog_delete">حذف سرورهای کلید</string>
|
<string name="label_keyserver_dialog_delete">حذف سرورهای کلید</string>
|
||||||
<string name="label_theme">قالب</string>
|
<string name="label_theme">قالب</string>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
<string name="label_enable_compression">Activer la compression</string>
|
<string name="label_enable_compression">Activer la compression</string>
|
||||||
<string name="label_encrypt_filenames">Chiffrer les nom de fichier</string>
|
<string name="label_encrypt_filenames">Chiffrer les nom de fichier</string>
|
||||||
<string name="label_hidden_recipients">Cacher les destinataires</string>
|
<string name="label_hidden_recipients">Cacher les destinataires</string>
|
||||||
<string name="label_verify_keyserver">Vérifier le serveur de clefs</string>
|
<string name="label_verify_keyserver_connection">Vérifier le serveur de clefs</string>
|
||||||
<string name="label_enter_keyserver_url">Saisir l\'URL du serveur de clefs</string>
|
<string name="label_enter_keyserver_url">Saisir l\'URL du serveur de clefs</string>
|
||||||
<string name="label_keyserver_dialog_delete">Supprimer le serveur de clefs</string>
|
<string name="label_keyserver_dialog_delete">Supprimer le serveur de clefs</string>
|
||||||
<string name="label_theme">Thème</string>
|
<string name="label_theme">Thème</string>
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<string name="progress_deleting">suppression des clefs...</string>
|
<string name="progress_deleting">suppression des clefs...</string>
|
||||||
<string name="progress_con_saving">consolider : enregistrement dans le cache...</string>
|
<string name="progress_con_saving">consolider : enregistrement dans le cache...</string>
|
||||||
<string name="progress_con_reimport">consolider : réimportation...</string>
|
<string name="progress_con_reimport">consolider : réimportation...</string>
|
||||||
<string name="progress_verifying_keyserver_url">vérification du serveur de clefs...</string>
|
<string name="progress_verifying_keyserver_connection">vérification du serveur de clefs...</string>
|
||||||
<string name="progress_starting_orbot">Démarrage d\'Orbot...</string>
|
<string name="progress_starting_orbot">Démarrage d\'Orbot...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Chercher par nom, adresse courriel...</string>
|
<string name="hint_cloud_search_hint">Chercher par nom, adresse courriel...</string>
|
||||||
@@ -691,7 +691,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Ajouter un serveur de clefs</string>
|
<string name="add_keyserver_dialog_title">Ajouter un serveur de clefs</string>
|
||||||
<string name="edit_keyserver_dialog_title">Modifier le serveur de clefs</string>
|
<string name="edit_keyserver_dialog_title">Modifier le serveur de clefs</string>
|
||||||
<string name="add_keyserver_verified">Le serveur de clefs a été vérifié !</string>
|
<string name="add_keyserver_connection_verified">Le serveur de clefs a été vérifié !</string>
|
||||||
<string name="add_keyserver_without_verification">Le serveur de clefs a été ajouté sans vérification.</string>
|
<string name="add_keyserver_without_verification">Le serveur de clefs a été ajouté sans vérification.</string>
|
||||||
<string name="add_keyserver_invalid_url">URL invalide !</string>
|
<string name="add_keyserver_invalid_url">URL invalide !</string>
|
||||||
<string name="add_keyserver_connection_failed">Échec de connexion au serveur de clefs. Veuillez vérifier l\'URL et votre connexion Internet.</string>
|
<string name="add_keyserver_connection_failed">Échec de connexion au serveur de clefs. Veuillez vérifier l\'URL et votre connexion Internet.</string>
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
<string name="label_enable_compression">Abilitare compressione</string>
|
<string name="label_enable_compression">Abilitare compressione</string>
|
||||||
<string name="label_encrypt_filenames">Codifica nome dei file</string>
|
<string name="label_encrypt_filenames">Codifica nome dei file</string>
|
||||||
<string name="label_hidden_recipients">Nascondi destinatari</string>
|
<string name="label_hidden_recipients">Nascondi destinatari</string>
|
||||||
<string name="label_verify_keyserver">Verificare server chiavi</string>
|
<string name="label_verify_keyserver_connection">Verificare server chiavi</string>
|
||||||
<string name="label_enter_keyserver_url">Inserisci URL server chiavi</string>
|
<string name="label_enter_keyserver_url">Inserisci URL server chiavi</string>
|
||||||
<string name="label_keyserver_dialog_delete">Cancella server chiavi</string>
|
<string name="label_keyserver_dialog_delete">Cancella server chiavi</string>
|
||||||
<string name="pref_keyserver">Server chiavi OpenPGP</string>
|
<string name="pref_keyserver">Server chiavi OpenPGP</string>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
<string name="label_enable_compression">圧縮を有効</string>
|
<string name="label_enable_compression">圧縮を有効</string>
|
||||||
<string name="label_encrypt_filenames">暗号化するファイル名</string>
|
<string name="label_encrypt_filenames">暗号化するファイル名</string>
|
||||||
<string name="label_hidden_recipients">受信者を隠す</string>
|
<string name="label_hidden_recipients">受信者を隠す</string>
|
||||||
<string name="label_verify_keyserver">鍵サーバを検証</string>
|
<string name="label_verify_keyserver_connection">鍵サーバを検証</string>
|
||||||
<string name="label_enter_keyserver_url">鍵サーバのURLを入力</string>
|
<string name="label_enter_keyserver_url">鍵サーバのURLを入力</string>
|
||||||
<string name="label_keyserver_dialog_delete">鍵サーバの削除</string>
|
<string name="label_keyserver_dialog_delete">鍵サーバの削除</string>
|
||||||
<string name="label_theme">テーマ</string>
|
<string name="label_theme">テーマ</string>
|
||||||
@@ -382,7 +382,7 @@
|
|||||||
<string name="progress_deleting">鍵の削除中...</string>
|
<string name="progress_deleting">鍵の削除中...</string>
|
||||||
<string name="progress_con_saving">統合: キャッシュへ保存…</string>
|
<string name="progress_con_saving">統合: キャッシュへ保存…</string>
|
||||||
<string name="progress_con_reimport">統合: 再インポート中…</string>
|
<string name="progress_con_reimport">統合: 再インポート中…</string>
|
||||||
<string name="progress_verifying_keyserver_url">鍵サーバの検証...</string>
|
<string name="progress_verifying_keyserver_connection">鍵サーバの検証...</string>
|
||||||
<string name="progress_starting_orbot">Orbotを始める...</string>
|
<string name="progress_starting_orbot">Orbotを始める...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">名前、Email...で検索</string>
|
<string name="hint_cloud_search_hint">名前、Email...で検索</string>
|
||||||
@@ -674,7 +674,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">鍵サーバを追加</string>
|
<string name="add_keyserver_dialog_title">鍵サーバを追加</string>
|
||||||
<string name="edit_keyserver_dialog_title">鍵サーバの編集</string>
|
<string name="edit_keyserver_dialog_title">鍵サーバの編集</string>
|
||||||
<string name="add_keyserver_verified">鍵サーバを検証しました!</string>
|
<string name="add_keyserver_connection_verified">鍵サーバを検証しました!</string>
|
||||||
<string name="add_keyserver_without_verification">鍵サーバを検証なしで追加した。</string>
|
<string name="add_keyserver_without_verification">鍵サーバを検証なしで追加した。</string>
|
||||||
<string name="add_keyserver_invalid_url">無効なURLです!</string>
|
<string name="add_keyserver_invalid_url">無効なURLです!</string>
|
||||||
<string name="add_keyserver_connection_failed">鍵サーバへの接続し失敗。URLとあなたのインターネット接続をチェックしてください。</string>
|
<string name="add_keyserver_connection_failed">鍵サーバへの接続し失敗。URLとあなたのインターネット接続をチェックしてください。</string>
|
||||||
|
|||||||
@@ -151,7 +151,7 @@
|
|||||||
<string name="label_enable_compression">Compressie aanzetten</string>
|
<string name="label_enable_compression">Compressie aanzetten</string>
|
||||||
<string name="label_encrypt_filenames">Versleutel bestandsnamen</string>
|
<string name="label_encrypt_filenames">Versleutel bestandsnamen</string>
|
||||||
<string name="label_hidden_recipients">Verberg ontvangers</string>
|
<string name="label_hidden_recipients">Verberg ontvangers</string>
|
||||||
<string name="label_verify_keyserver">Sleutelserver verifiëren</string>
|
<string name="label_verify_keyserver_connection">Sleutelserver verifiëren</string>
|
||||||
<string name="label_enter_keyserver_url">Voer sleutelserver-URL in</string>
|
<string name="label_enter_keyserver_url">Voer sleutelserver-URL in</string>
|
||||||
<string name="label_keyserver_dialog_delete">Sleutelserver verwijderen</string>
|
<string name="label_keyserver_dialog_delete">Sleutelserver verwijderen</string>
|
||||||
<string name="label_theme">Thema</string>
|
<string name="label_theme">Thema</string>
|
||||||
@@ -366,7 +366,7 @@
|
|||||||
<string name="progress_deleting">bezig met verwijderen van sleutels…</string>
|
<string name="progress_deleting">bezig met verwijderen van sleutels…</string>
|
||||||
<string name="progress_con_saving">consolidatie: bezig met opslaan naar cache…</string>
|
<string name="progress_con_saving">consolidatie: bezig met opslaan naar cache…</string>
|
||||||
<string name="progress_con_reimport">consolidatie: bezig met opnieuw importeren…</string>
|
<string name="progress_con_reimport">consolidatie: bezig met opnieuw importeren…</string>
|
||||||
<string name="progress_verifying_keyserver_url">bezig met verifiëren van sleutelserver…</string>
|
<string name="progress_verifying_keyserver_connection">bezig met verifiëren van sleutelserver…</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Zoeken via naam, e-mail, ...</string>
|
<string name="hint_cloud_search_hint">Zoeken via naam, e-mail, ...</string>
|
||||||
<!--key bit length selections-->
|
<!--key bit length selections-->
|
||||||
@@ -648,7 +648,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Sleutelserver toevoegen</string>
|
<string name="add_keyserver_dialog_title">Sleutelserver toevoegen</string>
|
||||||
<string name="edit_keyserver_dialog_title">Sleutelserver bewerken</string>
|
<string name="edit_keyserver_dialog_title">Sleutelserver bewerken</string>
|
||||||
<string name="add_keyserver_verified">Sleutelserver geverifieerd!</string>
|
<string name="add_keyserver_connection_verified">Sleutelserver geverifieerd!</string>
|
||||||
<string name="add_keyserver_without_verification">Sleutelserver toegevoegd zonder verificatie.</string>
|
<string name="add_keyserver_without_verification">Sleutelserver toegevoegd zonder verificatie.</string>
|
||||||
<string name="add_keyserver_invalid_url">Ongeldige URL!</string>
|
<string name="add_keyserver_invalid_url">Ongeldige URL!</string>
|
||||||
<string name="add_keyserver_connection_failed">Kon niet verbinden met sleutelserver. Controleer de URL en je internetverbinding.</string>
|
<string name="add_keyserver_connection_failed">Kon niet verbinden met sleutelserver. Controleer de URL en je internetverbinding.</string>
|
||||||
|
|||||||
@@ -152,7 +152,7 @@
|
|||||||
<string name="label_enable_compression">Использовать сжатие</string>
|
<string name="label_enable_compression">Использовать сжатие</string>
|
||||||
<string name="label_encrypt_filenames">Шифровать имена файлов</string>
|
<string name="label_encrypt_filenames">Шифровать имена файлов</string>
|
||||||
<string name="label_hidden_recipients">Скрыть получателей</string>
|
<string name="label_hidden_recipients">Скрыть получателей</string>
|
||||||
<string name="label_verify_keyserver">Подтвердить сервер ключей</string>
|
<string name="label_verify_keyserver_connection">Подтвердить сервер ключей</string>
|
||||||
<string name="label_enter_keyserver_url">Введите адрес сервера ключей</string>
|
<string name="label_enter_keyserver_url">Введите адрес сервера ключей</string>
|
||||||
<string name="label_keyserver_dialog_delete">Удалить сервер ключей</string>
|
<string name="label_keyserver_dialog_delete">Удалить сервер ключей</string>
|
||||||
<string name="label_theme">Тема</string>
|
<string name="label_theme">Тема</string>
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
<string name="progress_deleting">удаление ключей...</string>
|
<string name="progress_deleting">удаление ключей...</string>
|
||||||
<string name="progress_con_saving">объединение: сохранение в кэш...</string>
|
<string name="progress_con_saving">объединение: сохранение в кэш...</string>
|
||||||
<string name="progress_con_reimport">объединение: реимпорт...</string>
|
<string name="progress_con_reimport">объединение: реимпорт...</string>
|
||||||
<string name="progress_verifying_keyserver_url">подтверждение сервера ключей...</string>
|
<string name="progress_verifying_keyserver_connection">подтверждение сервера ключей...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Искать через Имя, Email...</string>
|
<string name="hint_cloud_search_hint">Искать через Имя, Email...</string>
|
||||||
<!--key bit length selections-->
|
<!--key bit length selections-->
|
||||||
@@ -568,7 +568,7 @@
|
|||||||
<string name="view_key_fragment_no_system_contact"><нет></string>
|
<string name="view_key_fragment_no_system_contact"><нет></string>
|
||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Добавить сервер ключей</string>
|
<string name="add_keyserver_dialog_title">Добавить сервер ключей</string>
|
||||||
<string name="add_keyserver_verified">Сервер ключей подтверждён!</string>
|
<string name="add_keyserver_connection_verified">Сервер ключей подтверждён!</string>
|
||||||
<string name="add_keyserver_without_verification">Сервер ключей добавлен без подтверждения.</string>
|
<string name="add_keyserver_without_verification">Сервер ключей добавлен без подтверждения.</string>
|
||||||
<string name="add_keyserver_invalid_url">Неправильный адрес!</string>
|
<string name="add_keyserver_invalid_url">Неправильный адрес!</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
<string name="label_enable_compression">Омогући компресију</string>
|
<string name="label_enable_compression">Омогући компресију</string>
|
||||||
<string name="label_encrypt_filenames">Шифруј имена фајлова</string>
|
<string name="label_encrypt_filenames">Шифруј имена фајлова</string>
|
||||||
<string name="label_hidden_recipients">Сакриј примаоце</string>
|
<string name="label_hidden_recipients">Сакриј примаоце</string>
|
||||||
<string name="label_verify_keyserver">Овери сервер кључева</string>
|
<string name="label_verify_keyserver_connection">Овери сервер кључева</string>
|
||||||
<string name="label_enter_keyserver_url">Унесите УРЛ сервера кључева</string>
|
<string name="label_enter_keyserver_url">Унесите УРЛ сервера кључева</string>
|
||||||
<string name="label_keyserver_dialog_delete">Обриши сервер кључева</string>
|
<string name="label_keyserver_dialog_delete">Обриши сервер кључева</string>
|
||||||
<string name="label_theme">Тема</string>
|
<string name="label_theme">Тема</string>
|
||||||
@@ -390,7 +390,7 @@
|
|||||||
<string name="progress_deleting">бришем кључеве…</string>
|
<string name="progress_deleting">бришем кључеве…</string>
|
||||||
<string name="progress_con_saving">учвршћивање: уписујем у кеш…</string>
|
<string name="progress_con_saving">учвршћивање: уписујем у кеш…</string>
|
||||||
<string name="progress_con_reimport">учвршћивање: поново увозим…</string>
|
<string name="progress_con_reimport">учвршћивање: поново увозим…</string>
|
||||||
<string name="progress_verifying_keyserver_url">оверавам сервер кључева…</string>
|
<string name="progress_verifying_keyserver_connection">оверавам сервер кључева…</string>
|
||||||
<string name="progress_starting_orbot">Покрећем Орбот…</string>
|
<string name="progress_starting_orbot">Покрећем Орбот…</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Тражи преко имена, е-адресе…</string>
|
<string name="hint_cloud_search_hint">Тражи преко имена, е-адресе…</string>
|
||||||
@@ -709,7 +709,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Додај сервер кључева</string>
|
<string name="add_keyserver_dialog_title">Додај сервер кључева</string>
|
||||||
<string name="edit_keyserver_dialog_title">Промени сервер кључева</string>
|
<string name="edit_keyserver_dialog_title">Промени сервер кључева</string>
|
||||||
<string name="add_keyserver_verified">Сервер кључева оверен!</string>
|
<string name="add_keyserver_connection_verified">Сервер кључева оверен!</string>
|
||||||
<string name="add_keyserver_without_verification">Сервер кључева додат без оверивања.</string>
|
<string name="add_keyserver_without_verification">Сервер кључева додат без оверивања.</string>
|
||||||
<string name="add_keyserver_invalid_url">Неисправан УРЛ!</string>
|
<string name="add_keyserver_invalid_url">Неисправан УРЛ!</string>
|
||||||
<string name="add_keyserver_connection_failed">Неуспех повезивања са сервером кључева. Проверите УРЛ и вашу везу са интернетом.</string>
|
<string name="add_keyserver_connection_failed">Неуспех повезивања са сервером кључева. Проверите УРЛ и вашу везу са интернетом.</string>
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
<string name="label_enable_compression">Aktivera kompression</string>
|
<string name="label_enable_compression">Aktivera kompression</string>
|
||||||
<string name="label_encrypt_filenames">Kryptera filnamn</string>
|
<string name="label_encrypt_filenames">Kryptera filnamn</string>
|
||||||
<string name="label_hidden_recipients">Dölj mottagare</string>
|
<string name="label_hidden_recipients">Dölj mottagare</string>
|
||||||
<string name="label_verify_keyserver">Verifiera nyckelserver</string>
|
<string name="label_verify_keyserver_connection">Verifiera nyckelserver</string>
|
||||||
<string name="label_enter_keyserver_url">Ange nyckelserver-URL</string>
|
<string name="label_enter_keyserver_url">Ange nyckelserver-URL</string>
|
||||||
<string name="pref_keyserver">OpenPGP nyckelservrar</string>
|
<string name="pref_keyserver">OpenPGP nyckelservrar</string>
|
||||||
<string name="pref_keyserver_summary">Sök nycklar på valda OpenPGP nyckelservrar (HKP-protokollet)</string>
|
<string name="pref_keyserver_summary">Sök nycklar på valda OpenPGP nyckelservrar (HKP-protokollet)</string>
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
<string name="progress_deleting">raderar nycklar…</string>
|
<string name="progress_deleting">raderar nycklar…</string>
|
||||||
<string name="progress_con_saving">konsolidera: sparar till cache…</string>
|
<string name="progress_con_saving">konsolidera: sparar till cache…</string>
|
||||||
<string name="progress_con_reimport">konsolidera: återimporterar…</string>
|
<string name="progress_con_reimport">konsolidera: återimporterar…</string>
|
||||||
<string name="progress_verifying_keyserver_url">verifierar nyckelserver...</string>
|
<string name="progress_verifying_keyserver_connection">verifierar nyckelserver...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">Söker via Namn, E-post...</string>
|
<string name="hint_cloud_search_hint">Söker via Namn, E-post...</string>
|
||||||
<!--key bit length selections-->
|
<!--key bit length selections-->
|
||||||
@@ -565,7 +565,7 @@
|
|||||||
<string name="view_key_fragment_no_system_contact"><ingen></string>
|
<string name="view_key_fragment_no_system_contact"><ingen></string>
|
||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">Lägg till nyckelserver</string>
|
<string name="add_keyserver_dialog_title">Lägg till nyckelserver</string>
|
||||||
<string name="add_keyserver_verified">Nyckelserver verifierad!</string>
|
<string name="add_keyserver_connection_verified">Nyckelserver verifierad!</string>
|
||||||
<string name="add_keyserver_without_verification">Nyckelserver tillagd utan verifiering.</string>
|
<string name="add_keyserver_without_verification">Nyckelserver tillagd utan verifiering.</string>
|
||||||
<string name="add_keyserver_invalid_url">Ogiltig URL!</string>
|
<string name="add_keyserver_invalid_url">Ogiltig URL!</string>
|
||||||
<string name="add_keyserver_connection_failed">Misslyckades med att ansluta till nyckelserver. Kontrollera URL:en och din internetanslutning.</string>
|
<string name="add_keyserver_connection_failed">Misslyckades med att ansluta till nyckelserver. Kontrollera URL:en och din internetanslutning.</string>
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
<string name="label_enable_compression">啓用壓縮</string>
|
<string name="label_enable_compression">啓用壓縮</string>
|
||||||
<string name="label_encrypt_filenames">加密檔名</string>
|
<string name="label_encrypt_filenames">加密檔名</string>
|
||||||
<string name="label_hidden_recipients">隱藏收件人</string>
|
<string name="label_hidden_recipients">隱藏收件人</string>
|
||||||
<string name="label_verify_keyserver">驗證金鑰伺服器</string>
|
<string name="label_verify_keyserver_connection">驗證金鑰伺服器</string>
|
||||||
<string name="label_enter_keyserver_url">輸入金鑰伺服器網址</string>
|
<string name="label_enter_keyserver_url">輸入金鑰伺服器網址</string>
|
||||||
<string name="label_keyserver_dialog_delete">刪除金鑰伺服器</string>
|
<string name="label_keyserver_dialog_delete">刪除金鑰伺服器</string>
|
||||||
<string name="label_theme">主題</string>
|
<string name="label_theme">主題</string>
|
||||||
@@ -362,7 +362,7 @@
|
|||||||
<string name="progress_verifying_integrity">正在驗證完整性…</string>
|
<string name="progress_verifying_integrity">正在驗證完整性…</string>
|
||||||
<string name="progress_deleting_securely">正在安全地刪除 \'%s\'...</string>
|
<string name="progress_deleting_securely">正在安全地刪除 \'%s\'...</string>
|
||||||
<string name="progress_deleting">正在刪除金鑰…</string>
|
<string name="progress_deleting">正在刪除金鑰…</string>
|
||||||
<string name="progress_verifying_keyserver_url">正在驗證金鑰伺服器...</string>
|
<string name="progress_verifying_keyserver_connection">正在驗證金鑰伺服器...</string>
|
||||||
<string name="progress_starting_orbot">正在啟動Orbot...</string>
|
<string name="progress_starting_orbot">正在啟動Orbot...</string>
|
||||||
<!--action strings-->
|
<!--action strings-->
|
||||||
<string name="hint_cloud_search_hint">使用姓名,電子郵件尋找...</string>
|
<string name="hint_cloud_search_hint">使用姓名,電子郵件尋找...</string>
|
||||||
@@ -625,7 +625,7 @@
|
|||||||
<!--Add/Edit keyserver-->
|
<!--Add/Edit keyserver-->
|
||||||
<string name="add_keyserver_dialog_title">新增金鑰伺服器</string>
|
<string name="add_keyserver_dialog_title">新增金鑰伺服器</string>
|
||||||
<string name="edit_keyserver_dialog_title">編輯金鑰伺服器</string>
|
<string name="edit_keyserver_dialog_title">編輯金鑰伺服器</string>
|
||||||
<string name="add_keyserver_verified">已驗證金鑰伺服器!</string>
|
<string name="add_keyserver_connection_verified">已驗證金鑰伺服器!</string>
|
||||||
<string name="add_keyserver_without_verification">已新增金鑰伺服器但並未進行驗證。</string>
|
<string name="add_keyserver_without_verification">已新增金鑰伺服器但並未進行驗證。</string>
|
||||||
<string name="add_keyserver_invalid_url">URL無效!</string>
|
<string name="add_keyserver_invalid_url">URL無效!</string>
|
||||||
<string name="add_keyserver_connection_failed">連線到金鑰伺服器失敗。請確認金鑰伺服器網址及網路連線。</string>
|
<string name="add_keyserver_connection_failed">連線到金鑰伺服器失敗。請確認金鑰伺服器網址及網路連線。</string>
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
<string name="section_share_key">"Key"</string>
|
<string name="section_share_key">"Key"</string>
|
||||||
<string name="section_key_server">"Keyserver"</string>
|
<string name="section_key_server">"Keyserver"</string>
|
||||||
<string name="section_fingerprint">"Fingerprint"</string>
|
<string name="section_fingerprint">"Fingerprint"</string>
|
||||||
|
<string name="section_phrases">"Phrases"</string>
|
||||||
<string name="section_encrypt">"Encrypt"</string>
|
<string name="section_encrypt">"Encrypt"</string>
|
||||||
<string name="section_decrypt">"Decrypt / Verify"</string>
|
<string name="section_decrypt">"Decrypt / Verify"</string>
|
||||||
<string name="section_current_expiry">"Current expiry"</string>
|
<string name="section_current_expiry">"Current expiry"</string>
|
||||||
@@ -84,12 +85,14 @@
|
|||||||
<string name="btn_back">"Back"</string>
|
<string name="btn_back">"Back"</string>
|
||||||
<string name="btn_no">"No"</string>
|
<string name="btn_no">"No"</string>
|
||||||
<string name="btn_match">"Fingerprints match"</string>
|
<string name="btn_match">"Fingerprints match"</string>
|
||||||
|
<string name="btn_match_phrases">"Phrases match"</string>
|
||||||
<string name="btn_share_encrypted_signed">"Encrypt/sign and share text"</string>
|
<string name="btn_share_encrypted_signed">"Encrypt/sign and share text"</string>
|
||||||
<string name="btn_copy_encrypted_signed">"Encrypt/sign and copy text"</string>
|
<string name="btn_copy_encrypted_signed">"Encrypt/sign and copy text"</string>
|
||||||
<string name="btn_view_cert_key">"View certification key"</string>
|
<string name="btn_view_cert_key">"View certification key"</string>
|
||||||
<string name="btn_create_key">"Create key"</string>
|
<string name="btn_create_key">"Create key"</string>
|
||||||
<string name="btn_add_files">"Add file(s)"</string>
|
<string name="btn_add_files">"Add file(s)"</string>
|
||||||
<string name="btn_share_decrypted_text">"Share"</string>
|
<string name="btn_share_decrypted_text">"Share"</string>
|
||||||
|
<string name="btn_open_with">"Open with…"</string>
|
||||||
<string name="btn_copy_decrypted_text">"Copy decrypted text"</string>
|
<string name="btn_copy_decrypted_text">"Copy decrypted text"</string>
|
||||||
<string name="btn_decrypt_clipboard">"Read from clipboard"</string>
|
<string name="btn_decrypt_clipboard">"Read from clipboard"</string>
|
||||||
<string name="btn_decrypt_files">"Select input file"</string>
|
<string name="btn_decrypt_files">"Select input file"</string>
|
||||||
@@ -100,6 +103,7 @@
|
|||||||
<string name="btn_add_keyserver">"Add"</string>
|
<string name="btn_add_keyserver">"Add"</string>
|
||||||
<string name="btn_save_default">"Save as default"</string>
|
<string name="btn_save_default">"Save as default"</string>
|
||||||
<string name="btn_saved">"Saved!"</string>
|
<string name="btn_saved">"Saved!"</string>
|
||||||
|
<string name="btn_not_matching">"Doesn't match"</string>
|
||||||
|
|
||||||
<!-- menu -->
|
<!-- menu -->
|
||||||
<string name="menu_preferences">"Settings"</string>
|
<string name="menu_preferences">"Settings"</string>
|
||||||
@@ -116,7 +120,7 @@
|
|||||||
<string name="menu_update_all_keys">"Update all keys"</string>
|
<string name="menu_update_all_keys">"Update all keys"</string>
|
||||||
<string name="menu_advanced">"Extended information"</string>
|
<string name="menu_advanced">"Extended information"</string>
|
||||||
<string name="menu_certify_fingerprint">"Confirm via fingerprint"</string>
|
<string name="menu_certify_fingerprint">"Confirm via fingerprint"</string>
|
||||||
<string name="menu_certify_fingerprint_word">"Confirm via words"</string>
|
<string name="menu_certify_fingerprint_phrases">"Confirm via phrases"</string>
|
||||||
<string name="menu_share_log">"Share Log"</string>
|
<string name="menu_share_log">"Share Log"</string>
|
||||||
|
|
||||||
<string name="menu_keyserver_add">"Add"</string>
|
<string name="menu_keyserver_add">"Add"</string>
|
||||||
@@ -173,8 +177,9 @@
|
|||||||
<string name="label_encrypt_filenames">"Encrypt filenames"</string>
|
<string name="label_encrypt_filenames">"Encrypt filenames"</string>
|
||||||
<string name="label_hidden_recipients">"Hide recipients"</string>
|
<string name="label_hidden_recipients">"Hide recipients"</string>
|
||||||
|
|
||||||
<string name="label_verify_keyserver">"Verify keyserver"</string>
|
<string name="label_verify_keyserver_connection">"Test connection"</string>
|
||||||
<string name="label_enter_keyserver_url">"Enter keyserver URL"</string>
|
<string name="label_only_trusted_keyserver">"Only trusted keyserver"</string>
|
||||||
|
<string name="label_enter_keyserver_url">"URL"</string>
|
||||||
<string name="label_keyserver_dialog_delete">"Delete keyserver"</string>
|
<string name="label_keyserver_dialog_delete">"Delete keyserver"</string>
|
||||||
<string name="label_theme">"Theme"</string>
|
<string name="label_theme">"Theme"</string>
|
||||||
|
|
||||||
@@ -195,8 +200,8 @@
|
|||||||
<string name="label_experimental_settings_desc_title">"Warning"</string>
|
<string name="label_experimental_settings_desc_title">"Warning"</string>
|
||||||
<string name="label_experimental_settings_desc_summary">"These features are not yet finished or results of user experience/security research. Thus, don't rely on their security and please don't report issues you encounter!"</string>
|
<string name="label_experimental_settings_desc_summary">"These features are not yet finished or results of user experience/security research. Thus, don't rely on their security and please don't report issues you encounter!"</string>
|
||||||
|
|
||||||
<string name="label_experimental_settings_word_confirm_title">"Word Confirm"</string>
|
<string name="label_experimental_settings_word_confirm_title">"Phrase Confirmation"</string>
|
||||||
<string name="label_experimental_settings_word_confirm_summary">"Confirm keys with words instead of hexadecimal fingerprints"</string>
|
<string name="label_experimental_settings_word_confirm_summary">"Confirm keys with phrases instead of hexadecimal fingerprints"</string>
|
||||||
<string name="label_experimental_settings_linked_identities_title">"Linked Identities"</string>
|
<string name="label_experimental_settings_linked_identities_title">"Linked Identities"</string>
|
||||||
<string name="label_experimental_settings_linked_identities_summary">"Link keys to Twitter, GitHub, websites or DNS (similar to keybase.io but decentralized)"</string>
|
<string name="label_experimental_settings_linked_identities_summary">"Link keys to Twitter, GitHub, websites or DNS (similar to keybase.io but decentralized)"</string>
|
||||||
<string name="label_experimental_settings_keybase_title">"Keybase.io Proofs"</string>
|
<string name="label_experimental_settings_keybase_title">"Keybase.io Proofs"</string>
|
||||||
@@ -446,7 +451,7 @@
|
|||||||
<string name="progress_con_saving">"consolidate: saving to cache…"</string>
|
<string name="progress_con_saving">"consolidate: saving to cache…"</string>
|
||||||
<string name="progress_con_reimport">"consolidate: reimporting…"</string>
|
<string name="progress_con_reimport">"consolidate: reimporting…"</string>
|
||||||
|
|
||||||
<string name="progress_verifying_keyserver_url">"verifying keyserver…"</string>
|
<string name="progress_verifying_keyserver_connection">"verifying connection…"</string>
|
||||||
|
|
||||||
<string name="progress_starting_orbot">"Starting Orbot…"</string>
|
<string name="progress_starting_orbot">"Starting Orbot…"</string>
|
||||||
|
|
||||||
@@ -779,9 +784,10 @@
|
|||||||
<!-- Add/Edit keyserver -->
|
<!-- Add/Edit keyserver -->
|
||||||
<string name="add_keyserver_dialog_title">"Add keyserver"</string>
|
<string name="add_keyserver_dialog_title">"Add keyserver"</string>
|
||||||
<string name="edit_keyserver_dialog_title">"Edit keyserver"</string>
|
<string name="edit_keyserver_dialog_title">"Edit keyserver"</string>
|
||||||
<string name="add_keyserver_verified">"Keyserver verified!"</string>
|
<string name="add_keyserver_connection_verified">"Connection verified!"</string>
|
||||||
<string name="add_keyserver_without_verification">"Keyserver added without verification."</string>
|
<string name="add_keyserver_without_verification">"Keyserver added without verification."</string>
|
||||||
<string name="add_keyserver_invalid_url">"Invalid URL!"</string>
|
<string name="add_keyserver_invalid_url">"Invalid URL!"</string>
|
||||||
|
<string name="add_keyserver_keyserver_not_trusted">"Keyserver is not one of the trusted ones (no pinned certificate available)!"</string>
|
||||||
<string name="add_keyserver_connection_failed">"Failed to connect to keyserver. Please check the URL and your Internet connection."</string>
|
<string name="add_keyserver_connection_failed">"Failed to connect to keyserver. Please check the URL and your Internet connection."</string>
|
||||||
<string name="keyserver_preference_deleted">"%s deleted"</string>
|
<string name="keyserver_preference_deleted">"%s deleted"</string>
|
||||||
<string name="keyserver_preference_cannot_delete_last">"Cannot delete last keyserver. At least one is required!"</string>
|
<string name="keyserver_preference_cannot_delete_last">"Cannot delete last keyserver. At least one is required!"</string>
|
||||||
@@ -990,6 +996,7 @@
|
|||||||
<string name="msg_kc_uid_no_cert">"No valid self-certificate found for user ID '%s', removing from ring"</string>
|
<string name="msg_kc_uid_no_cert">"No valid self-certificate found for user ID '%s', removing from ring"</string>
|
||||||
<string name="msg_kc_uid_remove">"Removing invalid user ID '%s'"</string>
|
<string name="msg_kc_uid_remove">"Removing invalid user ID '%s'"</string>
|
||||||
<string name="msg_kc_uid_dup">"Removing duplicate user ID '%s'. The keyring contained two of them. This may result in missing certificates!"</string>
|
<string name="msg_kc_uid_dup">"Removing duplicate user ID '%s'. The keyring contained two of them. This may result in missing certificates!"</string>
|
||||||
|
<string name="msg_kc_uid_too_many">"Removing user ID '%s'. More than 100 User IDs are not imported!"</string>
|
||||||
<string name="msg_kc_uid_warn_encoding">"User ID does not verify as UTF-8!"</string>
|
<string name="msg_kc_uid_warn_encoding">"User ID does not verify as UTF-8!"</string>
|
||||||
<string name="msg_kc_uat_jpeg">"Processing user attribute of type JPEG"</string>
|
<string name="msg_kc_uat_jpeg">"Processing user attribute of type JPEG"</string>
|
||||||
<string name="msg_kc_uat_unknown">"Processing user attribute of unknown type"</string>
|
<string name="msg_kc_uat_unknown">"Processing user attribute of unknown type"</string>
|
||||||
@@ -1362,7 +1369,7 @@
|
|||||||
<string name="msg_data_detached_unsupported">"Unsupported type of detached signature!"</string>
|
<string name="msg_data_detached_unsupported">"Unsupported type of detached signature!"</string>
|
||||||
<string name="msg_data_error_io">"Error reading input data!"</string>
|
<string name="msg_data_error_io">"Error reading input data!"</string>
|
||||||
<string name="msg_data_error_openpgp">"Error processing OpenPGP data!"</string>
|
<string name="msg_data_error_openpgp">"Error processing OpenPGP data!"</string>
|
||||||
<string name="msg_data_mime_error">"Error parsing MIME data!"</string>
|
<string name="msg_data_mime_bad">"Could not parse as MIME data"</string>
|
||||||
<string name="msg_data_mime_filename">"Filename: '%s'"</string>
|
<string name="msg_data_mime_filename">"Filename: '%s'"</string>
|
||||||
<string name="msg_data_mime_length">"Content-Length: %s"</string>
|
<string name="msg_data_mime_length">"Content-Length: %s"</string>
|
||||||
<string name="msg_data_mime">"Parsing MIME data structure"</string>
|
<string name="msg_data_mime">"Parsing MIME data structure"</string>
|
||||||
@@ -1441,9 +1448,8 @@
|
|||||||
<string name="certs_text">"Only validated self-certificates and validated certificates created with your keys are displayed here."</string>
|
<string name="certs_text">"Only validated self-certificates and validated certificates created with your keys are displayed here."</string>
|
||||||
<string name="section_uids_to_certify">"Identities for "</string>
|
<string name="section_uids_to_certify">"Identities for "</string>
|
||||||
<string name="certify_text">"The keys you are importing contain “identities”: names and email addresses. Select exactly those for confirmation which match what you expected."</string>
|
<string name="certify_text">"The keys you are importing contain “identities”: names and email addresses. Select exactly those for confirmation which match what you expected."</string>
|
||||||
<string name="certify_fingerprint_text">"Compare the displayed fingerprint, character by character, with the one displayed on your partners device."</string>
|
<string name="certify_fingerprint_text">"Compare the fingerprint, character by character, with the one displayed on your partner’s device."</string>
|
||||||
<string name="certify_fingerprint_text_words">"Compare the displayed fingerprint, word by word, with the one displayed on your partners device."</string>
|
<string name="certify_fingerprint_text_phrases">"Compare these phrases with the ones displayed on your partner’s device."</string>
|
||||||
<string name="certify_fingerprint_text2">"Do the fingerprints match?"</string>
|
|
||||||
<string name="label_revocation">"Revocation Reason"</string>
|
<string name="label_revocation">"Revocation Reason"</string>
|
||||||
<string name="label_cert_type">"Type"</string>
|
<string name="label_cert_type">"Type"</string>
|
||||||
<string name="error_key_not_found">"Key not found!"</string>
|
<string name="error_key_not_found">"Key not found!"</string>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Expand the Tools directory and select "Android SDK Build-tools (Version 21.1.2)"
|
|||||||
Expand the Extras directory and install "Android Support Repository"
|
Expand the Extras directory and install "Android Support Repository"
|
||||||
Select everything for the newest SDK Platform, API 22, and also API 21
|
Select everything for the newest SDK Platform, API 22, and also API 21
|
||||||
5. Export ANDROID_HOME pointing to your Android SDK
|
5. Export ANDROID_HOME pointing to your Android SDK
|
||||||
6. Execute ``./gradlew build``
|
6. Execute ``./gradlew assembleDebug``
|
||||||
7. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk``
|
7. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk``
|
||||||
|
|
||||||
### Run Tests
|
### Run Tests
|
||||||
|
|||||||
2
extern/KeybaseLib
vendored
2
extern/KeybaseLib
vendored
Submodule extern/KeybaseLib updated: 0b0a60533c...b89648f500
Reference in New Issue
Block a user