aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OpenKeychain/build.gradle38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java61
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java34
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryFileProvider.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java48
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java34
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java113
-rw-r--r--OpenKeychain/src/main/res/layout-w600dp/backup_code_fragment.xml (renamed from OpenKeychain/src/main/res/layout-land/backup_code_fragment.xml)2
-rw-r--r--OpenKeychain/src/main/res/layout-w600dp/security_token_operation_activity.xml (renamed from OpenKeychain/src/main/res/layout-land/security_token_operation_activity.xml)0
-rw-r--r--OpenKeychain/src/main/res/layout/backup_code_fragment.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/passphrase_dialog_backup_code.xml4
-rw-r--r--OpenKeychain/src/main/res/values-sw360dp/styles.xml9
-rw-r--r--OpenKeychain/src/main/res/values-sw400dp/styles.xml9
-rw-r--r--OpenKeychain/src/main/res/values/styles.xml7
-rw-r--r--build.gradle2
m---------extern/openpgp-api-lib0
27 files changed, 334 insertions, 220 deletions
diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle
index 0eedb8394..523750d74 100644
--- a/OpenKeychain/build.gradle
+++ b/OpenKeychain/build.gradle
@@ -43,20 +43,20 @@ dependencies {
// JCenter etc.
compile 'com.eftimoff:android-patternview:1.0.5@aar'
- compile 'com.journeyapps:zxing-android-embedded:3.1.0@aar'
+ compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile 'com.google.zxing:core:3.2.1'
compile 'com.jpardogo.materialtabstrip:library:1.1.0'
compile 'com.getbase:floatingactionbutton:1.10.1'
compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0'
compile 'org.ocpsoft.prettytime:prettytime:4.0.1.Final'
- compile 'com.splitwise:tokenautocomplete:2.0.2@aar'
+ compile 'com.splitwise:tokenautocomplete:2.0.5@aar'
compile 'com.github.pinball83:masked-edittext:1.0.3'
compile 'se.emilsjolander:stickylistheaders:2.7.0'
compile 'org.sufficientlysecure:html-textview:1.3'
compile 'org.sufficientlysecure:donations:2.4'
compile 'com.nispok:snackbar:2.11.0'
- compile 'com.squareup.okhttp:okhttp:2.7.1'
- compile 'com.squareup.okhttp:okhttp-urlconnection:2.7.1'
+ compile 'com.squareup.okhttp:okhttp:2.7.5'
+ compile 'com.squareup.okhttp:okhttp-urlconnection:2.7.5'
compile 'org.apache.james:apache-mime4j-core:0.7.2'
compile 'org.apache.james:apache-mime4j-dom:0.7.2'
compile 'org.thoughtcrime.ssl.pinning:AndroidPinning:1.0.0'
@@ -94,21 +94,21 @@ dependencyVerification {
'com.android.support:recyclerview-v7:81aad9ff4104a20d8d5cda49dbbe0f2925e7dcd607a689374db843c6f2eca20a',
'com.android.support:cardview-v7:b2c2c070a78fbf7683ab4d84b23f9eecf2af3848f126775d048ae62238b55aed',
'com.eftimoff:android-patternview:594dde382fb9a445ef0c92d614f6f127727ce699f124de8167929e10f298bf8b',
- 'com.journeyapps:zxing-android-embedded:90840a4457e68962fdfb74f691c6a736be7596291001045241901f1f0e6db2ac',
+ 'com.journeyapps:zxing-android-embedded:afe4cd51d95ba0fd3a4bfe08c5a160bd32602aa174d511600ac824b6de4c79f1',
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
'com.getbase:floatingactionbutton:3edefa511aac4d90794c7b0496aca59cff2eee1e32679247b4f85acbeee05240',
'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13',
'org.ocpsoft.prettytime:prettytime:ef7098d973ae78b57d1a22dc37d3b8a771bf030301300e24055d676b6cdc5e75',
- 'com.splitwise:tokenautocomplete:2fc238424130b42155b5f2e39799a90bbbd13b148850afbe534ab08bb913c7f7',
+ 'com.splitwise:tokenautocomplete:f86b8cd80e8fa1336f47d86b8ce862e1a40bdc8e206ac38c56c8e41a3d05a331',
'com.github.pinball83:masked-edittext:b1913d86482c7066ebb7831696773ac131865dc441cf8a3fc41d3b7d5691724e',
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
'org.sufficientlysecure:donations:96f8197bab26dfe41900d824f10f8f1914519cd62eedb77bdac5b223eccdf0a6',
'org.sufficientlysecure:html-textview:39048e35894e582adada388e6c00631803283f8defed8e07ad58a5f284f272ee',
- 'com.squareup.okhttp:okhttp:8df336e3e93b22ba8c05da5d94caf968950db845869c7ca16ed682e065135aa8',
+ 'com.squareup.okhttp:okhttp:88ac9fd1bb51f82bcc664cc1eb9c225c90dc4389d660231b4cc737bebfe7d0aa',
'com.nispok:snackbar:46b5eb9d630d329e13c2ce00ee9fb115ffb66c23c72cff32ee97eedd76824c6f',
'org.apache.james:apache-mime4j-core:4d7434c68f94b81a253c12f28e6bbb4d6239c361d6086a46e22e594bb43ac660',
- 'com.squareup.okhttp:okhttp-urlconnection:8dce03792fd7b5f089dc4fc0fdcecbbe50ae6cca21cb08a787a3b902a9914111',
+ 'com.squareup.okhttp:okhttp-urlconnection:6ae7c527abd2253e7c499ded790174f8f37d9676add63d9e23a76f3ba0588c07',
'org.thoughtcrime.ssl.pinning:AndroidPinning:afa1d74e699257fa75cb109ff29bac50726ef269c6e306bdeffe8223cee06ef4',
'org.apache.james:apache-mime4j-dom:7e6b06ee164a1c21b7e477249ea0b74a18fddce44764e5764085f58dd8c34633',
'com.mikepenz:materialdrawer:4e2644f454cc2ce48b956536d3339957c3f592adb2e0b6dad72d477da29f7677',
@@ -119,15 +119,15 @@ dependencyVerification {
'com.mikepenz:google-material-typeface:48b2712de87d542e9b050846e9f602238a367f38e2d5e8ea4557c5b12adfcbec',
'com.fidesmo:nordpol-android:56f43fe2b1676817bcb4085926de14a08282ef6729c855c198d81aec62b20d65',
'com.mikepenz:community-material-typeface:990acfcfb892a733d36748fe29176bd61dd5ab34bc8ca1c591200e639d955b99',
-// 'OpenKeychain.extern.bouncycastle:core:b22dfb37e09fb520683dd0ba089351787560a75b59b60822143f633ec984cab5',
-// 'OpenKeychain.extern.openpgp-api-lib:openpgp-api:fbd9a53022747bdc3c5b0926c6f9cbcbee19e766dd96f090a4310dc65026b393',
-// 'OpenKeychain.extern.openkeychain-api-lib:openkeychain-intents:9263330c00497b7bb70502160f50c8396228129376f48f4f5656d28360a2edac',
-// 'OpenKeychain.extern.bouncycastle:prov:2d93a52e1b519995b18c0a92a1e59a2773d67d9b466a9cce6af5202a66502577',
-// 'OpenKeychain.extern.bouncycastle:pg:1397025acf36be36d329c0345b136af776be82fe5d6dad70cc06db09d2f02201',
-// 'OpenKeychain.extern.safeslinger-exchange:safeslinger-exchange:989fcc0eba663489a41aa166f6bb39f21271d980faddea5f06ab75339e792d10',
+// 'OpenKeychain.extern.bouncycastle:core:5321ccaae5c49cd681d6cc222252d8fc4fe033978a3c79ae63f842e701bb5197',
+// 'OpenKeychain.extern.openpgp-api-lib:openpgp-api:e7121ea04a39bdc62e56db30e273de3c53c1e3baf21416cfeb551e6652bef639',
+// 'OpenKeychain.extern.openkeychain-api-lib:openkeychain-intents:bd88737b61c0efa8cf9fc2cf3da2e2b827c77e4c0b5342b7a665bcc58daca17f',
+// 'OpenKeychain.extern.bouncycastle:prov:7fe09ee4fc9e7653f430f1fa30eacb2ef594f4cc3f1b27edcce17da27af7af10',
+// 'OpenKeychain.extern.bouncycastle:pg:1efe7abff1d94630064606f1a1c8b55e41a57953d3792524b2a07bc9821b3802',
+// 'OpenKeychain.extern.safeslinger-exchange:safeslinger-exchange:202943c4c9affdf52ee85840b0ff65ceea12b7c3f4e5f1e378e906815769613e',
'com.android.support:support-annotations:7f21659b084da073b77b6f7fe7ab250c4f23346238d4efdbbbb937e017ae4693',
-// 'OpenKeychain.extern:minidns:109d5851ab351d7628ed62a0ed96b40598952424e56657c17debbeb4a704f0ce',
-// 'OpenKeychain.extern.KeybaseLib:Lib:c5b1567ff781c311240e83f865c4ba76ae435eb00994529b8364371abf0d76de',
+// 'OpenKeychain.extern:minidns:c026deb65796d29d347ee6a0d61daf4e8cd97e714eb540386dc0764bddf96cd3',
+// 'OpenKeychain.extern.KeybaseLib:Lib:83be9cc36fd6807dbec5b4ba7e3c2c1287a70e43bbe564abf20d096299848b73',
'com.android.support:animated-vector-drawable:4d8366192dedc8ca9e6ff62e9be9ba6145166554d61befc9df312e8328836f55',
'com.android.support:support-vector-drawable:0f43fc47b0d2797c4e1851aba61ab87a4fd33323348c2bd022821aaac052a266',
'com.squareup.okio:okio:114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266',
@@ -141,14 +141,12 @@ android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
- // TODO: remove org.apache dependencies in LinkedTokenResource etc.
- useLibrary 'org.apache.http.legacy'
defaultConfig {
minSdkVersion 15
targetSdkVersion 23
- versionCode 39000
- versionName "3.9"
+ versionCode 39300
+ versionName "3.9.3"
applicationId "org.sufficientlysecure.keychain"
// the androidjunitrunner is broken regarding coverage, see here:
// https://code.google.com/p/android/issues/detail?id=170607
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
index e5a128e32..6a584a939 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
@@ -2,12 +2,10 @@ package org.sufficientlysecure.keychain.linked;
import android.content.Context;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.params.BasicHttpParams;
+import com.squareup.okhttp.CertificatePinner;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
import org.json.JSONException;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
@@ -18,12 +16,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
-import org.thoughtcrime.ssl.pinning.util.PinningHelper;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.HashMap;
@@ -233,46 +227,35 @@ public abstract class LinkedTokenResource extends LinkedResource {
}
- @SuppressWarnings("deprecation") // HttpRequestBase is deprecated
- public static String getResponseBody(Context context, HttpRequestBase request)
- throws IOException, HttpStatusException {
- return getResponseBody(context, request, null);
+
+ private static CertificatePinner getCertificatePinner(String hostname, String[] pins){
+ CertificatePinner.Builder builder = new CertificatePinner.Builder();
+ for(String pin : pins){
+ builder.add(hostname,pin);
+ }
+ return builder.build();
}
- @SuppressWarnings("deprecation") // HttpRequestBase is deprecated
- public static String getResponseBody(Context context, HttpRequestBase request, String[] pins)
- throws IOException, HttpStatusException {
- StringBuilder sb = new StringBuilder();
+ public static String getResponseBody(Request request, String... pins)
+ throws IOException, HttpStatusException {
- request.setHeader("User-Agent", "Open Keychain");
+ Log.d("Connection to: "+request.url().getHost(),"");
+ OkHttpClient client = new OkHttpClient();
+ if(pins !=null){
+ client.setCertificatePinner(getCertificatePinner(request.url().getHost(),pins));
+ }
+ Response response = client.newCall(request).execute();
- HttpClient httpClient;
- if (pins == null) {
- httpClient = new DefaultHttpClient(new BasicHttpParams());
- } else {
- httpClient = PinningHelper.getPinnedHttpClient(context, pins);
- }
- HttpResponse response = httpClient.execute(request);
- int statusCode = response.getStatusLine().getStatusCode();
- String reason = response.getStatusLine().getReasonPhrase();
+ int statusCode = response.code();
+ String reason = response.message();
if (statusCode != 200) {
throw new HttpStatusException(statusCode, reason);
}
- HttpEntity entity = response.getEntity();
- InputStream inputStream = entity.getContent();
-
- BufferedReader bReader = new BufferedReader(
- new InputStreamReader(inputStream, "UTF-8"), 8);
- String line;
- while ((line = bReader.readLine()) != null) {
- sb.append(line);
- }
-
- return sb.toString();
+ return response.body().string();
}
public static class HttpStatusException extends Throwable {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
index 82240c405..d6b8640e3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
@@ -6,7 +6,7 @@ import android.net.Uri;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
-import org.apache.http.client.methods.HttpGet;
+import com.squareup.okhttp.Request;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
@@ -32,14 +32,16 @@ public class GenericHttpsResource extends LinkedTokenResource {
token, "0x" + KeyFormattingUtils.convertFingerprintToHex(fingerprint).substring(24));
}
- @SuppressWarnings("deprecation") // HttpGet is deprecated
@Override
protected String fetchResource (Context context, OperationLog log, int indent)
throws HttpStatusException, IOException {
log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
- HttpGet httpGet = new HttpGet(mSubUri);
- return getResponseBody(context, httpGet);
+ Request request = new Request.Builder()
+ .url(mSubUri.toURL())
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
+ return getResponseBody(request);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
index 7a97ffd96..134582ae1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
@@ -6,7 +6,7 @@ import android.net.Uri;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
-import org.apache.http.client.methods.HttpGet;
+import com.squareup.okhttp.Request;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -47,7 +47,7 @@ public class GithubResource extends LinkedTokenResource {
return String.format(context.getResources().getString(R.string.linked_id_github_text), token);
}
- @SuppressWarnings("deprecation") // HttpGet is deprecated
+
@Override
protected String fetchResource (Context context, OperationLog log, int indent)
throws HttpStatusException, IOException, JSONException {
@@ -55,8 +55,11 @@ public class GithubResource extends LinkedTokenResource {
log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
indent += 1;
- HttpGet httpGet = new HttpGet("https://api.github.com/gists/" + mGistId);
- String response = getResponseBody(context, httpGet);
+ Request request = new Request.Builder()
+ .url("https://api.github.com/gists/" + mGistId)
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
+ String response = getResponseBody(request);
JSONObject obj = new JSONObject(response);
@@ -79,7 +82,7 @@ public class GithubResource extends LinkedTokenResource {
}
- @Deprecated // not used for now, but could be used to pick up earlier posted gist if already present?
+
@SuppressWarnings({ "deprecation", "unused" })
public static GithubResource searchInGithubStream(
Context context, String screenName, String needle, OperationLog log) {
@@ -94,12 +97,12 @@ public class GithubResource extends LinkedTokenResource {
try {
JSONArray array; {
- HttpGet httpGet =
- new HttpGet("https://api.github.com/users/" + screenName + "/gists");
- httpGet.setHeader("Content-Type", "application/json");
- httpGet.setHeader("User-Agent", "OpenKeychain");
-
- String response = getResponseBody(context, httpGet);
+ Request request = new Request.Builder()
+ .url("https://api.github.com/users/" + screenName + "/gists")
+ .addHeader("Content-Type", "application/json")
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
+ String response = getResponseBody(request);
array = new JSONArray(response);
}
@@ -116,10 +119,13 @@ public class GithubResource extends LinkedTokenResource {
continue;
}
String id = obj.getString("id");
- HttpGet httpGet = new HttpGet("https://api.github.com/gists/" + id);
- httpGet.setHeader("User-Agent", "OpenKeychain");
- JSONObject gistObj = new JSONObject(getResponseBody(context, httpGet));
+ Request request = new Request.Builder()
+ .url("https://api.github.com/gists/" + id)
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
+
+ JSONObject gistObj = new JSONObject(getResponseBody(request));
JSONObject gistFiles = gistObj.getJSONObject("files");
Iterator<String> gistIt = gistFiles.keys();
if (!gistIt.hasNext()) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
index 73e3d3643..b0f02c43c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
@@ -7,11 +7,11 @@ import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.util.Log;
+import com.squareup.okhttp.MediaType;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.RequestBody;
import com.textuality.keybase.lib.JWalk;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -84,18 +84,19 @@ public class TwitterResource extends LinkedTokenResource {
return null;
}
- HttpGet httpGet =
- new HttpGet("https://api.twitter.com/1.1/statuses/show.json"
- + "?id=" + mTweetId
- + "&include_entities=false");
-
// construct a normal HTTPS request and include an Authorization
// header with the value of Bearer <>
- httpGet.setHeader("Authorization", "Bearer " + authToken);
- httpGet.setHeader("Content-Type", "application/json");
+ Request request = new Request.Builder()
+ .url("https://api.twitter.com/1.1/statuses/show.json"
+ + "?id=" + mTweetId
+ + "&include_entities=false")
+ .addHeader("Authorization", "Bearer " + authToken)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
try {
- String response = getResponseBody(context, httpGet, CERT_PINS);
+ String response = getResponseBody(request, CERT_PINS);
JSONObject obj = new JSONObject(response);
JSONObject user = obj.getJSONObject("user");
if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) {
@@ -157,21 +158,20 @@ public class TwitterResource extends LinkedTokenResource {
return null;
}
- HttpGet httpGet =
- new HttpGet("https://api.twitter.com/1.1/statuses/user_timeline.json"
+ Request request = new Request.Builder()
+ .url("https://api.twitter.com/1.1/statuses/user_timeline.json"
+ "?screen_name=" + screenName
+ "&count=15"
+ "&include_rts=false"
+ "&trim_user=true"
- + "&exclude_replies=true");
-
- // construct a normal HTTPS request and include an Authorization
- // header with the value of Bearer <>
- httpGet.setHeader("Authorization", "Bearer " + authToken);
- httpGet.setHeader("Content-Type", "application/json");
+ + "&exclude_replies=true")
+ .addHeader("Authorization", "Bearer " + authToken)
+ .addHeader("Content-Type", "application/json")
+ .addHeader("User-Agent", "OpenKeychain")
+ .build();
try {
- String response = getResponseBody(context, httpGet, CERT_PINS);
+ String response = getResponseBody(request, CERT_PINS);
JSONArray array = new JSONArray(response);
for (int i = 0; i < array.length(); i++) {
@@ -216,12 +216,20 @@ public class TwitterResource extends LinkedTokenResource {
String base64Encoded = rot13("D293FQqanH0jH29KIaWJER5DomqSGRE2Ewc1LJACn3cbD1c"
+ "Fq1bmqSAQAz5MI2cIHKOuo3cPoRAQI1OyqmIVFJS6LHMXq2g6MRLkIj") + "==";
+ RequestBody requestBody = RequestBody.create(
+ MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"),
+ "grant_type=client_credentials");
+
// Step 2: Obtain a bearer token
- HttpPost httpPost = new HttpPost("https://api.twitter.com/oauth2/token");
- httpPost.setHeader("Authorization", "Basic " + base64Encoded);
- httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
- httpPost.setEntity(new StringEntity("grant_type=client_credentials"));
- JSONObject rawAuthorization = new JSONObject(getResponseBody(context, httpPost, CERT_PINS));
+ Request request = new Request.Builder()
+ .url("https://api.twitter.com/oauth2/token")
+ .addHeader("Authorization", "Basic " + base64Encoded)
+ .addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
+ .addHeader("User-Agent", "OpenKeychain")
+ .post(requestBody)
+ .build();
+
+ JSONObject rawAuthorization = new JSONObject(getResponseBody(request, CERT_PINS));
// Applications should verify that the value associated with the
// token_type key of the returned object is bearer
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
index 43fc11b84..6682cc6e7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
@@ -119,8 +119,9 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
// inform the storage provider about the mime type for this uri
if (decryptResult.getDecryptionMetadata() != null) {
- TemporaryFileProvider.setMimeType(mContext, currentInputUri,
- decryptResult.getDecryptionMetadata().getMimeType());
+ OpenPgpMetadata meta = decryptResult.getDecryptionMetadata();
+ TemporaryFileProvider.setName(mContext, currentInputUri, meta.getFilename());
+ TemporaryFileProvider.setMimeType(mContext, currentInputUri, meta.getMimeType());
}
} else {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 009876045..328daa7ff 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -470,7 +470,13 @@ public class PgpSignEncryptOperation extends BaseOperation {
InputStream in = new BufferedInputStream(inputData.getInputStream());
if (enableCompression) {
- compressGen = new PGPCompressedDataGenerator(input.getCompressionAlgorithm());
+ // Use preferred compression algo
+ int algo = input.getCompressionAlgorithm();
+ if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
+ algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
+ }
+
+ compressGen = new PGPCompressedDataGenerator(algo);
bcpgOut = new BCPGOutputStream(compressGen.open(out));
} else {
bcpgOut = new BCPGOutputStream(out);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 2a4d898bc..c3697997f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -279,37 +279,35 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER");
db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB");
case 7:
- // consolidate
- case 8:
// new table for allowed key ids in API
try {
db.execSQL(CREATE_API_APPS_ALLOWED_KEYS);
} catch (Exception e) {
// never mind, the column probably already existed
}
- case 9:
+ case 8:
// tbale name for user_ids changed to user_packets
db.execSQL("DROP TABLE IF EXISTS certs");
db.execSQL("DROP TABLE IF EXISTS user_ids");
db.execSQL(CREATE_USER_PACKETS);
db.execSQL(CREATE_CERTS);
- case 10:
+ case 9:
// do nothing here, just consolidate
- case 11:
+ case 10:
// fix problems in database, see #1402 for details
// https://github.com/open-keychain/open-keychain/issues/1402
db.execSQL("DELETE FROM api_accounts WHERE key_id BETWEEN 0 AND 3");
- case 12:
+ case 11:
db.execSQL(CREATE_UPDATE_KEYS);
- case 13:
+ case 12:
// do nothing here, just consolidate
- case 14:
+ case 13:
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysColumns.RANK + ");");
db.execSQL("CREATE INDEX uids_by_rank ON user_packets (" + UserPacketsColumns.RANK + ", "
+ UserPacketsColumns.USER_ID + ", " + UserPacketsColumns.MASTER_KEY_ID + ");");
db.execSQL("CREATE INDEX verified_certs ON certs ("
+ CertsColumns.VERIFIED + ", " + CertsColumns.MASTER_KEY_ID + ");");
- case 15:
+ case 14:
db.execSQL("ALTER TABLE user_packets ADD COLUMN name TEXT");
db.execSQL("ALTER TABLE user_packets ADD COLUMN email TEXT");
db.execSQL("ALTER TABLE user_packets ADD COLUMN comment TEXT");
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryFileProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryFileProvider.java
index 68963d595..bb44314d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryFileProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryFileProvider.java
@@ -99,6 +99,12 @@ public class TemporaryFileProvider extends ContentProvider {
return context.getContentResolver().insert(CONTENT_URI, contentValues);
}
+ public static int setName(Context context, Uri uri, String name) {
+ ContentValues values = new ContentValues();
+ values.put(TemporaryFileColumns.COLUMN_NAME, name);
+ return context.getContentResolver().update(uri, values, null, null);
+ }
+
public static int setMimeType(Context context, Uri uri, String mimetype) {
ContentValues values = new ContentValues();
values.put(TemporaryFileColumns.COLUMN_TYPE, mimetype);
@@ -283,8 +289,11 @@ public class TemporaryFileProvider extends ContentProvider {
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- if (values.size() != 1 || !values.containsKey(TemporaryFileColumns.COLUMN_TYPE)) {
- throw new UnsupportedOperationException("Update supported only for type field!");
+ if (values.size() != 1) {
+ throw new UnsupportedOperationException("Update supported only for one field at a time!");
+ }
+ if (!values.containsKey(TemporaryFileColumns.COLUMN_NAME) && !values.containsKey(TemporaryFileColumns.COLUMN_TYPE)) {
+ throw new UnsupportedOperationException("Update supported only for name and type field!");
}
if (selection != null || selectionArgs != null) {
throw new UnsupportedOperationException("Update supported only for plain uri!");
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index 2d70f3681..02d9ba62d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -103,20 +103,20 @@ public class OpenPgpService extends Service {
}
private static class KeyIdResult {
- final Intent mRequiredUserInteraction;
+ final Intent mResultIntent;
final HashSet<Long> mKeyIds;
- KeyIdResult(Intent requiredUserInteraction) {
- mRequiredUserInteraction = requiredUserInteraction;
+ KeyIdResult(Intent resultIntent) {
+ mResultIntent = resultIntent;
mKeyIds = null;
}
KeyIdResult(HashSet<Long> keyIds) {
- mRequiredUserInteraction = null;
+ mResultIntent = null;
mKeyIds = keyIds;
}
}
- private KeyIdResult returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) {
+ private KeyIdResult returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds, boolean isOpportunistic) {
boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0);
boolean missingUserIdsCheck = false;
boolean duplicateUserIdsCheck = false;
@@ -159,9 +159,15 @@ public class OpenPgpService extends Service {
}
}
- if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) {
- // allow the user to verify pub key selection
+ if (isOpportunistic && (noUserIdsCheck || missingUserIdsCheck)) {
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_ERROR,
+ new OpenPgpError(OpenPgpError.OPPORTUNISTIC_MISSING_KEYS, "missing keys in opportunistic mode"));
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
+ return new KeyIdResult(result);
+ }
+ if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) {
// convert ArrayList<Long> to long[]
long[] keyIdsArray = getUnboxedLongArray(keyIds);
ApiPendingIntentFactory piFactory = new ApiPendingIntentFactory(getBaseContext());
@@ -173,15 +179,14 @@ public class OpenPgpService extends Service {
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
return new KeyIdResult(result);
- } else {
- // everything was easy, we have exactly one key for every email
-
- if (keyIds.isEmpty()) {
- Log.e(Constants.TAG, "keyIdsArray.length == 0, should never happen!");
- }
+ }
- return new KeyIdResult(keyIds);
+ // everything was easy, we have exactly one key for every email
+ if (keyIds.isEmpty()) {
+ Log.e(Constants.TAG, "keyIdsArray.length == 0, should never happen!");
}
+
+ return new KeyIdResult(keyIds);
}
private Intent signImpl(Intent data, InputStream inputStream,
@@ -302,12 +307,12 @@ public class OpenPgpService extends Service {
// get key ids based on given user ids
if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) {
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
- data.removeExtra(OpenPgpApi.EXTRA_USER_IDS);
+ boolean isOpportunistic = data.getBooleanExtra(OpenPgpApi.EXTRA_OPPORTUNISTIC_ENCRYPTION, false);
// give params through to activity...
- KeyIdResult result = returnKeyIdsFromEmails(data, userIds);
+ KeyIdResult result = returnKeyIdsFromEmails(data, userIds, isOpportunistic);
- if (result.mRequiredUserInteraction != null) {
- return result.mRequiredUserInteraction;
+ if (result.mResultIntent != null) {
+ return result.mResultIntent;
}
encryptKeyIds.addAll(result.mKeyIds);
}
@@ -695,10 +700,9 @@ public class OpenPgpService extends Service {
} else {
// get key ids based on given user ids
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
- data.removeExtra(OpenPgpApi.EXTRA_USER_IDS);
- KeyIdResult keyResult = returnKeyIdsFromEmails(data, userIds);
- if (keyResult.mRequiredUserInteraction != null) {
- return keyResult.mRequiredUserInteraction;
+ KeyIdResult keyResult = returnKeyIdsFromEmails(data, userIds, false);
+ if (keyResult.mResultIntent != null) {
+ return keyResult.mResultIntent;
}
if (keyResult.mKeyIds == null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
index 47552bf13..e7ff6ce46 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java
@@ -43,6 +43,7 @@ import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
+import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -170,11 +171,7 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
mTitleAnimator.setDisplayedChild(1, animate);
mStatusAnimator.setDisplayedChild(1, animate);
mCodeFieldsAnimator.setDisplayedChild(1, animate);
- // use non-breaking spaces to enlarge the empty EditText appropriately
- String empty = "\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0" +
- "-\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0" +
- "-\u00a0\u00a0\u00a0\u00a0-\u00a0\u00a0\u00a0\u00a0";
- mCodeEditText.setText(empty);
+ mCodeEditText.setText(" - - - - - ");
pushBackStackEntry();
@@ -241,6 +238,30 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
mCodeEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
setupEditTextSuccessListener(mCodeEditText);
+ // prevent selection action mode, partially circumventing text selection bug
+ mCodeEditText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+
+ }
+ });
+
+
TextView codeDisplayText = (TextView) view.findViewById(R.id.backup_code_display);
setupAutomaticLinebreak(codeDisplayText);
@@ -354,8 +375,7 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
String currentBackupCode = backupCode.getText().toString();
boolean inInputState = mCurrentState == BackupCodeState.STATE_INPUT
|| mCurrentState == BackupCodeState.STATE_INPUT_ERROR;
- boolean partIsComplete = (currentBackupCode.indexOf(' ') == -1)
- && (currentBackupCode.indexOf('\u00a0') == -1);
+ boolean partIsComplete = (currentBackupCode.indexOf(' ') == -1);
if (!inInputState || !partIsComplete) {
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index be08f6a53..22202a35f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -247,10 +247,10 @@ public class EncryptFilesFragment
try {
mFilesAdapter.add(inputUri);
} catch (IOException e) {
+ String fileName = FileHelper.getFilename(getActivity(), inputUri);
Notify.create(getActivity(),
- getActivity().getString(R.string.error_file_added_already, FileHelper.getFilename(getActivity(), inputUri)),
+ getActivity().getString(R.string.error_file_added_already, fileName),
Notify.Style.ERROR).show(this);
- return;
}
// remove from pending input uris
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index b399af950..4d4219f56 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -330,9 +330,16 @@ public class ImportKeysListFragment extends ListFragment implements
}
public void loadNew(LoaderState loaderState) {
-
mLoaderState = loaderState;
+ if (mLoaderState instanceof BytesLoaderState) {
+ BytesLoaderState ls = (BytesLoaderState) mLoaderState;
+
+ if ( ls.mDataUri != null && ! checkAndRequestReadPermission(ls.mDataUri)) {
+ return;
+ }
+ }
+
restartLoaders();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index fd4f27176..e7f91a07e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -192,6 +192,8 @@ public class PassphraseDialogActivity extends FragmentActivity {
mBackupCodeEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mBackupCodeEditText.setOnEditorActionListener(this);
+ openKeyboard(mBackupCodeEditText);
+
AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null);
@@ -281,28 +283,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseText.setText(message);
mPassphraseEditText.setHint(hint);
- // Hack to open keyboard.
- // This is the only method that I found to work across all Android versions
- // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
- // Notes: * onCreateView can't be used because we want to add buttons to the dialog
- // * opening in onActivityCreated does not work on Android 4.4
- mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPassphraseEditText.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || mPassphraseEditText == null) {
- return;
- }
- InputMethodManager imm = (InputMethodManager) getActivity()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
- }
- });
- }
- });
- mPassphraseEditText.requestFocus();
+ openKeyboard(mPassphraseEditText);
mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mPassphraseEditText.setOnEditorActionListener(this);
@@ -325,6 +306,34 @@ public class PassphraseDialogActivity extends FragmentActivity {
}
/**
+ * Hack to open keyboard.
+ *
+ * This is the only method that I found to work across all Android versions
+ * http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
+ * Notes: * onCreateView can't be used because we want to add buttons to the dialog
+ * * opening in onActivityCreated does not work on Android 4.4
+ */
+ private void openKeyboard(final TextView textView) {
+ textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ textView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (getActivity() == null || textView == null) {
+ return;
+ }
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(textView, InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
+ }
+ });
+ textView.requestFocus();
+ }
+
+ /**
* Automatic line break with max 6 lines for smaller displays
* <p/>
* NOTE: I was not able to get this behaviour using XML!
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
index 78d82d436..d2ecce242 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SecurityTokenOperationActivity.java
@@ -249,13 +249,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenNfcActivity
}
// change PINs afterwards
- nfcModifyPIN(0x81, newPin);
- nfcModifyPIN(0x83, newAdminPin);
+ nfcModifyPin(0x81, newPin);
+ nfcModifyPin(0x83, newAdminPin);
break;
}
case NFC_RESET_CARD: {
- nfcResetCard();
+ nfcReset();
break;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
index 5a8ab36bc..488558aa3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java
@@ -40,6 +40,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.dialog.AddEditKeyserverDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperAdapter;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperViewHolder;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperDragCallback;
@@ -312,19 +313,19 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
public void showAsSelectedKeyserver() {
isSelectedKeyserver = true;
selectedServerLabel.setVisibility(View.VISIBLE);
- outerLayout.setBackgroundColor(getResources().getColor(R.color.android_green_dark));
+ outerLayout.setBackgroundColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorPrimaryDark));
}
public void showAsUnselectedKeyserver() {
isSelectedKeyserver = false;
selectedServerLabel.setVisibility(View.GONE);
- outerLayout.setBackgroundColor(Color.WHITE);
+ outerLayout.setBackgroundColor(0);
}
@Override
public void onItemSelected() {
selectedServerLabel.setVisibility(View.GONE);
- itemView.setBackgroundColor(Color.LTGRAY);
+ itemView.setBackgroundColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorBrightToolbar));
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
index 107c63e0b..beaf68372 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
@@ -45,8 +45,8 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- initTheme();
super.onCreate(savedInstanceState);
+ initTheme();
initLayout();
initToolbar();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
index c3352363a..77044cd2b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java
@@ -26,14 +26,11 @@ import java.nio.ByteBuffer;
import java.security.interfaces.RSAPrivateCrtKey;
import android.app.Activity;
-import android.app.PendingIntent;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.TagLostException;
-import android.nfc.tech.IsoDep;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -319,7 +316,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
// 6A82 app not installed on security token!
case 0x6A82: {
- if (isFidesmoDevice()) {
+ if (isFidesmoToken()) {
// Check if the Fidesmo app is installed
if (isAndroidAppInstalled(FIDESMO_APP_PACKAGE)) {
promptFidesmoPgpInstall();
@@ -530,18 +527,18 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
public String nfcGetUserId() throws IOException {
String info = "00CA006500";
- return nfcGetHolderName(nfcCommunicate(info));
+ return getHolderName(nfcCommunicate(info));
}
/**
- * Calls to calculate the signature and returns the MPI value
+ * Call COMPUTE DIGITAL SIGNATURE command and returns the MPI value
*
* @param hash the hash for signing
* @return a big integer representing the MPI for the given hash
*/
public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException {
if (!mPw1ValidatedForSignature) {
- nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing)
+ nfcVerifyPin(0x81); // (Verify PW1 with mode 81 for signing)
}
// dsi, including Lc
@@ -634,14 +631,14 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
- * Calls to calculate the signature and returns the MPI value
+ * Call DECIPHER command
*
* @param encryptedSessionKey the encoded session key
* @return the decoded session key
*/
public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException {
if (!mPw1ValidatedForDecrypt) {
- nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption)
+ nfcVerifyPin(0x82); // (Verify PW1 with mode 82 for decryption)
}
String firstApdu = "102a8086fe";
@@ -657,10 +654,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
two[i] = encryptedSessionKey[i + one.length + 1];
}
- String first = nfcCommunicate(firstApdu + getHex(one));
+ nfcCommunicate(firstApdu + getHex(one));
String second = nfcCommunicate(secondApdu + getHex(two) + le);
- String decryptedSessionKey = nfcGetDataField(second);
+ String decryptedSessionKey = getDataField(second);
return Hex.decode(decryptedSessionKey);
}
@@ -670,7 +667,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* @param mode For PW1, this is 0x81 for signing, 0x82 for everything else.
* For PW3 (Admin PIN), mode is 0x83.
*/
- public void nfcVerifyPIN(int mode) throws IOException {
+ public void nfcVerifyPin(int mode) throws IOException {
if (mPin != null || mode == 0x83) {
byte[] pin;
@@ -683,7 +680,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
// SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
// See specification, page 51
String accepted = "9000";
- String response = tryPin(mode, pin); // login
+ String response = nfcTryPin(mode, pin); // login
if (!response.equals(accepted)) {
throw new CardException("Bad PIN!", parseCardStatus(response));
}
@@ -698,13 +695,18 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- public void nfcResetCard() throws IOException {
+ /**
+ * Resets security token, which deletes all keys and data objects.
+ * This works by entering a wrong PIN and then Admin PIN 4 times respectively.
+ * Afterwards, the token is reactivated.
+ */
+ public void nfcReset() throws IOException {
String accepted = "9000";
// try wrong PIN 4 times until counter goes to C0
byte[] pin = "XXXXXX".getBytes();
for (int i = 0; i <= 4; i++) {
- String response = tryPin(0x81, pin);
+ String response = nfcTryPin(0x81, pin);
if (response.equals(accepted)) { // Should NOT accept!
throw new CardException("Should never happen, XXXXXX has been accepted!", parseCardStatus(response));
}
@@ -713,7 +715,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
// try wrong Admin PIN 4 times until counter goes to C0
byte[] adminPin = "XXXXXXXX".getBytes();
for (int i = 0; i <= 4; i++) {
- String response = tryPin(0x83, adminPin);
+ String response = nfcTryPin(0x83, adminPin);
if (response.equals(accepted)) { // Should NOT accept!
throw new CardException("Should never happen, XXXXXXXX has been accepted", parseCardStatus(response));
}
@@ -730,7 +732,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
- private String tryPin(int mode, byte[] pin) throws IOException {
+ private String nfcTryPin(int mode, byte[] pin) throws IOException {
// Command APDU for VERIFY command (page 32)
String login =
"00" // CLA
@@ -749,7 +751,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83.
* @param newPin The new PW1 or PW3.
*/
- public void nfcModifyPIN(int pw, byte[] newPin) throws IOException {
+ public void nfcModifyPin(int pw, byte[] newPin) throws IOException {
final int MAX_PW1_LENGTH_INDEX = 1;
final int MAX_PW3_LENGTH_INDEX = 3;
@@ -802,10 +804,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
if (dataObject == 0x0101 || dataObject == 0x0103) {
if (!mPw1ValidatedForDecrypt) {
- nfcVerifyPIN(0x82); // (Verify PW1 for non-signing operations)
+ nfcVerifyPin(0x82); // (Verify PW1 for non-signing operations)
}
} else if (!mPw3Validated) {
- nfcVerifyPIN(0x83); // (Verify PW3)
+ nfcVerifyPin(0x83); // (Verify PW3)
}
String putDataApdu = "00" // CLA
@@ -854,7 +856,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
if (!mPw3Validated) {
- nfcVerifyPIN(0x83); // (Verify PW3 with mode 83)
+ nfcVerifyPin(0x83); // (Verify PW3 with mode 83)
}
byte[] header= Hex.decode(
@@ -934,6 +936,53 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
+ * Generates a key on the card in the given slot. If the slot is 0xB6 (the signature key),
+ * this command also has the effect of resetting the digital signature counter.
+ * NOTE: This does not set the key fingerprint data object! After calling this command, you
+ * must construct a public key packet using the returned public key data objects, compute the
+ * key fingerprint, and store it on the card using: nfcPutData(0xC8, key.getFingerprint())
+ *
+ * @param slot The slot on the card where the key should be generated:
+ * 0xB6: Signature Key
+ * 0xB8: Decipherment Key
+ * 0xA4: Authentication Key
+ * @return the public key data objects, in TLV format. For RSA this will be the public modulus
+ * (0x81) and exponent (0x82). These may come out of order; proper TLV parsing is required.
+ */
+ public byte[] nfcGenerateKey(int slot) throws IOException {
+ if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) {
+ throw new IOException("Invalid key slot");
+ }
+
+ if (!mPw3Validated) {
+ nfcVerifyPin(0x83); // (Verify PW3 with mode 83)
+ }
+
+ String generateKeyApdu = "0047800002" + String.format("%02x", slot) + "0000";
+ String getResponseApdu = "00C00000";
+
+ String first = nfcCommunicate(generateKeyApdu);
+ String second = nfcCommunicate(getResponseApdu);
+
+ if (!second.endsWith("9000")) {
+ throw new IOException("On-card key generation failed");
+ }
+
+ String publicKeyData = getDataField(first) + getDataField(second);
+
+ Log.d(Constants.TAG, "Public Key Data Objects: " + publicKeyData);
+
+ return Hex.decode(publicKeyData);
+ }
+
+ /**
+ * Transceive data via NFC encoded as Hex
+ */
+ public String nfcCommunicate(String apdu) throws IOException {
+ return getHex(mIsoCard.transceive(Hex.decode(apdu)));
+ }
+
+ /**
* Parses out the status word from a JavaCard response string.
*
* @param response A hex string with the response from the token
@@ -951,7 +1000,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- public String nfcGetHolderName(String name) {
+ public String getHolderName(String name) {
try {
String slength;
int ilength;
@@ -971,14 +1020,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
}
- private String nfcGetDataField(String output) {
+ private String getDataField(String output) {
return output.substring(0, output.length() - 4);
}
- public String nfcCommunicate(String apdu) throws IOException {
- return getHex(mIsoCard.transceive(Hex.decode(apdu)));
- }
-
public static String getHex(byte[] raw) {
return new String(Hex.encode(raw));
}
@@ -1005,7 +1050,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
- private boolean isFidesmoDevice() {
+ private boolean isFidesmoToken() {
if (isNfcConnected()) { // Check if we can still talk to the card
try {
// By trying to select any apps that have the Fidesmo AID prefix we can
@@ -1021,11 +1066,11 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
}
/**
- * Ask user if she wants to install PGP onto her Fidesmo device
+ * Ask user if she wants to install PGP onto her Fidesmo token
*/
private void promptFidesmoPgpInstall() {
- FidesmoPgpInstallDialog mFidesmoPgpInstallDialog = new FidesmoPgpInstallDialog();
- mFidesmoPgpInstallDialog.show(getSupportFragmentManager(), "mFidesmoPgpInstallDialog");
+ FidesmoPgpInstallDialog fidesmoPgpInstallDialog = new FidesmoPgpInstallDialog();
+ fidesmoPgpInstallDialog.show(getSupportFragmentManager(), "fidesmoPgpInstallDialog");
}
/**
@@ -1033,8 +1078,8 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
* to launch the Google Play store.
*/
private void promptFidesmoAppInstall() {
- FidesmoInstallDialog mFidesmoInstallDialog = new FidesmoInstallDialog();
- mFidesmoInstallDialog.show(getSupportFragmentManager(), "mFidesmoInstallDialog");
+ FidesmoInstallDialog fidesmoInstallDialog = new FidesmoInstallDialog();
+ fidesmoInstallDialog.show(getSupportFragmentManager(), "fidesmoInstallDialog");
}
/**
@@ -1044,7 +1089,7 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
*/
private boolean isAndroidAppInstalled(String uri) {
PackageManager mPackageManager = getPackageManager();
- boolean mAppInstalled = false;
+ boolean mAppInstalled;
try {
mPackageManager.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
mAppInstalled = true;
diff --git a/OpenKeychain/src/main/res/layout-land/backup_code_fragment.xml b/OpenKeychain/src/main/res/layout-w600dp/backup_code_fragment.xml
index 0a4f97d53..6cea50a32 100644
--- a/OpenKeychain/src/main/res/layout-land/backup_code_fragment.xml
+++ b/OpenKeychain/src/main/res/layout-w600dp/backup_code_fragment.xml
@@ -84,11 +84,9 @@
android:textSize="18dp"
android:textStyle="bold"
android:typeface="monospace"
- app:deleteChar="\u00a0"
app:mask="****-****-****-****-****-****"
app:maskIconColor="@color/colorPrimary"
app:notMaskedSymbol="*"
- app:replacementChar="\u00a0"
tools:ignore="SpUsage" />
</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
diff --git a/OpenKeychain/src/main/res/layout-land/security_token_operation_activity.xml b/OpenKeychain/src/main/res/layout-w600dp/security_token_operation_activity.xml
index cf0edac8c..cf0edac8c 100644
--- a/OpenKeychain/src/main/res/layout-land/security_token_operation_activity.xml
+++ b/OpenKeychain/src/main/res/layout-w600dp/security_token_operation_activity.xml
diff --git a/OpenKeychain/src/main/res/layout/backup_code_fragment.xml b/OpenKeychain/src/main/res/layout/backup_code_fragment.xml
index 330f18d1c..619a1b3b1 100644
--- a/OpenKeychain/src/main/res/layout/backup_code_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/backup_code_fragment.xml
@@ -84,11 +84,9 @@
android:textSize="18dp"
android:textStyle="bold"
android:typeface="monospace"
- app:deleteChar="\u00a0"
app:mask="****-****-****-****-****-****"
app:maskIconColor="@color/colorPrimary"
app:notMaskedSymbol="*"
- app:replacementChar="\u00a0"
tools:ignore="SpUsage" />
</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
diff --git a/OpenKeychain/src/main/res/layout/passphrase_dialog_backup_code.xml b/OpenKeychain/src/main/res/layout/passphrase_dialog_backup_code.xml
index b17c9dba7..f18b5193e 100644
--- a/OpenKeychain/src/main/res/layout/passphrase_dialog_backup_code.xml
+++ b/OpenKeychain/src/main/res/layout/passphrase_dialog_backup_code.xml
@@ -30,19 +30,17 @@
<com.github.pinball83.maskededittext.MaskedEditText
android:id="@+id/backup_code"
+ style="@style/BackupCodeTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
- android:textSize="18dp"
android:textStyle="bold"
android:typeface="monospace"
- app:deleteChar="\u00a0"
app:mask="****-****-****-****-****-****"
app:maskIconColor="@color/colorPrimary"
app:notMaskedSymbol="*"
- app:replacementChar="\u00a0"
tools:ignore="SpUsage" />
</LinearLayout>
diff --git a/OpenKeychain/src/main/res/values-sw360dp/styles.xml b/OpenKeychain/src/main/res/values-sw360dp/styles.xml
new file mode 100644
index 000000000..70587b7dc
--- /dev/null
+++ b/OpenKeychain/src/main/res/values-sw360dp/styles.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+ <!-- constrain size of backup code input for smaller devices -->
+ <style name="BackupCodeTextStyle">
+ <item name="android:textSize" tools:ignore="SpUsage">16dp</item>
+ </style>
+
+</resources>
diff --git a/OpenKeychain/src/main/res/values-sw400dp/styles.xml b/OpenKeychain/src/main/res/values-sw400dp/styles.xml
new file mode 100644
index 000000000..b18c708d9
--- /dev/null
+++ b/OpenKeychain/src/main/res/values-sw400dp/styles.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+ <!-- constrain size of backup code input for smaller devices -->
+ <style name="BackupCodeTextStyle">
+ <item name="android:textSize" tools:ignore="SpUsage">18dp</item>
+ </style>
+
+</resources>
diff --git a/OpenKeychain/src/main/res/values/styles.xml b/OpenKeychain/src/main/res/values/styles.xml
index 55c4e2220..5d7486d19 100644
--- a/OpenKeychain/src/main/res/values/styles.xml
+++ b/OpenKeychain/src/main/res/values/styles.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools">
<style name="CardViewHeader">
<item name="android:drawableBottom">?attr/cardViewHeaderDrawable</item>
@@ -38,4 +38,9 @@
<item name="android:textColor">?attr/colorAccent</item>
</style>
+ <!-- constrain size of backup code input for smaller devices -->
+ <style name="BackupCodeTextStyle">
+ <item name="android:textSize" tools:ignore="SpUsage">14dp</item>
+ </style>
+
</resources>
diff --git a/build.gradle b/build.gradle
index 0f2e968b2..d70fb6a13 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,7 +11,7 @@ buildscript {
classpath files('gradle-witness.jar')
// bintray dependency to satisfy dependency of openpgp-api lib
classpath 'com.novoda:bintray-release:0.2.7'
-
+
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0'
// classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.0.2'
diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib
-Subproject 8ca0f578bb843db7744dbd5724b32f6664b5c3d
+Subproject 710a0d8fe8d89cb9a1f247007000a7f49a29c52