diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index 7c604611b..94d17b8d6 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -148,11 +148,6 @@
android:name=".ui.EditKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_edit_key" />
-
ANALYTICS_PREFS = Arrays.asList(USE_NORMAL_PROXY, USE_TOR_PROXY,
SYNC_CONTACTS, SYNC_KEYSERVER, ENABLE_WIFI_SYNC_ONLY, EXPERIMENTAL_ENABLE_KEYBASE,
- EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, EXPERIMENTAL_USB_ALLOW_UNTESTED,
+ EXPERIMENTAL_USB_ALLOW_UNTESTED,
PASSPHRASE_CACHE_SUBS, SEARCH_KEYSERVER, SEARCH_KEYBASE, SEARCH_WEB_KEY_DIRECTORY,
TEXT_USE_COMPRESSION, TEXT_SELF_ENCRYPT, FILE_USE_COMPRESSION, FILE_SELF_ENCRYPT, USE_ARMOR,
USE_NUMKEYPAD_FOR_SECURITY_TOKEN_PIN, ENCRYPT_FILENAMES);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java
deleted file mode 100644
index cceb66438..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked;
-
-import java.net.URI;
-
-import android.content.Context;
-import android.support.annotation.DrawableRes;
-
-public class LinkedAttribute extends UriAttribute {
-
- public final LinkedResource mResource;
-
- protected LinkedAttribute(URI uri, LinkedResource resource) {
- super(uri);
- if (resource == null) {
- throw new AssertionError("resource must not be null in a LinkedIdentity!");
- }
- mResource = resource;
- }
-
- public @DrawableRes int getDisplayIcon() {
- return mResource.getDisplayIcon();
- }
-
- public String getDisplayTitle(Context context) {
- return mResource.getDisplayTitle(context);
- }
-
- public String getDisplayComment(Context context) {
- return mResource.getDisplayComment(context);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java
deleted file mode 100644
index ba2d88e11..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked;
-
-import java.net.URI;
-
-import android.content.Context;
-import android.content.Intent;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.StringRes;
-
-public abstract class LinkedResource {
-
- public abstract URI toUri();
-
- public abstract @DrawableRes int getDisplayIcon();
- public abstract @StringRes int getVerifiedText(boolean isSecret);
- public abstract String getDisplayTitle(Context context);
- public abstract String getDisplayComment(Context context);
- public boolean isViewable() {
- return false;
- }
- public Intent getViewIntent() {
- return null;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
deleted file mode 100644
index b7ce26072..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked;
-
-import android.content.Context;
-
-import okhttp3.CertificatePinner;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-import org.json.JSONException;
-import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
-import org.sufficientlysecure.keychain.linked.resources.GithubResource;
-import org.sufficientlysecure.keychain.linked.resources.TwitterResource;
-import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.network.OkHttpClientFactory;
-import timber.log.Timber;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-public abstract class LinkedTokenResource extends LinkedResource {
-
- protected final URI mSubUri;
- protected final Set mFlags;
- protected final HashMap mParams;
-
- public static Pattern magicPattern =
- Pattern.compile("\\[Verifying my (?:Open|)?PGP key(?::|) openpgp4fpr:([a-zA-Z0-9]+)]");
-
- protected LinkedTokenResource(Set flags, HashMap params, URI uri) {
- mFlags = flags;
- mParams = params;
- mSubUri = uri;
- }
-
- @SuppressWarnings("unused")
- public URI getSubUri () {
- return mSubUri;
- }
-
- public Set getFlags () {
- return new HashSet<>(mFlags);
- }
-
- public HashMap getParams () {
- return new HashMap<>(mParams);
- }
-
- public static String generate (byte[] fingerprint) {
- return String.format("[Verifying my OpenPGP key: openpgp4fpr:%s]",
- KeyFormattingUtils.convertFingerprintToHex(fingerprint));
- }
-
- protected static LinkedTokenResource fromUri (URI uri) {
-
- if (!"openpgpid+token".equals(uri.getScheme())
- && !"openpgpid+cookie".equals(uri.getScheme())) {
- Timber.e("unknown uri scheme in (suspected) linked id packet");
- return null;
- }
-
- if (!uri.isOpaque()) {
- Timber.e("non-opaque uri in (suspected) linked id packet");
- return null;
- }
-
- String specific = uri.getSchemeSpecificPart();
- if (!specific.contains("@")) {
- Timber.e("unknown uri scheme in linked id packet");
- return null;
- }
-
- String[] pieces = specific.split("@", 2);
- URI subUri = URI.create(pieces[1]);
-
- Set flags = new HashSet<>();
- HashMap params = new HashMap<>();
- if (!pieces[0].isEmpty()) {
- String[] rawParams = pieces[0].split(";");
- for (String param : rawParams) {
- String[] p = param.split("=", 2);
- if (p.length == 1) {
- flags.add(param);
- } else {
- params.put(p[0], p[1]);
- }
- }
- }
-
- return findResourceType(flags, params, subUri);
-
- }
-
- protected static LinkedTokenResource findResourceType (Set flags,
- HashMap params, URI subUri) {
-
- LinkedTokenResource res;
-
- res = GenericHttpsResource.create(flags, params, subUri);
- if (res != null) {
- return res;
- }
- // res = DnsResource.create(flags, params, subUri);
- // if (res != null) {
- // return res;
- // }
- res = TwitterResource.create(flags, params, subUri);
- if (res != null) {
- return res;
- }
- res = GithubResource.create(flags, params, subUri);
- if (res != null) {
- return res;
- }
-
- return null;
-
- }
-
- public URI toUri () {
-
- StringBuilder b = new StringBuilder();
- b.append("openpgpid+token:");
-
- // add flags
- if (mFlags != null) {
- boolean first = true;
- for (String flag : mFlags) {
- if (!first) {
- b.append(";");
- }
- first = false;
- b.append(flag);
- }
- }
-
- // add parameters
- if (mParams != null) {
- boolean first = true;
- for (Entry stringStringEntry : mParams.entrySet()) {
- if (!first) {
- b.append(";");
- }
- first = false;
- b.append(stringStringEntry.getKey()).append("=").append(stringStringEntry.getValue());
- }
- }
-
- b.append("@");
- b.append(mSubUri);
-
- return URI.create(b.toString());
-
- }
-
- public LinkedVerifyResult verify(Context context, byte[] fingerprint) {
-
- OperationLog log = new OperationLog();
- log.add(LogType.MSG_LV, 0);
-
- // Try to fetch resource. Logs for itself
- String res = null;
- try {
- res = fetchResource(context, log, 1);
- } catch (HttpStatusException e) {
- // log verbose output to logcat
- Timber.e("http error (" + e.getStatus() + "): " + e.getReason());
- log.add(LogType.MSG_LV_FETCH_ERROR, 2, Integer.toString(e.getStatus()));
- } catch (MalformedURLException e) {
- log.add(LogType.MSG_LV_FETCH_ERROR_URL, 2);
- } catch (IOException e) {
- Timber.e(e, "io error");
- log.add(LogType.MSG_LV_FETCH_ERROR_IO, 2);
- } catch (JSONException e) {
- Timber.e(e, "json error");
- log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 2);
- }
-
- if (res == null) {
- // if this is null, an error was recorded in fetchResource above
- return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
- }
-
- Timber.d("Resource data: '" + res + "'");
-
- return verifyString(log, 1, res, fingerprint);
-
- }
-
- protected abstract String fetchResource (Context context, OperationLog log, int indent)
- throws HttpStatusException, IOException, JSONException;
-
- protected Matcher matchResource (OperationLog log, int indent, String res) {
- return magicPattern.matcher(res);
- }
-
- protected LinkedVerifyResult verifyString (OperationLog log, int indent,
- String res,
- byte[] fingerprint) {
-
- log.add(LogType.MSG_LV_MATCH, indent);
- Matcher match = matchResource(log, indent+1, res);
- if (!match.find()) {
- log.add(LogType.MSG_LV_MATCH_ERROR, 2);
- return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
- }
-
- String candidateFp = match.group(1).toLowerCase();
- String fp = KeyFormattingUtils.convertFingerprintToHex(fingerprint);
- if (!fp.equals(candidateFp)) {
- log.add(LogType.MSG_LV_FP_ERROR, indent);
- return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
- }
- log.add(LogType.MSG_LV_FP_OK, indent);
-
- return new LinkedVerifyResult(LinkedVerifyResult.RESULT_OK, log);
-
- }
-
-
- 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();
- }
-
-
- public static String getResponseBody(Request request, String... pins)
- throws IOException, HttpStatusException {
-
- Timber.d("");
- OkHttpClient client;
- if (pins != null) {
- client = OkHttpClientFactory.getSimpleClientPinned(getCertificatePinner(request.url().url().getHost(), pins));
- } else {
- client = OkHttpClientFactory.getSimpleClient();
- }
-
- Response response = client.newCall(request).execute();
-
-
- int statusCode = response.code();
- String reason = response.message();
-
- if (statusCode != 200) {
- throw new HttpStatusException(statusCode, reason);
- }
-
- return response.body().string();
- }
-
- public static class HttpStatusException extends Throwable {
-
- private final int mStatusCode;
- private final String mReason;
-
- HttpStatusException(int statusCode, String reason) {
- super("http status " + statusCode + ": " + reason);
- mStatusCode = statusCode;
- mReason = reason;
- }
-
- public int getStatus() {
- return mStatusCode;
- }
-
- public String getReason() {
- return mReason;
- }
-
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java
deleted file mode 100644
index 6187d8ff7..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked;
-
-import org.bouncycastle.util.Strings;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
-import timber.log.Timber;
-
-import java.io.IOException;
-import java.net.URI;
-
-import android.content.Context;
-import android.support.annotation.DrawableRes;
-
-/** The RawLinkedIdentity contains raw parsed data from a Linked Identity subpacket. */
-public class UriAttribute {
-
- public final URI mUri;
-
- protected UriAttribute(URI uri) {
- mUri = uri;
- }
-
- public byte[] getEncoded() {
- return Strings.toUTF8ByteArray(mUri.toASCIIString());
- }
-
- public static UriAttribute fromAttributeData(byte[] data) throws IOException {
- WrappedUserAttribute att = WrappedUserAttribute.fromData(data);
-
- byte[][] subpackets = att.getSubpackets();
- if (subpackets.length >= 1) {
- return fromSubpacketData(subpackets[0]);
- }
-
- throw new IOException("no subpacket data");
- }
-
- static UriAttribute fromSubpacketData(byte[] data) {
-
- try {
- String uriStr = Strings.fromUTF8ByteArray(data);
- URI uri = URI.create(uriStr);
-
- LinkedResource res = LinkedTokenResource.fromUri(uri);
- if (res == null) {
- return new UriAttribute(uri);
- }
-
- return new LinkedAttribute(uri, res);
-
- } catch (IllegalArgumentException e) {
- Timber.e("error parsing uri in (suspected) linked id packet");
- return null;
- }
- }
-
- public static UriAttribute fromResource (LinkedTokenResource res) {
- return new UriAttribute(res.toUri());
- }
-
-
- public WrappedUserAttribute toUserAttribute () {
- return WrappedUserAttribute.fromSubpacket(WrappedUserAttribute.UAT_URI_ATTRIBUTE, getEncoded());
- }
-
- public @DrawableRes int getDisplayIcon() {
- return R.drawable.ic_warning_grey_24dp;
- }
-
- public String getDisplayTitle(Context context) {
- return "Unknown Identity";
- }
-
- public String getDisplayComment(Context context) {
- return null;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java
deleted file mode 100644
index e3f7a9c48..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked.resources;
-
-import android.content.Context;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.StringRes;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-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.CLASS;
-import de.measite.minidns.Record.TYPE;
-import de.measite.minidns.record.TXT;
-
-public class DnsResource extends LinkedTokenResource {
-
- final static Pattern magicPattern =
- Pattern.compile("openpgpid\\+token=([a-zA-Z0-9]+)(?:#|;)([a-zA-Z0-9]+)");
-
- String mFqdn;
- CLASS mClass;
- TYPE mType;
-
- DnsResource(Set flags, HashMap params, URI uri,
- String fqdn, CLASS clazz, TYPE type) {
- super(flags, params, uri);
-
- mFqdn = fqdn;
- mClass = clazz;
- mType = type;
- }
-
- public static String generateText(byte[] fingerprint) {
-
- return String.format("openpgp4fpr=%s",
- KeyFormattingUtils.convertFingerprintToHex(fingerprint));
-
- }
-
- public static DnsResource createNew (String domain) {
- HashSet flags = new HashSet<>();
- HashMap params = new HashMap<>();
- URI uri = URI.create("dns:" + domain + "?TYPE=TXT");
- return create(flags, params, uri);
- }
-
- public static DnsResource create(Set flags, HashMap params, URI uri) {
- if ( ! ("dns".equals(uri.getScheme())
- && (flags == null || flags.isEmpty())
- && (params == null || params.isEmpty()))) {
- return null;
- }
-
- //
- String spec = uri.getSchemeSpecificPart();
- // If there are // at the beginning, this includes an authority - we don't support those!
- if (spec.startsWith("//")) {
- return null;
- }
-
- String[] pieces = spec.split("\\?", 2);
- // In either case, part before a ? is the fqdn
- String fqdn = pieces[0];
- // There may be a query part
- /*
- if (pieces.length > 1) {
- // parse CLASS and TYPE query parameters
- }
- */
-
- CLASS clazz = CLASS.IN;
- TYPE type = TYPE.TXT;
-
- return new DnsResource(flags, params, uri, fqdn, clazz, type);
- }
-
- @SuppressWarnings("unused")
- public String getFqdn() {
- return mFqdn;
- }
-
- @Override
- protected String fetchResource (Context context, OperationLog log, int indent) {
-
- Client c = new Client();
- DNSMessage msg = c.query(new Question(mFqdn, mType, mClass));
- Record aw = msg.getAnswers()[0];
- TXT txt = (TXT) aw.getPayload();
- return txt.getText().toLowerCase();
-
- }
-
- @Override
- protected Matcher matchResource(OperationLog log, int indent, String res) {
- return magicPattern.matcher(res);
- }
-
- @Override
- public @StringRes
- int getVerifiedText(boolean isSecret) {
- return isSecret ? R.string.linked_verified_secret_dns : R.string.linked_verified_dns;
- }
-
- @Override
- public @DrawableRes int getDisplayIcon() {
- return R.drawable.linked_dns;
- }
-
- @Override
- public String getDisplayTitle(Context context) {
- return context.getString(R.string.linked_title_dns);
- }
-
- @Override
- public String getDisplayComment(Context context) {
- return mFqdn;
- }
-}
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
deleted file mode 100644
index e9b531ddb..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked.resources;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.StringRes;
-
-import okhttp3.Request;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
-public class GenericHttpsResource extends LinkedTokenResource {
-
- GenericHttpsResource(Set flags, HashMap params, URI uri) {
- super(flags, params, uri);
- }
-
- public static String generateText (Context context, byte[] fingerprint) {
- String token = LinkedTokenResource.generate(fingerprint);
-
- return String.format(context.getResources().getString(R.string.linked_id_generic_text),
- token, "0x" + KeyFormattingUtils.convertFingerprintToHex(fingerprint).substring(24));
- }
-
- @Override
- protected String fetchResource (Context context, OperationLog log, int indent)
- throws HttpStatusException, IOException {
-
- log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
- Request request = new Request.Builder()
- .url(mSubUri.toURL())
- .addHeader("User-Agent", "OpenKeychain")
- .build();
- return getResponseBody(request);
-
- }
-
- public static GenericHttpsResource createNew (URI uri) {
- HashSet flags = new HashSet<>();
- flags.add("generic");
- HashMap params = new HashMap<>();
- return create(flags, params, uri);
- }
-
- public static GenericHttpsResource create(Set flags, HashMap params, URI uri) {
- if ( ! ("https".equals(uri.getScheme())
- && flags != null && flags.size() == 1 && flags.contains("generic")
- && (params == null || params.isEmpty()))) {
- return null;
- }
- return new GenericHttpsResource(flags, params, uri);
- }
-
- @Override
- public @DrawableRes
- int getDisplayIcon() {
- return R.drawable.linked_https;
- }
-
- @Override
- public @StringRes
- int getVerifiedText(boolean isSecret) {
- return isSecret ? R.string.linked_verified_secret_https : R.string.linked_verified_https;
- }
-
- @Override
- public String getDisplayTitle(Context context) {
- return context.getString(R.string.linked_title_https);
- }
-
- @Override
- public String getDisplayComment(Context context) {
- return mSubUri.toString();
- }
-
- @Override
- public boolean isViewable() {
- return true;
- }
-
- @Override
- public Intent getViewIntent() {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(mSubUri.toString()));
- return intent;
- }
-}
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
deleted file mode 100644
index 5b32c9c4e..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked.resources;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.StringRes;
-
-import okhttp3.Request;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import timber.log.Timber;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-public class GithubResource extends LinkedTokenResource {
-
- final String mHandle;
- final String mGistId;
-
- GithubResource(Set flags, HashMap params, URI uri,
- String handle, String gistId) {
- super(flags, params, uri);
-
- mHandle = handle;
- mGistId = gistId;
- }
-
- public static String generate(Context context, byte[] fingerprint) {
- String token = LinkedTokenResource.generate(fingerprint);
-
- return String.format(context.getResources().getString(R.string.linked_id_github_text), token);
- }
-
-
- @Override
- protected String fetchResource (Context context, OperationLog log, int indent)
- throws HttpStatusException, IOException, JSONException {
-
- log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
- indent += 1;
-
- 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);
-
- JSONObject owner = obj.getJSONObject("owner");
- if (!mHandle.equals(owner.getString("login"))) {
- log.add(LogType.MSG_LV_ERROR_GITHUB_HANDLE, indent);
- return null;
- }
-
- JSONObject files = obj.getJSONObject("files");
- Iterator it = files.keys();
- if (it.hasNext()) {
- // TODO can there be multiple candidates?
- JSONObject file = files.getJSONObject(it.next());
- return file.getString("content");
- }
-
- log.add(LogType.MSG_LV_ERROR_GITHUB_NOT_FOUND, indent);
- return null;
-
- }
-
-
- @SuppressWarnings({ "deprecation", "unused" })
- public static GithubResource searchInGithubStream(
- Context context, String screenName, String needle, OperationLog log) {
-
- // narrow the needle down to important part
- Matcher matcher = magicPattern.matcher(needle);
- if (!matcher.find()) {
- throw new AssertionError("Needle must contain token pattern! This is a programming error, please report.");
- }
- needle = matcher.group();
-
- try {
-
- JSONArray array; {
- 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);
- }
-
- for (int i = 0, j = Math.min(array.length(), 5); i < j; i++) {
- JSONObject obj = array.getJSONObject(i);
-
- JSONObject files = obj.getJSONObject("files");
- Iterator it = files.keys();
- if (it.hasNext()) {
-
- JSONObject file = files.getJSONObject(it.next());
- String type = file.getString("type");
- if (!"text/plain".equals(type)) {
- continue;
- }
- String id = obj.getString("id");
-
- 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 gistIt = gistFiles.keys();
- if (!gistIt.hasNext()) {
- continue;
- }
- // TODO can there be multiple candidates?
- JSONObject gistFile = gistFiles.getJSONObject(gistIt.next());
- String content = gistFile.getString("content");
- if (!content.contains(needle)) {
- continue;
- }
-
- URI uri = URI.create("https://gist.github.com/" + screenName + "/" + id);
- return create(uri);
- }
- }
-
- // update the results with the body of the response
- log.add(LogType.MSG_LV_FETCH_ERROR_NOTHING, 2);
- return null;
-
- } catch (HttpStatusException e) {
- // log verbose output to logcat
- Timber.e("http error (" + e.getStatus() + "): " + e.getReason());
- log.add(LogType.MSG_LV_FETCH_ERROR, 2, Integer.toString(e.getStatus()));
- } catch (MalformedURLException e) {
- log.add(LogType.MSG_LV_FETCH_ERROR_URL, 2);
- } catch (IOException e) {
- Timber.e(e, "io error");
- log.add(LogType.MSG_LV_FETCH_ERROR_IO, 2);
- } catch (JSONException e) {
- Timber.e(e, "json error");
- log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 2);
- }
-
- return null;
- }
-
- public static GithubResource create(URI uri) {
- return create(new HashSet(), new HashMap(), uri);
- }
-
- public static GithubResource create(Set flags, HashMap params, URI uri) {
-
- // no params or flags
- if (!flags.isEmpty() || !params.isEmpty()) {
- return null;
- }
-
- Pattern p = Pattern.compile("https://gist\\.github\\.com/([a-zA-Z0-9_-]+)/([0-9a-f]+)");
- Matcher match = p.matcher(uri.toString());
- if (!match.matches()) {
- return null;
- }
- String handle = match.group(1);
- String gistId = match.group(2);
-
- return new GithubResource(flags, params, uri, handle, gistId);
-
- }
-
-
- @Override
- public @DrawableRes
- int getDisplayIcon() {
- return R.drawable.linked_github;
- }
-
- @Override
- public @StringRes
- int getVerifiedText(boolean isSecret) {
- return isSecret ? R.string.linked_verified_secret_github : R.string.linked_verified_github;
- }
-
- @Override
- public String getDisplayTitle(Context context) {
- return context.getString(R.string.linked_title_github);
- }
-
- @Override
- public String getDisplayComment(Context context) {
- return mHandle;
- }
-
- @Override
- public boolean isViewable() {
- return true;
- }
-
- @Override
- public Intent getViewIntent() {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(mSubUri.toString()));
- return intent;
- }
-}
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
deleted file mode 100644
index 48e6b4163..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.linked.resources;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.StringRes;
-import android.util.Log;
-
-import com.textuality.keybase.lib.JWalk;
-
-import okhttp3.MediaType;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import timber.log.Timber;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class TwitterResource extends LinkedTokenResource {
-
- public static final String[] CERT_PINS = null; /*(new String[] {
- // Symantec Class 3 Secure Server CA - G4
- "513fb9743870b73440418d30930699ff"
- };*/
-
- final String mHandle;
- final String mTweetId;
-
- TwitterResource(Set flags, HashMap params,
- URI uri, String handle, String tweetId) {
- super(flags, params, uri);
-
- mHandle = handle;
- mTweetId = tweetId;
- }
-
- public static TwitterResource create(URI uri) {
- return create(new HashSet(), new HashMap(), uri);
- }
-
- public static TwitterResource create(Set flags, HashMap params, URI uri) {
-
- // no params or flags
- if (!flags.isEmpty() || !params.isEmpty()) {
- return null;
- }
-
- Pattern p = Pattern.compile("https://twitter\\.com/([a-zA-Z0-9_]+)/status/([0-9]+)");
- Matcher match = p.matcher(uri.toString());
- if (!match.matches()) {
- return null;
- }
- String handle = match.group(1);
- String tweetId = match.group(2);
-
- return new TwitterResource(flags, params, uri, handle, tweetId);
-
- }
-
- @SuppressWarnings("deprecation")
- @Override
- protected String fetchResource(Context context, OperationLog log, int indent)
- throws IOException, HttpStatusException, JSONException {
-
- String authToken;
- try {
- authToken = getAuthToken(context);
- } catch (IOException | HttpStatusException | JSONException e) {
- log.add(LogType.MSG_LV_ERROR_TWITTER_AUTH, indent);
- return null;
- }
-
- // construct a normal HTTPS request and include an Authorization
- // header with the value of Bearer <>
- 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(request, CERT_PINS);
- JSONObject obj = new JSONObject(response);
- JSONObject user = obj.getJSONObject("user");
- if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) {
- log.add(LogType.MSG_LV_ERROR_TWITTER_HANDLE, indent);
- return null;
- }
-
- // update the results with the body of the response
- return obj.getString("text");
- } catch (JSONException e) {
- log.add(LogType.MSG_LV_ERROR_TWITTER_RESPONSE, indent);
- return null;
- }
-
- }
-
- @Override
- public @DrawableRes int getDisplayIcon() {
- return R.drawable.linked_twitter;
- }
-
- @Override
- public @StringRes
- int getVerifiedText(boolean isSecret) {
- return isSecret ? R.string.linked_verified_secret_twitter : R.string.linked_verified_twitter;
- }
-
- @Override
- public String getDisplayTitle(Context context) {
- return context.getString(R.string.linked_title_twitter);
- }
-
- @Override
- public String getDisplayComment(Context context) {
- return "@" + mHandle;
- }
-
- @Override
- public boolean isViewable() {
- return true;
- }
-
- @Override
- public Intent getViewIntent() {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(mSubUri.toString()));
- return intent;
- }
-
- @SuppressWarnings("deprecation")
- public static TwitterResource searchInTwitterStream(
- Context context, String screenName, String needle, OperationLog log) {
-
- String authToken;
- try {
- authToken = getAuthToken(context);
- } catch (IOException | HttpStatusException | JSONException e) {
- log.add(LogType.MSG_LV_ERROR_TWITTER_AUTH, 1);
- return null;
- }
-
- 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")
- .addHeader("Authorization", "Bearer " + authToken)
- .addHeader("Content-Type", "application/json")
- .addHeader("User-Agent", "OpenKeychain")
- .build();
-
- try {
- String response = getResponseBody(request, CERT_PINS);
- JSONArray array = new JSONArray(response);
-
- for (int i = 0; i < array.length(); i++) {
- JSONObject obj = array.getJSONObject(i);
- String tweet = obj.getString("text");
- if (tweet.contains(needle)) {
- String id = obj.getString("id_str");
- URI uri = URI.create("https://twitter.com/" + screenName + "/status/" + id);
- return create(uri);
- }
- }
-
- // update the results with the body of the response
- log.add(LogType.MSG_LV_FETCH_ERROR_NOTHING, 1);
- return null;
-
- } catch (HttpStatusException e) {
- // log verbose output to logcat
- Timber.e("http error (" + e.getStatus() + "): " + e.getReason());
- log.add(LogType.MSG_LV_FETCH_ERROR, 1, Integer.toString(e.getStatus()));
- } catch (MalformedURLException e) {
- log.add(LogType.MSG_LV_FETCH_ERROR_URL, 1);
- } catch (IOException e) {
- Timber.e(e, "io error");
- log.add(LogType.MSG_LV_FETCH_ERROR_IO, 1);
- } catch (JSONException e) {
- Timber.e(e, "json error");
- log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 1);
- }
-
- return null;
- }
-
- private static String cachedAuthToken;
-
- @SuppressWarnings("deprecation")
- private static String getAuthToken(Context context)
- throws IOException, HttpStatusException, JSONException {
- if (cachedAuthToken != null) {
- return cachedAuthToken;
- }
- 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
- 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
- if (!"bearer".equals(JWalk.getString(rawAuthorization, "token_type"))) {
- throw new JSONException("Expected bearer token in response!");
- }
-
- cachedAuthToken = rawAuthorization.getString("access_token");
- return cachedAuthToken;
-
- }
-
- public static String rot13(String input) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < input.length(); i++) {
- char c = input.charAt(i);
- if (c >= 'a' && c <= 'm') c += 13;
- else if (c >= 'A' && c <= 'M') c += 13;
- else if (c >= 'n' && c <= 'z') c -= 13;
- else if (c >= 'N' && c <= 'Z') c -= 13;
- sb.append(c);
- }
- return sb.toString();
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java
deleted file mode 100644
index 7dc75dfcc..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.operations.results;
-
-import android.os.Parcel;
-
-public class LinkedVerifyResult extends OperationResult {
-
- public LinkedVerifyResult(int result, OperationLog log) {
- super(result, log);
- }
-
- /** Construct from a parcel - trivial because we have no extra data. */
- public LinkedVerifyResult(Parcel source) {
- super(source);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- }
-
- public static Creator CREATOR = new Creator() {
- public LinkedVerifyResult createFromParcel(final Parcel source) {
- return new LinkedVerifyResult(source);
- }
-
- public LinkedVerifyResult[] newArray(final int size) {
- return new LinkedVerifyResult[size];
- }
- };
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java
index b8bbd43c0..44b6ab5b5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java
@@ -20,11 +20,8 @@ package org.sufficientlysecure.keychain.ui.adapter;
import java.util.List;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Typeface;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -34,41 +31,30 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.UriAttribute;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.ViewHolder;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
-import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
-import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
public class IdentityAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_USER_ID = 0;
- private static final int VIEW_TYPE_LINKED_ID = 1;
- private final Context context;
private final LayoutInflater layoutInflater;
private final IdentityClickListener identityClickListener;
private List data;
- private boolean isSecret;
public IdentityAdapter(Context context, IdentityClickListener identityClickListener) {
super();
this.layoutInflater = LayoutInflater.from(context);
- this.context = context;
this.identityClickListener = identityClickListener;
}
- public void setData(List data, boolean isSecret) {
+ public void setData(List data) {
this.data = data;
- this.isSecret = isSecret;
-
notifyDataSetChanged();
}
@@ -83,8 +69,6 @@ public class IdentityAdapter extends RecyclerView.Adapter {
} else {
((UserIdViewHolder) holder).bind((UserIdInfo) info);
}
- } else if (viewType == VIEW_TYPE_LINKED_ID) {
- ((LinkedIdViewHolder) holder).bind(context, (LinkedIdInfo) info, isSecret);
} else {
throw new IllegalStateException("unhandled identitytype!");
}
@@ -96,9 +80,6 @@ public class IdentityAdapter extends RecyclerView.Adapter {
if (viewType == VIEW_TYPE_USER_ID) {
return new UserIdViewHolder(
layoutInflater.inflate(R.layout.view_key_identity_user_id, parent, false), identityClickListener);
- } else if (viewType == VIEW_TYPE_LINKED_ID) {
- return new LinkedIdViewHolder(layoutInflater.inflate(R.layout.linked_id_item, parent, false),
- identityClickListener);
} else {
throw new IllegalStateException("unhandled identitytype!");
}
@@ -109,8 +90,6 @@ public class IdentityAdapter extends RecyclerView.Adapter {
IdentityInfo info = data.get(position);
if (info instanceof UserIdInfo || info instanceof AutocryptPeerInfo) {
return VIEW_TYPE_USER_ID;
- } else if (info instanceof LinkedIdInfo) {
- return VIEW_TYPE_LINKED_ID;
} else {
throw new IllegalStateException("unhandled identitytype!");
}
@@ -131,69 +110,6 @@ public class IdentityAdapter extends RecyclerView.Adapter {
}
}
- public static class LinkedIdViewHolder extends ViewHolder {
- public final ImageView vVerified;
- final private ImageView vIcon;
- final private TextView vTitle;
- final private TextView vComment;
-
- public LinkedIdViewHolder(View view, final IdentityClickListener identityClickListener) {
- super(view);
-
- vVerified = view.findViewById(R.id.linked_id_certified_icon);
- vIcon = view.findViewById(R.id.linked_id_type_icon);
- vTitle = view.findViewById(R.id.linked_id_title);
- vComment = view.findViewById(R.id.linked_id_comment);
-
- view.setOnClickListener(v -> {
- if (identityClickListener != null) {
- identityClickListener.onClickIdentity(getAdapterPosition());
- }
- });
- }
-
- public void bind(Context context, LinkedIdInfo info, boolean isSecret) {
- bindVerified(context, info, isSecret);
-
- UriAttribute uriAttribute = info.getLinkedAttribute();
- bind(context, uriAttribute);
- }
-
- public void bind(Context context, UriAttribute uriAttribute) {
- vTitle.setText(uriAttribute.getDisplayTitle(context));
-
- String comment = uriAttribute.getDisplayComment(context);
- if (comment != null) {
- vComment.setVisibility(View.VISIBLE);
- vComment.setText(comment);
- } else {
- vComment.setVisibility(View.GONE);
- }
-
- vIcon.setImageResource(uriAttribute.getDisplayIcon());
- }
-
- private void bindVerified(Context context, IdentityInfo info, boolean isSecret) {
- if (!isSecret) {
- if (info.isVerified()) {
- KeyFormattingUtils.setStatusImage(context, vVerified,
- null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
- } else {
- KeyFormattingUtils.setStatusImage(context, vVerified,
- null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
- }
- }
- }
-
- public void seekAttention() {
- if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- ObjectAnimator anim = SubtleAttentionSeeker.tintText(vComment, 1000);
- anim.setStartDelay(200);
- anim.start();
- }
- }
- }
-
private static class UserIdViewHolder extends ViewHolder {
private final TextView vName;
private final TextView vAddress;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java
index 3e3c58466..1f208349b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java
@@ -8,10 +8,10 @@ import android.arch.lifecycle.Transformations;
import android.arch.lifecycle.ViewModel;
import android.content.Context;
+import org.sufficientlysecure.keychain.daos.KeyMetadataDao;
import org.sufficientlysecure.keychain.livedata.GenericLiveData;
import org.sufficientlysecure.keychain.model.KeyMetadata;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
-import org.sufficientlysecure.keychain.daos.KeyMetadataDao;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao;
@@ -26,13 +26,12 @@ public class KeyFragmentViewModel extends ViewModel {
private LiveData systemContactInfo;
private LiveData keyserverStatus;
- LiveData> getIdentityInfo(Context context, LiveData unifiedKeyInfoLiveData,
- boolean showLinkedIds) {
+ LiveData> getIdentityInfo(Context context, LiveData unifiedKeyInfoLiveData) {
if (identityInfo == null) {
IdentityDao identityDao = IdentityDao.getInstance(context);
identityInfo = Transformations.switchMap(unifiedKeyInfoLiveData,
(unifiedKeyInfo) -> unifiedKeyInfo == null ? null : new GenericLiveData<>(context,
- () -> identityDao.getIdentityInfos(unifiedKeyInfo.master_key_id(), showLinkedIds)));
+ () -> identityDao.getIdentityInfos(unifiedKeyInfo.master_key_id())));
}
return identityInfo;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/LinkedIdViewFragment.java
deleted file mode 100644
index b30087fd7..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/LinkedIdViewFragment.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.keyview;
-
-
-import java.util.Collections;
-import java.util.List;
-
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.PorterDuff;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
-import android.support.v4.content.ContextCompat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextSwitcher;
-import android.widget.TextView;
-import android.widget.ViewAnimator;
-
-import org.sufficientlysecure.keychain.Constants.key;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.LinkedAttribute;
-import org.sufficientlysecure.keychain.linked.LinkedResource;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import org.sufficientlysecure.keychain.linked.UriAttribute;
-import org.sufficientlysecure.keychain.daos.CertificationDao;
-import org.sufficientlysecure.keychain.livedata.GenericLiveData;
-import org.sufficientlysecure.keychain.model.Certification.CertDetails;
-import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
-import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.daos.KeyRepository;
-import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
-import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
-import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
-import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment.ViewHolder.VerifyState;
-import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao;
-import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.ui.util.Notify.Style;
-import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
-import org.sufficientlysecure.keychain.ui.widget.CertListWidget;
-import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
-import timber.log.Timber;
-
-
-public class LinkedIdViewFragment extends CryptoOperationFragment implements OnBackStackChangedListener {
-
- private static final String ARG_LID_RANK = "rank";
- private static final String ARG_IS_SECRET = "verified";
- private static final String ARG_MASTER_KEY_ID = "master_key_id";
-
- private long masterKeyId;
- private boolean isSecret;
-
- private UriAttribute linkedId;
- private LinkedTokenResource linkedResource;
-
- private AsyncTask taskInProgress;
-
- private ViewHolder viewHolder;
- private int lidRank;
- private long certifyKeyId;
-
- public static LinkedIdViewFragment newInstance(long masterKeyId, int rank, boolean isSecret) {
- LinkedIdViewFragment frag = new LinkedIdViewFragment();
-
- Bundle args = new Bundle();
- args.putInt(ARG_LID_RANK, rank);
- args.putBoolean(ARG_IS_SECRET, isSecret);
- args.putLong(ARG_MASTER_KEY_ID, masterKeyId);
- frag.setArguments(args);
-
- return frag;
- }
-
- public LinkedIdViewFragment() {
- // IMPORTANT: the id must be unique in the ViewKeyActivity CryptoOperationHelper id namespace!
- // no initial progress message -> we handle progress ourselves!
- super(5, null);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Bundle args = getArguments();
- lidRank = args.getInt(ARG_LID_RANK);
-
- isSecret = args.getBoolean(ARG_IS_SECRET);
- masterKeyId = args.getLong(ARG_MASTER_KEY_ID);
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- LinkedIdViewModel viewModel = ViewModelProviders.of(this).get(LinkedIdViewModel.class);
- viewModel.getLinkedIdInfo(requireContext(), masterKeyId, lidRank).observe(this, this::onLinkedIdInfoLoaded);
- viewModel.getCertifyingKeys(requireContext()).observe(this, viewHolder.vKeySpinner::setData);
- }
-
- private void onLinkedIdInfoLoaded(LinkedIdInfo linkedIdInfo) {
- if (linkedIdInfo == null) {
- Timber.e("error loading identity");
- Notify.create(getActivity(), "Error loading linked identity!",
- Notify.LENGTH_LONG, Style.ERROR).show();
- finishFragment();
- return;
- }
-
- loadIdentity(linkedIdInfo.getLinkedAttribute(), linkedIdInfo.isVerified());
- }
-
- public void finishFragment() {
- new Handler().post(() -> {
- FragmentManager manager = getFragmentManager();
- manager.removeOnBackStackChangedListener(LinkedIdViewFragment.this);
- manager.popBackStack("linked_id", FragmentManager.POP_BACK_STACK_INCLUSIVE);
- });
- }
-
- private void loadIdentity(LinkedAttribute linkedId, boolean isVerified) {
- this.linkedId = linkedId;
-
- LinkedResource res = ((LinkedAttribute) this.linkedId).mResource;
- linkedResource = (LinkedTokenResource) res;
-
- if (!isSecret) {
- if (isVerified) {
- KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
- null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
- } else {
- KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
- null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
- }
- } else {
- viewHolder.mLinkedIdHolder.vVerified.setImageResource(R.drawable.octo_link_24dp);
- }
-
- viewHolder.mLinkedIdHolder.bind(getContext(), this.linkedId);
-
- setShowVerifying(false);
-
- if (linkedResource.isViewable()) {
- viewHolder.vButtonView.setVisibility(View.VISIBLE);
- viewHolder.vButtonView.setOnClickListener(v -> {
- Intent intent = linkedResource.getViewIntent();
- if (intent == null) {
- return;
- }
- startActivity(intent);
- });
- } else {
- viewHolder.vButtonView.setVisibility(View.GONE);
- }
-
- }
-
- static class ViewHolder {
- private final View vButtonView;
- private final ViewAnimator vVerifyingContainer;
- private final ViewAnimator vItemCertified;
- private final View vKeySpinnerContainer;
- IdentityAdapter.LinkedIdViewHolder mLinkedIdHolder;
-
- private ViewAnimator vButtonSwitcher;
- private CertListWidget vLinkedCerts;
- private KeySpinner vKeySpinner;
- private final View vButtonVerify;
- private final View vButtonRetry;
- private final View vButtonConfirm;
-
- private final ViewAnimator vProgress;
- private final TextSwitcher vText;
-
- ViewHolder(View root) {
- vLinkedCerts = root.findViewById(R.id.linked_id_certs);
- vKeySpinner = root.findViewById(R.id.cert_key_spinner);
- vKeySpinnerContainer = root.findViewById(R.id.cert_key_spincontainer);
- vButtonSwitcher = root.findViewById(R.id.button_animator);
-
- mLinkedIdHolder = new IdentityAdapter.LinkedIdViewHolder(root, null);
-
- vButtonVerify = root.findViewById(R.id.button_verify);
- vButtonRetry = root.findViewById(R.id.button_retry);
- vButtonConfirm = root.findViewById(R.id.button_confirm);
- vButtonView = root.findViewById(R.id.button_view);
-
- vVerifyingContainer = root.findViewById(R.id.linked_verify_container);
- vItemCertified = root.findViewById(R.id.linked_id_certified);
-
- vProgress = root.findViewById(R.id.linked_cert_progress);
- vText = root.findViewById(R.id.linked_cert_text);
-
- vKeySpinner.setShowNone(R.string.choice_select_cert);
- }
-
- enum VerifyState {
- VERIFYING, VERIFY_OK, VERIFY_ERROR, CERTIFYING
- }
-
- void setVerifyingState(Context context, VerifyState state, boolean isSecret) {
- switch (state) {
- case VERIFYING:
- vProgress.setDisplayedChild(0);
- vText.setText(context.getString(R.string.linked_text_verifying));
- vKeySpinnerContainer.setVisibility(View.GONE);
- break;
-
- case VERIFY_OK:
- vProgress.setDisplayedChild(1);
- if (!isSecret) {
- showButton(2);
- if (!vKeySpinner.isSingleEntry()) {
- vKeySpinnerContainer.setVisibility(View.VISIBLE);
- }
- } else {
- showButton(1);
- vKeySpinnerContainer.setVisibility(View.GONE);
- }
- break;
-
- case VERIFY_ERROR:
- showButton(1);
- vProgress.setDisplayedChild(2);
- vText.setText(context.getString(R.string.linked_text_error));
- vKeySpinnerContainer.setVisibility(View.GONE);
- break;
-
- case CERTIFYING:
- vProgress.setDisplayedChild(0);
- vText.setText(context.getString(R.string.linked_text_confirming));
- vKeySpinnerContainer.setVisibility(View.GONE);
- vButtonConfirm.setEnabled(false);
- break;
- }
- }
-
- void showVerifyingContainer(Context context, boolean show, boolean isSecret) {
- if (vVerifyingContainer.getDisplayedChild() == (show ? 1 : 0)) {
- return;
- }
-
- vVerifyingContainer.setInAnimation(context, show ? R.anim.fade_in_up : R.anim.fade_in_down);
- vVerifyingContainer.setOutAnimation(context, show ? R.anim.fade_out_up : R.anim.fade_out_down);
- vVerifyingContainer.setDisplayedChild(show ? 1 : 0);
-
- vItemCertified.setInAnimation(context, show ? R.anim.fade_in_up : R.anim.fade_in_down);
- vItemCertified.setOutAnimation(context, show ? R.anim.fade_out_up : R.anim.fade_out_down);
- vItemCertified.setDisplayedChild(show || isSecret ? 1 : 0);
- }
-
- void showButton(int which) {
- if (vButtonSwitcher.getDisplayedChild() == which) {
- return;
- }
- vButtonSwitcher.setDisplayedChild(which);
- }
-
- }
-
- private boolean mVerificationState = false;
- /** Switches between the 'verifying' ui bit and certificate status. This method
- * must behave correctly in all states, showing or hiding the appropriate views
- * and cancelling pending operations where necessary.
- *
- * This method also handles back button functionality in combination with
- * onBackStateChanged.
- */
- void setShowVerifying(boolean show) {
- if (!show) {
- if (taskInProgress != null) {
- taskInProgress.cancel(false);
- taskInProgress = null;
- }
- getFragmentManager().removeOnBackStackChangedListener(this);
- new Handler().post(() -> getFragmentManager().popBackStack("verification",
- FragmentManager.POP_BACK_STACK_INCLUSIVE));
-
- if (!mVerificationState) {
- return;
- }
- mVerificationState = false;
-
- viewHolder.showButton(0);
- viewHolder.vKeySpinnerContainer.setVisibility(View.GONE);
- viewHolder.showVerifyingContainer(getContext(), false, isSecret);
- return;
- }
-
- if (mVerificationState) {
- return;
- }
- mVerificationState = true;
-
- FragmentManager manager = getFragmentManager();
- manager.beginTransaction().addToBackStack("verification").commit();
- manager.executePendingTransactions();
- manager.addOnBackStackChangedListener(this);
- viewHolder.showVerifyingContainer(getContext(), true, isSecret);
-
- }
-
- @Override
- public void onBackStackChanged() {
- setShowVerifying(false);
- }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.linked_id_view_fragment, superContainer, false);
- Context context = getContext();
- if (context == null) {
- throw new NullPointerException();
- }
-
- viewHolder = new ViewHolder(root);
- root.setTag(viewHolder);
-
- ((ImageView) root.findViewById(R.id.status_icon_verified))
- .setColorFilter(ContextCompat.getColor(context, R.color.android_green_light),
- PorterDuff.Mode.SRC_IN);
- ((ImageView) root.findViewById(R.id.status_icon_invalid))
- .setColorFilter(ContextCompat.getColor(context, R.color.android_red_light),
- PorterDuff.Mode.SRC_IN);
-
- viewHolder.vButtonVerify.setOnClickListener(v -> verifyResource());
- viewHolder.vButtonRetry.setOnClickListener(v -> verifyResource());
- viewHolder.vButtonConfirm.setOnClickListener(v -> initiateCertifying());
-
- LinkedIdViewModel viewModel = ViewModelProviders.of(this).get(LinkedIdViewModel.class);
- viewModel.getCertDetails(context, masterKeyId, lidRank).observe(this, this::onLoadCertDetails);
-
- return root;
- }
-
- private void onLoadCertDetails(CertDetails certDetails) {
- viewHolder.vLinkedCerts.setData(certDetails, isSecret);
- }
-
- void verifyResource() {
-
- // only one at a time (no sync needed, taskInProgress is only touched in ui thread)
- if (taskInProgress != null) {
- return;
- }
-
- setShowVerifying(true);
-
- viewHolder.vKeySpinnerContainer.setVisibility(View.GONE);
- viewHolder.setVerifyingState(getContext(), VerifyState.VERIFYING, isSecret);
-
- taskInProgress = new AsyncTask() {
- @Override
- protected LinkedVerifyResult doInBackground(Void... params) {
- FragmentActivity activity = getActivity();
-
- byte[] fingerprint;
- try {
- fingerprint = KeyRepository.create(activity).getFingerprintByKeyId(masterKeyId);
- } catch (NotFoundException e) {
- throw new IllegalStateException("Key to verify linked id for must exist in db!");
- }
-
- long timer = System.currentTimeMillis();
- LinkedVerifyResult result = linkedResource.verify(activity, fingerprint);
-
- // ux flow: this operation should take at last a second
- timer = System.currentTimeMillis() -timer;
- if (timer < 1000) try {
- Thread.sleep(1000 -timer);
- } catch (InterruptedException e) {
- // never mind
- }
-
- return result;
- }
-
- @Override
- protected void onPostExecute(LinkedVerifyResult result) {
- if (isCancelled()) {
- return;
- }
- if (result.success()) {
- viewHolder.vText.setText(getString(linkedResource.getVerifiedText(isSecret)));
- // hack to preserve bold text
- ((TextView) viewHolder.vText.getCurrentView()).setText(
- linkedResource.getVerifiedText(isSecret));
- viewHolder.setVerifyingState(getContext(), VerifyState.VERIFY_OK, isSecret);
- viewHolder.mLinkedIdHolder.seekAttention();
- } else {
- viewHolder.setVerifyingState(getContext(), VerifyState.VERIFY_ERROR, isSecret);
- result.createNotify(getActivity()).show();
- }
- taskInProgress = null;
- }
- }.execute();
-
- }
-
- private void initiateCertifying() {
-
- if (isSecret) {
- return;
- }
-
- // get the user's passphrase for this key (if required)
- certifyKeyId = viewHolder.vKeySpinner.getSelectedKeyId();
- if (certifyKeyId == key.none || certifyKeyId == key.symmetric) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- SubtleAttentionSeeker.tintBackground(viewHolder.vKeySpinnerContainer, 600).start();
- } else {
- Notify.create(getActivity(), R.string.select_key_to_certify, Style.ERROR).show();
- }
- return;
- }
-
- viewHolder.setVerifyingState(getContext(), VerifyState.CERTIFYING, false);
- cryptoOperation();
-
- }
-
- @Override
- public void onCryptoOperationCancelled() {
- super.onCryptoOperationCancelled();
-
- // go back to 'verified ok'
- setShowVerifying(false);
-
- }
-
- @Nullable
- @Override
- public Parcelable createOperationInput() {
- CertifyAction action = CertifyAction.createForUserAttributes(masterKeyId,
- Collections.singletonList(linkedId.toUserAttribute()));
-
- // fill values for this action
- CertifyActionsParcel.Builder builder = CertifyActionsParcel.builder(certifyKeyId);
- builder.addActions(Collections.singletonList(action));
-
- return builder.build();
- }
-
- @Override
- public void onCryptoOperationSuccess(OperationResult result) {
- result.createNotify(getActivity()).show();
- // no need to do anything else, we will get a loader refresh!
- }
-
- @Override
- public void onCryptoOperationError(OperationResult result) {
- result.createNotify(getActivity()).show();
- }
-
- @Override
- public boolean onCryptoSetProgress(String msg, int progress, int max) {
- return true;
- }
-
- public static class LinkedIdViewModel extends ViewModel {
- LiveData> certifyingKeysLiveData;
- LiveData certDetailsLiveData;
- LiveData linkedIfInfoLiveData;
-
- LiveData> getCertifyingKeys(Context context) {
- if (certifyingKeysLiveData == null) {
- certifyingKeysLiveData = new GenericLiveData<>(context, () -> {
- KeyRepository keyRepository = KeyRepository.create(context);
- return keyRepository.getAllUnifiedKeyInfoWithSecret();
- });
- }
- return certifyingKeysLiveData;
- }
-
- LiveData getCertDetails(Context context, long masterKeyId, int lidRank) {
- if (certDetailsLiveData == null) {
- CertificationDao certificationDao = CertificationDao.getInstance(context);
- certDetailsLiveData = new GenericLiveData<>(context, masterKeyId,
- () -> certificationDao.getVerifyingCertDetails(masterKeyId, lidRank));
- }
- return certDetailsLiveData;
- }
-
- public LiveData getLinkedIdInfo(Context context, long masterKeyId, int lidRank) {
- if (linkedIfInfoLiveData == null) {
- IdentityDao identityDao = IdentityDao.getInstance(context);
- linkedIfInfoLiveData = new GenericLiveData<>(context, masterKeyId,
- () -> identityDao.getLinkedIdInfo(masterKeyId, lidRank));
- }
- return linkedIfInfoLiveData;
- }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java
index 004a7cb0c..4636a827c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java
@@ -41,17 +41,16 @@ import android.view.ViewGroup;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
import org.sufficientlysecure.keychain.model.KeyMetadata;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
-import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
-import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeyHealthStatus;
import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus;
@@ -62,8 +61,6 @@ import org.sufficientlysecure.keychain.ui.keyview.view.KeyHealthView;
import org.sufficientlysecure.keychain.ui.keyview.view.KeyStatusList.KeyDisplayStatus;
import org.sufficientlysecure.keychain.ui.keyview.view.KeyserverStatusView;
import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView;
-import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
-import org.sufficientlysecure.keychain.util.Preferences;
import timber.log.Timber;
@@ -128,8 +125,7 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
KeyFragmentViewModel model = ViewModelProviders.of(this).get(KeyFragmentViewModel.class);
- boolean showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities();
- model.getIdentityInfo(context, unifiedKeyInfoLiveData, showLinkedIds).observe(this, this::onLoadIdentityInfo);
+ model.getIdentityInfo(context, unifiedKeyInfoLiveData).observe(this, this::onLoadIdentityInfo);
model.getKeyserverStatus(context, unifiedKeyInfoLiveData).observe(this, this::onLoadKeyMetadata);
model.getSystemContactInfo(context, unifiedKeyInfoLiveData).observe(this, this::onLoadSystemContact);
model.getSubkeyStatus(context, unifiedKeyInfoLiveData).observe(this, this::onLoadSubkeyStatus);
@@ -238,21 +234,12 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
return;
}
- Context context = requireContext();
-
this.unifiedKeyInfo = unifiedKeyInfo;
-
- boolean showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities();
- boolean isSecret = unifiedKeyInfo.has_any_secret();
- identitiesCardView.setAddLinkedIdButtonVisible(showLinkedIds && isSecret);
- identitiesCardView.setIdentitiesCardListener((v) -> addLinkedIdentity());
}
private void showIdentityInfo(final int position) {
IdentityInfo info = identitiesAdapter.getInfo(position);
- if (info instanceof LinkedIdInfo) {
- showLinkedId((LinkedIdInfo) info);
- } else if (info instanceof UserIdInfo) {
+ if (info instanceof UserIdInfo) {
showUserIdInfo((UserIdInfo) info);
} else if (info instanceof AutocryptPeerInfo) {
Intent autocryptPeerIntent = ((AutocryptPeerInfo) info).getAutocryptPeerIntent();
@@ -266,12 +253,6 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
showContextMenu(position, anchor);
}
- private void showLinkedId(final LinkedIdInfo info) {
- LinkedIdViewFragment frag = LinkedIdViewFragment.newInstance(info.getMasterKeyId(), info.getRank(), unifiedKeyInfo.has_any_secret());
-
- switchToFragment(frag, "linked_id");
- }
-
private void showUserIdInfo(UserIdInfo info) {
if (!unifiedKeyInfo.has_any_secret()) {
UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, info.isVerified());
@@ -279,12 +260,6 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
}
}
- private void addLinkedIdentity() {
- Intent intent = new Intent(requireContext(), LinkedIdWizard.class);
- intent.putExtra(LinkedIdWizard.EXTRA_MASTER_KEY_ID, unifiedKeyInfo.master_key_id());
- startActivity(intent);
- }
-
public void onClickForgetIdentity(int position) {
AutocryptPeerInfo info = (AutocryptPeerInfo) identitiesAdapter.getInfo(position);
if (info == null) {
@@ -296,7 +271,7 @@ public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener
}
private void onLoadIdentityInfo(List identityInfos) {
- identitiesAdapter.setData(identityInfos, unifiedKeyInfo.has_any_secret());
+ identitiesAdapter.setData(identityInfos);
}
private void onLoadSystemContact(SystemContactInfo systemContactInfo) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java
index 9bc8c7398..288d6d18f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui.keyview.loader;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -35,17 +34,12 @@ import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import com.squareup.sqldelight.SqlDelightQuery;
import org.openintents.openpgp.util.OpenPgpApi;
-import org.sufficientlysecure.keychain.linked.LinkedAttribute;
-import org.sufficientlysecure.keychain.linked.UriAttribute;
+import org.sufficientlysecure.keychain.KeychainDatabase;
+import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
import org.sufficientlysecure.keychain.model.AutocryptPeer;
import org.sufficientlysecure.keychain.model.UserPacket;
-import org.sufficientlysecure.keychain.model.UserPacket.UserAttribute;
import org.sufficientlysecure.keychain.model.UserPacket.UserId;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
-import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
-import org.sufficientlysecure.keychain.KeychainDatabase;
import org.sufficientlysecure.keychain.ui.util.PackageIconGetter;
-import timber.log.Timber;
public class IdentityDao {
@@ -71,12 +65,9 @@ public class IdentityDao {
this.autocryptPeerDao = autocryptPeerDao;
}
- public List getIdentityInfos(long masterKeyId, boolean showLinkedIds) {
+ public List getIdentityInfos(long masterKeyId) {
ArrayList identities = new ArrayList<>();
- if (showLinkedIds) {
- loadLinkedIds(identities, masterKeyId);
- }
loadUserIds(identities, masterKeyId);
correlateOrAddAutocryptPeers(identities, masterKeyId);
@@ -132,46 +123,6 @@ public class IdentityDao {
return null;
}
- private void loadLinkedIds(ArrayList identities, long masterKeyId) {
- SqlDelightQuery query = UserPacket.FACTORY.selectUserAttributesByTypeAndMasterKeyId(
- (long) WrappedUserAttribute.UAT_URI_ATTRIBUTE, masterKeyId);
- try (Cursor cursor = db.query(query)) {
- while (cursor.moveToNext()) {
- UserAttribute userAttribute = UserPacket.USER_ATTRIBUTE_MAPPER.map(cursor);
-
- LinkedIdInfo linkedIdInfo = parseLinkedIdInfo(userAttribute);
- identities.add(linkedIdInfo);
- }
- }
- }
-
- public LinkedIdInfo getLinkedIdInfo(long masterKeyId, int rank) {
- SqlDelightQuery query = UserPacket.FACTORY.selectSpecificUserAttribute(
- (long) WrappedUserAttribute.UAT_URI_ATTRIBUTE, masterKeyId, rank);
- try (Cursor cursor = db.query(query)) {
- if (cursor.moveToFirst()) {
- UserAttribute userAttribute = UserPacket.USER_ATTRIBUTE_MAPPER.map(cursor);
-
- return parseLinkedIdInfo(userAttribute);
- }
- }
- return null;
- }
-
- @Nullable
- private LinkedIdInfo parseLinkedIdInfo(UserAttribute userAttribute) {
- try {
- UriAttribute uriAttribute = LinkedAttribute.fromAttributeData(userAttribute.attribute_data());
- if (uriAttribute instanceof LinkedAttribute) {
- return LinkedIdInfo.create(userAttribute.master_key_id(), userAttribute.rank(),
- userAttribute.isVerified(), userAttribute.is_primary(), (LinkedAttribute) uriAttribute);
- }
- } catch (IOException e) {
- Timber.e(e, "Failed parsing uri attribute");
- }
- return null;
- }
-
private void loadUserIds(ArrayList identities, long... masterKeyId) {
SqlDelightQuery query = UserPacket.FACTORY.selectUserIdsByMasterKeyId(masterKeyId);
try (Cursor cursor = db.query(query)) {
@@ -214,20 +165,6 @@ public class IdentityDao {
}
}
- @AutoValue
- public abstract static class LinkedIdInfo implements IdentityInfo {
- public abstract long getMasterKeyId();
- public abstract int getRank();
- public abstract boolean isVerified();
- public abstract boolean isPrimary();
-
- public abstract LinkedAttribute getLinkedAttribute();
-
- static LinkedIdInfo create(long masterKeyId, int rank, boolean isVerified, boolean isPrimary, LinkedAttribute linkedAttribute) {
- return new AutoValue_IdentityDao_LinkedIdInfo(masterKeyId, rank, isVerified, isPrimary, linkedAttribute);
- }
- }
-
@AutoValue
public abstract static class AutocryptPeerInfo implements IdentityInfo {
public abstract long getMasterKeyId();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java
index 9a9e2b5b0..aaedd2daa 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java
@@ -36,8 +36,6 @@ import org.sufficientlysecure.keychain.ui.util.recyclerview.DividerItemDecoratio
public class IdentitiesCardView extends CardView {
private final RecyclerView vIdentities;
- private final Button linkedIdsAddButton;
-
public IdentitiesCardView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -46,8 +44,6 @@ public class IdentitiesCardView extends CardView {
vIdentities = view.findViewById(R.id.view_key_user_ids);
vIdentities.setLayoutManager(new LinearLayoutManager(context));
vIdentities.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL_LIST, false));
-
- linkedIdsAddButton = view.findViewById(R.id.view_key_card_linked_ids_add);
}
public void setIdentitiesAdapter(IdentityAdapter identityAdapter) {
@@ -59,12 +55,4 @@ public class IdentitiesCardView extends CardView {
});
vIdentities.setAdapter(identityAdapter);
}
-
- public void setIdentitiesCardListener(OnClickListener identitiesCardListener) {
- linkedIdsAddButton.setOnClickListener(identitiesCardListener);
- }
-
- public void setAddLinkedIdButtonVisible(boolean show) {
- linkedIdsAddButton.setVisibility(show ? View.VISIBLE : View.GONE);
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
deleted file mode 100644
index 55552ae03..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import android.arch.lifecycle.ViewModelProviders;
-import android.graphics.PorterDuff;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.ViewAnimator;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.LinkedAttribute;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
-import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
-import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-
-public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragment {
- private ImageView mVerifyImage;
- private TextView mVerifyStatus;
- private ViewAnimator mVerifyAnimator;
-
- private long masterKeyId;
- byte[] fingerprint;
-
- // This is a resource, set AFTER it has been verified
- LinkedTokenResource mVerifiedResource = null;
- private ViewAnimator mVerifyButtonAnimator;
-
- protected abstract View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
- viewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
- }
-
- private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
- this.masterKeyId = unifiedKeyInfo.master_key_id();
- this.fingerprint = unifiedKeyInfo.fingerprint();
- }
-
- @NonNull
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = newView(inflater, container, savedInstanceState);
-
- View nextButton = view.findViewById(R.id.next_button);
- if (nextButton != null) {
- nextButton.setOnClickListener(v -> cryptoOperation());
- }
-
- view.findViewById(R.id.back_button).setOnClickListener(
- v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
-
- mVerifyAnimator = view.findViewById(R.id.verify_progress);
- mVerifyImage = view.findViewById(R.id.verify_image);
- mVerifyStatus = view.findViewById(R.id.verify_status);
- mVerifyButtonAnimator = view.findViewById(R.id.verify_buttons);
-
- view.findViewById(R.id.button_verify).setOnClickListener(v -> proofVerify());
-
- view.findViewById(R.id.button_retry).setOnClickListener(v -> proofVerify());
-
- setVerifyProgress(false, null);
- mVerifyStatus.setText(R.string.linked_verify_pending);
-
- return view;
- }
-
- abstract LinkedTokenResource getResource(OperationLog log);
-
- private void setVerifyProgress(boolean on, Boolean success) {
- if (success == null) {
- mVerifyStatus.setText(R.string.linked_verifying);
- displayButton(on ? 2 : 0);
- } else if (success) {
- mVerifyStatus.setText(R.string.linked_verify_success);
- mVerifyImage.setImageResource(R.drawable.status_signature_verified_cutout_24dp);
- mVerifyImage.setColorFilter(getResources().getColor(R.color.android_green_dark),
- PorterDuff.Mode.SRC_IN);
- displayButton(2);
- } else {
- mVerifyStatus.setText(R.string.linked_verify_error);
- mVerifyImage.setImageResource(R.drawable.status_signature_unknown_cutout_24dp);
- mVerifyImage.setColorFilter(getResources().getColor(R.color.android_red_dark),
- PorterDuff.Mode.SRC_IN);
- displayButton(1);
- }
- mVerifyAnimator.setDisplayedChild(on ? 1 : 0);
- }
-
- public void displayButton(int button) {
- if (mVerifyButtonAnimator.getDisplayedChild() == button) {
- return;
- }
- mVerifyButtonAnimator.setDisplayedChild(button);
- }
-
- protected void proofVerify() {
- setVerifyProgress(true, null);
-
- new AsyncTask() {
-
- @Override
- protected LinkedVerifyResult doInBackground(Void... params) {
- long timer = System.currentTimeMillis();
-
- OperationLog log = new OperationLog();
- LinkedTokenResource resource = getResource(log);
- if (resource == null) {
- return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
- }
-
- LinkedVerifyResult result = resource.verify(getActivity(), fingerprint);
-
- // ux flow: this operation should take at last a second
- timer = System.currentTimeMillis() -timer;
- if (timer < 1000) try {
- Thread.sleep(1000 -timer);
- } catch (InterruptedException e) {
- // never mind
- }
-
- if (result.success()) {
- mVerifiedResource = resource;
- }
- return result;
- }
-
- @Override
- protected void onPostExecute(LinkedVerifyResult result) {
- super.onPostExecute(result);
- if (result.success()) {
- setVerifyProgress(false, true);
- } else {
- setVerifyProgress(false, false);
- // on error, show error message
- result.createNotify(getActivity()).show(LinkedIdCreateFinalFragment.this);
- }
- }
- }.execute();
-
- }
-
- @Override
- protected void cryptoOperation() {
- if (mVerifiedResource == null) {
- Notify.create(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR)
- .show(LinkedIdCreateFinalFragment.this);
- return;
- }
-
- super.cryptoOperation();
- }
-
- @Override
- protected void cryptoOperation(CryptoInputParcel cryptoInput) {
- if (mVerifiedResource == null) {
- Notify.create(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR)
- .show(LinkedIdCreateFinalFragment.this);
- return;
- }
-
- super.cryptoOperation(cryptoInput);
- }
-
- @Nullable
- @Override
- public Parcelable createOperationInput() {
- SaveKeyringParcel.Builder builder=
- SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, fingerprint);
- WrappedUserAttribute ua = LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
- builder.addUserAttribute(ua);
- return builder.build();
- }
-
- @Override
- public void onCryptoOperationSuccess(OperationResult result) {
- requireActivity().finish();
- }
-
- @Override
- public void onCryptoOperationError(OperationResult result) {
- result.createNotify(getActivity()).show(this);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java
deleted file mode 100644
index 81594bcb4..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.net.SocketTimeoutException;
-import java.net.URI;
-import java.net.URL;
-import java.util.Random;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.util.Base64;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.CookieManager;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.ViewAnimator;
-
-import javax.net.ssl.HttpsURLConnection;
-import org.bouncycastle.util.encoders.Hex;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.sufficientlysecure.keychain.BuildConfig;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.LinkedAttribute;
-import org.sufficientlysecure.keychain.linked.resources.GithubResource;
-import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
-import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
-import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
-import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.ui.util.Notify.Style;
-import org.sufficientlysecure.keychain.ui.widget.StatusIndicator;
-import org.sufficientlysecure.keychain.ui.widget.StatusIndicator.Status;
-import timber.log.Timber;
-
-
-public class LinkedIdCreateGithubFragment extends CryptoOperationFragment {
-
- public static final String ARG_GITHUB_COOKIE = "github_cookie";
- private Button mRetryButton;
-
- enum State {
- IDLE, AUTH_PROCESS, AUTH_ERROR, POST_PROCESS, POST_ERROR, LID_PROCESS, LID_ERROR, DONE
- }
-
- ViewAnimator mButtonContainer;
-
- StatusIndicator mStatus1, mStatus2, mStatus3;
-
- byte[] mFingerprint;
- long mMasterKeyId;
- private SaveKeyringParcel.Builder mSkpBuilder;
- private TextView mLinkedIdTitle, mLinkedIdComment;
- private boolean mFinishOnStop;
-
- public static LinkedIdCreateGithubFragment newInstance() {
- return new LinkedIdCreateGithubFragment();
- }
-
- public LinkedIdCreateGithubFragment() {
- super(null);
- }
-
- @Override @NonNull
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.linked_create_github_fragment, container, false);
-
- mButtonContainer = view.findViewById(R.id.button_container);
-
- mStatus1 = view.findViewById(R.id.linked_status_step1);
- mStatus2 = view.findViewById(R.id.linked_status_step2);
- mStatus3 = view.findViewById(R.id.linked_status_step3);
-
- mRetryButton = view.findViewById(R.id.button_retry);
-
- ((ImageView) view.findViewById(R.id.linked_id_type_icon)).setImageResource(R.drawable.linked_github);
- ((ImageView) view.findViewById(R.id.linked_id_certified_icon)).setImageResource(R.drawable.octo_link_24dp);
- mLinkedIdTitle = view.findViewById(R.id.linked_id_title);
- mLinkedIdComment = view.findViewById(R.id.linked_id_comment);
-
- view.findViewById(R.id.back_button).setOnClickListener(v -> {
- LinkedIdWizard activity = (LinkedIdWizard) requireActivity();
- activity.loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
- });
-
- view.findViewById(R.id.button_send).setOnClickListener(v -> {
- step1GetOAuthCode();
- // for animation testing
- // onCryptoOperationSuccess(null);
- });
-
- return view;
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
- viewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
- }
-
- private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
- this.mMasterKeyId = unifiedKeyInfo.master_key_id();
- this.mFingerprint = unifiedKeyInfo.fingerprint();
- }
-
- private void step1GetOAuthCode() {
- setState(State.AUTH_PROCESS);
-
- mButtonContainer.setDisplayedChild(1);
-
- new Handler().postDelayed(
- () -> oAuthRequest("github.com/login/oauth/authorize", BuildConfig.GITHUB_CLIENT_ID, "gist"), 300);
-
- }
-
- private void showRetryForOAuth() {
- mRetryButton.setOnClickListener(v -> {
- v.setOnClickListener(null);
- step1GetOAuthCode();
- });
- mButtonContainer.setDisplayedChild(3);
-
- }
-
- private void step1GetOAuthToken() {
-
- if (mOAuthCode == null) {
- setState(State.AUTH_ERROR);
- showRetryForOAuth();
- return;
- }
-
- Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
- final String gistText = GithubResource.generate(activity, mFingerprint);
-
- new AsyncTask() {
-
- Exception mException;
-
- @Override
- protected JSONObject doInBackground(Void... dummy) {
- try {
-
- JSONObject params = new JSONObject();
- params.put("client_id", BuildConfig.GITHUB_CLIENT_ID);
- params.put("client_secret", BuildConfig.GITHUB_CLIENT_SECRET);
- params.put("code", mOAuthCode);
- params.put("state", mOAuthState);
-
- return jsonHttpRequest("https://github.com/login/oauth/access_token", params, null);
-
- } catch (IOException | HttpResultException e) {
- mException = e;
- } catch (JSONException e) {
- throw new AssertionError("json error, this is a bug!");
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(JSONObject result) {
- super.onPostExecute(result);
-
- Activity activity = getActivity();
- if (activity == null) {
- // we couldn't show an error anyways
- return;
- }
-
- Timber.d("response: " + result);
-
- if (result == null || result.optString("access_token", null) == null) {
- setState(State.AUTH_ERROR);
- showRetryForOAuth();
-
- if (result != null) {
- Notify.create(activity, R.string.linked_error_auth_failed, Style.ERROR).show();
- return;
- }
-
- if (mException instanceof SocketTimeoutException) {
- Notify.create(activity, R.string.linked_error_timeout, Style.ERROR).show();
- } else if (mException instanceof HttpResultException) {
- Notify.create(activity, activity.getString(R.string.linked_error_http,
- ((HttpResultException) mException).mResponse),
- Style.ERROR).show();
- } else if (mException instanceof IOException) {
- Notify.create(activity, R.string.linked_error_network, Style.ERROR).show();
- }
-
- return;
- }
-
- step2PostGist(result.optString("access_token"), gistText);
-
- }
- }.execute();
-
- }
-
- private void step2PostGist(final String accessToken, final String gistText) {
-
- setState(State.POST_PROCESS);
-
- new AsyncTask() {
-
- Exception mException;
-
- @Override
- protected JSONObject doInBackground(Void... dummy) {
- try {
-
- long timer = System.currentTimeMillis();
-
- JSONObject file = new JSONObject();
- file.put("content", gistText);
-
- JSONObject files = new JSONObject();
- files.put("openpgp.txt", file);
-
- JSONObject params = new JSONObject();
- params.put("public", true);
- params.put("description", getString(R.string.linked_gist_description));
- params.put("files", files);
-
- JSONObject result = jsonHttpRequest("https://api.github.com/gists", params, accessToken);
-
- // ux flow: this operation should take at last a second
- timer = System.currentTimeMillis() -timer;
- if (timer < 1000) try {
- Thread.sleep(1000 -timer);
- } catch (InterruptedException e) {
- // never mind
- }
-
- return result;
-
- } catch (IOException | HttpResultException e) {
- mException = e;
- } catch (JSONException e) {
- throw new AssertionError("json error, this is a bug!");
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(JSONObject result) {
- super.onPostExecute(result);
-
- Timber.d("response: " + result);
-
- Activity activity = getActivity();
- if (activity == null) {
- // we couldn't show an error anyways
- return;
- }
-
- if (result == null) {
- setState(State.POST_ERROR);
- showRetryForOAuth();
-
- if (mException instanceof SocketTimeoutException) {
- Notify.create(activity, R.string.linked_error_timeout, Style.ERROR).show();
- } else if (mException instanceof HttpResultException) {
- Notify.create(activity, activity.getString(R.string.linked_error_http,
- ((HttpResultException) mException).mResponse),
- Style.ERROR).show();
- } else if (mException instanceof IOException) {
- Notify.create(activity, R.string.linked_error_network, Style.ERROR).show();
- }
-
- return;
- }
-
- GithubResource resource;
-
- try {
- String gistId = result.getString("id");
- JSONObject owner = result.getJSONObject("owner");
- String gistLogin = owner.getString("login");
-
- URI uri = URI.create("https://gist.github.com/" + gistLogin + "/" + gistId);
- resource = GithubResource.create(uri);
- } catch (JSONException e) {
- setState(State.POST_ERROR);
- return;
- }
-
- View linkedItem = mButtonContainer.getChildAt(2);
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- linkedItem.setTransitionName(resource.toUri().toString());
- }
-
- // we only need authorization for this one operation, drop it afterwards
- revokeToken(accessToken);
-
- step3EditKey(resource);
- }
-
- }.execute();
-
- }
-
- private void revokeToken(final String token) {
-
- new AsyncTask() {
- @Override
- protected Void doInBackground(Void... dummy) {
- try {
- HttpsURLConnection nection = (HttpsURLConnection) new URL(
- "https://api.github.com/applications/" + BuildConfig.GITHUB_CLIENT_ID + "/tokens/" + token)
- .openConnection();
- nection.setRequestMethod("DELETE");
- String encoded = Base64.encodeToString(
- (BuildConfig.GITHUB_CLIENT_ID + ":" + BuildConfig.GITHUB_CLIENT_SECRET).getBytes(), Base64.NO_WRAP);
- nection.setRequestProperty("Authorization", "Basic " + encoded);
- nection.connect();
- } catch (IOException e) {
- // nvm
- }
- return null;
- }
- }.execute();
-
- }
-
- private void step3EditKey(final GithubResource resource) {
-
- // set item data while we're there
- {
- Context context = getActivity();
- mLinkedIdTitle.setText(resource.getDisplayTitle(context));
- mLinkedIdComment.setText(resource.getDisplayComment(context));
- }
-
- setState(State.LID_PROCESS);
-
- new Handler().postDelayed(() -> {
- WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
- mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
- mSkpBuilder.addUserAttribute(ua);
- cryptoOperation();
- }, 250);
-
- }
-
- @Nullable
- @Override
- public SaveKeyringParcel createOperationInput() {
- // if this is null, the cryptoOperation silently aborts - which is what we want in that case
- return mSkpBuilder.build();
- }
-
- @Override
- public void onCryptoOperationSuccess(EditKeyResult result) {
-
- setState(State.DONE);
-
- mButtonContainer.getInAnimation().setDuration(750);
- mButtonContainer.setDisplayedChild(2);
-
- new Handler().postDelayed(() -> {
- Activity activity = requireActivity();
- Intent intent = ViewKeyActivity.getViewKeyActivityIntent(requireActivity(), mMasterKeyId);
- // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- intent.putExtra(ViewKeyActivity.EXTRA_LINKED_TRANSITION, true);
- View linkedItem = mButtonContainer.getChildAt(2);
-
- Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(
- activity, linkedItem, linkedItem.getTransitionName()).toBundle();
- activity.startActivity(intent, options);
- mFinishOnStop = true;
- } else {
- activity.startActivity(intent);
- activity.finish();
- }
- }, 1000);
- }
-
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
-
- // cookies are automatically saved, we don't want that
- CookieManager cookieManager = CookieManager.getInstance();
- String cookie = cookieManager.getCookie("https://github.com/");
- outState.putString(ARG_GITHUB_COOKIE, cookie);
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- if (savedInstanceState != null) {
- String cookie = savedInstanceState.getString(ARG_GITHUB_COOKIE);
- CookieManager cookieManager = CookieManager.getInstance();
- cookieManager.setCookie("https://github.com/", cookie);
- }
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- try {
- // cookies are automatically saved, we don't want that
- CookieManager cookieManager = CookieManager.getInstance();
- // noinspection deprecation (replacement is api lvl 21)
- cookieManager.removeAllCookie();
- } catch (Exception e) {
- // no biggie if this fails
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- if (mFinishOnStop) {
- Activity activity = requireActivity();
- activity.setResult(Activity.RESULT_OK);
- activity.finish();
- }
- }
-
- @Override
- public void onCryptoOperationError(EditKeyResult result) {
- result.createNotify(getActivity()).show(this);
- setState(State.LID_ERROR);
- }
-
- @Override
- public void onCryptoOperationCancelled() {
- mRetryButton.setOnClickListener(v -> {
- v.setOnClickListener(null);
- mButtonContainer.setDisplayedChild(1);
- setState(State.LID_PROCESS);
- cryptoOperation();
- });
- mButtonContainer.setDisplayedChild(3);
- setState(State.LID_ERROR);
- }
-
- private String mOAuthCode, mOAuthState;
-
- public void oAuthRequest(String hostAndPath, String clientId, String scope) {
-
- Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
- byte[] buf = new byte[16];
- new Random().nextBytes(buf);
- mOAuthState = new String(Hex.encode(buf));
- mOAuthCode = null;
-
- final Dialog auth_dialog = new Dialog(activity);
- auth_dialog.setContentView(R.layout.oauth_webview);
- WebView web = auth_dialog.findViewById(R.id.web_view);
- web.getSettings().setSaveFormData(false);
- web.getSettings().setJavaScriptEnabled(true);
- web.getSettings().setUserAgentString("OpenKeychain " + BuildConfig.VERSION_NAME);
- web.setWebViewClient(new WebViewClient() {
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- Uri uri = Uri.parse(url);
- if ("oauth-openkeychain".equals(uri.getScheme())) {
-
- if (mOAuthCode != null) {
- return true;
- }
-
- if (uri.getQueryParameter("error") != null) {
- Timber.i("got oauth error: " + uri.getQueryParameter("error"));
- auth_dialog.dismiss();
- return true;
- }
-
- // check if mOAuthState == queryParam[state]
- mOAuthCode = uri.getQueryParameter("code");
-
- auth_dialog.dismiss();
- return true;
- }
- // don't surf away from github!
- if (!"github.com".equals(uri.getHost())) {
- auth_dialog.dismiss();
- return true;
- }
- return false;
- }
-
- });
-
- auth_dialog.setTitle(R.string.linked_webview_title_github);
- auth_dialog.setCancelable(true);
- auth_dialog.setOnDismissListener(dialog -> step1GetOAuthToken());
- auth_dialog.show();
-
- web.loadUrl("https://" + hostAndPath +
- "?client_id=" + clientId +
- "&scope=" + scope +
- "&redirect_uri=oauth-openkeychain://linked/" +
- "&state=" + mOAuthState);
-
- }
-
- public void setState(State state) {
- switch (state) {
- case IDLE:
- mStatus1.setDisplayedChild(Status.IDLE);
- mStatus2.setDisplayedChild(Status.IDLE);
- mStatus3.setDisplayedChild(Status.IDLE);
- break;
- case AUTH_PROCESS:
- mStatus1.setDisplayedChild(Status.PROGRESS);
- mStatus2.setDisplayedChild(Status.IDLE);
- mStatus3.setDisplayedChild(Status.IDLE);
- break;
- case AUTH_ERROR:
- mStatus1.setDisplayedChild(Status.ERROR);
- mStatus2.setDisplayedChild(Status.IDLE);
- mStatus3.setDisplayedChild(Status.IDLE);
- break;
- case POST_PROCESS:
- mStatus1.setDisplayedChild(Status.OK);
- mStatus2.setDisplayedChild(Status.PROGRESS);
- mStatus3.setDisplayedChild(Status.IDLE);
- break;
- case POST_ERROR:
- mStatus1.setDisplayedChild(Status.OK);
- mStatus2.setDisplayedChild(Status.ERROR);
- mStatus3.setDisplayedChild(Status.IDLE);
- break;
- case LID_PROCESS:
- mStatus1.setDisplayedChild(Status.OK);
- mStatus2.setDisplayedChild(Status.OK);
- mStatus3.setDisplayedChild(Status.PROGRESS);
- break;
- case LID_ERROR:
- mStatus1.setDisplayedChild(Status.OK);
- mStatus2.setDisplayedChild(Status.OK);
- mStatus3.setDisplayedChild(Status.ERROR);
- break;
- case DONE:
- mStatus1.setDisplayedChild(Status.OK);
- mStatus2.setDisplayedChild(Status.OK);
- mStatus3.setDisplayedChild(Status.OK);
- }
- }
-
- private static JSONObject jsonHttpRequest(String url, JSONObject params, String accessToken)
- throws IOException, HttpResultException {
-
- HttpsURLConnection nection = (HttpsURLConnection) new URL(url).openConnection();
- nection.setDoInput(true);
- nection.setDoOutput(true);
- nection.setConnectTimeout(3000);
- nection.setReadTimeout(5000);
- nection.setRequestProperty("Content-Type", "application/json");
- nection.setRequestProperty("Accept", "application/json");
- nection.setRequestProperty("User-Agent", "OpenKeychain " + BuildConfig.VERSION_NAME);
- if (accessToken != null) {
- nection.setRequestProperty("Authorization", "token " + accessToken);
- }
-
- try {
-
- nection.connect();
-
- OutputStream os = nection.getOutputStream();
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
- writer.write(params.toString());
- writer.flush();
- writer.close();
- os.close();
-
- int code = nection.getResponseCode();
- if (code != HttpsURLConnection.HTTP_CREATED && code != HttpsURLConnection.HTTP_OK) {
- throw new HttpResultException(nection.getResponseCode(), nection.getResponseMessage());
- }
-
- InputStream in = new BufferedInputStream(nection.getInputStream());
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- StringBuilder response = new StringBuilder();
- while (true) {
- String line = reader.readLine();
- if (line == null) {
- break;
- }
- response.append(line);
- }
-
- try {
- return new JSONObject(response.toString());
- } catch (JSONException e) {
- throw new IOException(e);
- }
-
- } finally {
- nection.disconnect();
- }
-
- }
-
- static class HttpResultException extends Exception {
- final int mCode;
- final String mResponse;
-
- HttpResultException(int code, String response) {
- mCode = code;
- mResponse = response;
- }
-
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java
deleted file mode 100644
index 4ec67e948..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.Fragment;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Patterns;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-
-import org.sufficientlysecure.keychain.R;
-
-
-public class LinkedIdCreateHttpsStep1Fragment extends Fragment {
- EditText mEditUri;
-
- public static LinkedIdCreateHttpsStep1Fragment newInstance() {
- LinkedIdCreateHttpsStep1Fragment frag = new LinkedIdCreateHttpsStep1Fragment();
-
- Bundle args = new Bundle();
- frag.setArguments(args);
-
- return frag;
- }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = inflater.inflate(R.layout.linked_create_https_fragment_step1, container, false);
-
- view.findViewById(R.id.next_button).setOnClickListener(v -> {
- String uri = "https://" + mEditUri.getText();
-
- if (!checkUri(uri)) {
- return;
- }
-
- LinkedIdCreateHttpsStep2Fragment frag = LinkedIdCreateHttpsStep2Fragment.newInstance(uri);
-
- ((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
- });
-
- view.findViewById(R.id.back_button).setOnClickListener(
- v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
-
- mEditUri = view.findViewById(R.id.linked_create_https_uri);
-
- mEditUri.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
- }
-
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- String uri = "https://" + editable;
- if (uri.length() > 0) {
- if (checkUri(uri)) {
- mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.ic_stat_retyped_ok, 0);
- } else {
- mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.ic_stat_retyped_bad, 0);
- }
- } else {
- // remove drawable if email is empty
- mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
- }
- }
- });
-
- // mEditUri.setText("mugenguild.com/pgpkey.txt");
-
- return view;
- }
-
- private static boolean checkUri(String uri) {
- return Patterns.WEB_URL.matcher(uri).matches();
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
deleted file mode 100644
index f6e90c28c..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.ui.util.Notify.Style;
-import org.sufficientlysecure.keychain.util.FileHelper;
-import timber.log.Timber;
-
-public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragment {
- private static final int REQUEST_CODE_OUTPUT = 0x00007007;
-
- public static final String ARG_URI = "uri";
-
- EditText mEditUri;
-
- URI mResourceUri;
-
- public static LinkedIdCreateHttpsStep2Fragment newInstance(String uri) {
-
- LinkedIdCreateHttpsStep2Fragment frag = new LinkedIdCreateHttpsStep2Fragment();
-
- Bundle args = new Bundle();
- args.putString(ARG_URI, uri);
- frag.setArguments(args);
-
- return frag;
- }
-
- @Override
- GenericHttpsResource getResource(OperationLog log) {
- return GenericHttpsResource.createNew(mResourceUri);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- try {
- mResourceUri = new URI(getArguments().getString(ARG_URI));
- } catch (URISyntaxException e) {
- Timber.e(e);
- requireActivity().finish();
- }
- }
-
- @Override
- protected View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.linked_create_https_fragment_step2, container, false);
- }
-
- @NonNull
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = super.onCreateView(inflater, container, savedInstanceState);
-
- view.findViewById(R.id.button_send).setOnClickListener(v -> proofSend());
- view.findViewById(R.id.button_save).setOnClickListener(v -> proofSave());
-
- mEditUri = view.findViewById(R.id.linked_create_https_uri);
- mEditUri.setText(mResourceUri.toString());
-
- return view;
- }
-
- private String getResourceString() {
- return GenericHttpsResource.generateText(requireActivity(), fingerprint);
- }
-
- private void proofSend() {
- Intent sendIntent = new Intent();
- sendIntent.setAction(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_TEXT, getResourceString());
- sendIntent.setType("text/plain");
- startActivity(sendIntent);
- }
-
- private void proofSave() {
- String state = Environment.getExternalStorageState();
- if (!Environment.MEDIA_MOUNTED.equals(state)) {
- Notify.create(getActivity(), "External storage not available!", Style.ERROR).show();
- return;
- }
-
- String targetName = "pgpkey.txt";
-
- // TODO: not supported on Android < 4.4
- FileHelper.saveDocument(this, targetName, "text/plain", REQUEST_CODE_OUTPUT);
- }
-
- private void saveFile(Uri uri) {
- try {
- PrintWriter out = new PrintWriter(requireActivity().getContentResolver().openOutputStream(uri));
- out.print(getResourceString());
- if (out.checkError()) {
- Notify.create(getActivity(), "Error writing file!", Style.ERROR).show();
- }
- } catch (FileNotFoundException e) {
- Notify.create(getActivity(), "File could not be opened for writing!", Style.ERROR).show();
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- // For saving a file
- case REQUEST_CODE_OUTPUT:
- if (data == null) {
- return;
- }
- Uri uri = data.getData();
- saveFile(uri);
- break;
- default:
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
deleted file mode 100644
index 41d3f2adb..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.EditText;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-
-public class LinkedIdCreateTwitterStep1Fragment extends Fragment {
- EditText mEditHandle;
-
- public static LinkedIdCreateTwitterStep1Fragment newInstance() {
- return new LinkedIdCreateTwitterStep1Fragment();
- }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = inflater.inflate(R.layout.linked_create_twitter_fragment_step1, container, false);
-
- view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
-
- final String handle = mEditHandle.getText().toString();
-
- if ("".equals(handle)) {
- mEditHandle.setError("Please input a Twitter handle!");
- return;
- }
-
- new AsyncTask() {
-
- @Override
- protected Boolean doInBackground(Void... params) {
- return true;
- // return checkHandle(handle);
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- super.onPostExecute(result);
-
- if (result == null) {
- Notify.create(getActivity(),
- "Connection error while checking username!",
- Notify.Style.ERROR).show(LinkedIdCreateTwitterStep1Fragment.this);
- return;
- }
-
- if (!result) {
- Notify.create(getActivity(),
- "This handle does not exist on Twitter!",
- Notify.Style.ERROR).show(LinkedIdCreateTwitterStep1Fragment.this);
- return;
- }
-
- LinkedIdCreateTwitterStep2Fragment frag =
- LinkedIdCreateTwitterStep2Fragment.newInstance(handle);
-
- ((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
- }
- }.execute();
-
- }
- });
-
- view.findViewById(R.id.back_button).setOnClickListener(
- v -> ((LinkedIdWizard) requireActivity()).loadFragment(null, LinkedIdWizard.FRAG_ACTION_TO_LEFT));
-
- mEditHandle = view.findViewById(R.id.linked_create_twitter_handle);
-
- return view;
- }
-
- /* not used at this point, too many problems
- private static Boolean checkHandle(String handle) {
- try {
- HttpURLConnection nection =
- (HttpURLConnection) new URL("https://twitter.com/" + handle).getUrlResponse();
- nection.setRequestMethod("HEAD");
- nection.setRequestProperty("User-Agent", "OpenKeychain");
- return nection.getResponseCode() == 200;
- } catch (IOException e) {
- return null;
- }
- }
- */
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java
deleted file mode 100644
index 37be1b89c..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.Html;
-import android.text.Spanned;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
-import org.sufficientlysecure.keychain.linked.resources.TwitterResource;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-
-public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragment {
-
- public static final String ARG_HANDLE = "handle";
-
- String mResourceHandle;
-
- public static LinkedIdCreateTwitterStep2Fragment newInstance(String handle) {
- LinkedIdCreateTwitterStep2Fragment frag = new LinkedIdCreateTwitterStep2Fragment();
-
- Bundle args = new Bundle();
- args.putString(ARG_HANDLE, handle);
- frag.setArguments(args);
-
- return frag;
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- mResourceHandle = getArguments().getString(ARG_HANDLE);
- }
-
- private String getResourceString() {
- return TwitterResource.generate(fingerprint);
- }
-
- @NonNull
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = super.onCreateView(inflater, container, savedInstanceState);
-
- view.findViewById(R.id.button_send).setOnClickListener(v -> proofSend());
- view.findViewById(R.id.button_share).setOnClickListener(v -> proofShare());
-
- Spanned tweetText = Html.fromHtml(getString(R.string.linked_create_twitter_2_3, mResourceHandle));
- ((TextView) view.findViewById(R.id.linked_tweet_published)).setText(tweetText);
-
- return view;
- }
-
- @Override
- LinkedTokenResource getResource(OperationLog log) {
- return TwitterResource.searchInTwitterStream(getActivity(), mResourceHandle, getResourceString(), log);
- }
-
- @Override
- protected View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.linked_create_twitter_fragment_step2, container, false);
- }
-
- private void proofShare() {
- Intent sendIntent = new Intent();
- sendIntent.setAction(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_TEXT, getResourceString());
- sendIntent.setType("text/plain");
- startActivity(sendIntent);
- }
-
- private void proofSend() {
- Uri.Builder builder = Uri.parse("https://twitter.com/intent/tweet").buildUpon();
- builder.appendQueryParameter("text", getResourceString());
- Uri uri = builder.build();
-
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- startActivity(intent);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java
deleted file mode 100644
index cd8262aaf..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.sufficientlysecure.keychain.R;
-
-
-public class LinkedIdSelectFragment extends Fragment {
- public static LinkedIdSelectFragment newInstance() {
- return new LinkedIdSelectFragment();
- }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.linked_select_fragment, container, false);
-
- view.findViewById(R.id.linked_create_https_button).setOnClickListener(v -> {
- LinkedIdCreateHttpsStep1Fragment frag = LinkedIdCreateHttpsStep1Fragment.newInstance();
- ((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
- });
-
- view.findViewById(R.id.linked_create_twitter_button).setOnClickListener(v -> {
- LinkedIdCreateTwitterStep1Fragment frag = LinkedIdCreateTwitterStep1Fragment.newInstance();
- ((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
- });
-
- view.findViewById(R.id.linked_create_github_button).setOnClickListener(v -> {
- LinkedIdCreateGithubFragment frag = LinkedIdCreateGithubFragment.newInstance();
- ((LinkedIdWizard) requireActivity()).loadFragment(frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
- });
-
-
- return view;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java
deleted file mode 100644
index bea6df04b..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * 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 .
- */
-
-package org.sufficientlysecure.keychain.ui.linked;
-
-
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
-import org.sufficientlysecure.keychain.ui.base.BaseActivity;
-import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
-import timber.log.Timber;
-
-
-public class LinkedIdWizard extends BaseActivity {
- public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
-
- public static final int FRAG_ACTION_START = 0;
- public static final int FRAG_ACTION_TO_RIGHT = 1;
- public static final int FRAG_ACTION_TO_LEFT = 2;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTitle(getString(R.string.title_linked_id_create));
-
- Bundle extras = getIntent().getExtras();
- if (extras == null || !extras.containsKey(EXTRA_MASTER_KEY_ID)) {
- Timber.e("Missing required extra master_key_id!");
- finish();
- return;
- }
-
- long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
- UnifiedKeyInfoViewModel viewModel = ViewModelProviders.of(this).get(UnifiedKeyInfoViewModel.class);
- viewModel.setMasterKeyId(masterKeyId);
- viewModel.getUnifiedKeyInfoLiveData(this).observe(this, this::onLoadUnifiedKeyInfo);
-
- hideKeyboard();
-
- // pass extras into fragment
- if (savedInstanceState == null) {
- LinkedIdSelectFragment frag = LinkedIdSelectFragment.newInstance();
- loadFragment(frag, FRAG_ACTION_START);
- }
- }
-
- private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
- if (!unifiedKeyInfo.has_any_secret()) {
- Timber.e("Linked Identities can only be added to secret keys!");
- finish();
- }
- }
-
- @Override
- protected void initLayout() {
- setContentView(R.layout.create_key_activity);
- }
-
- public void loadFragment(Fragment fragment, int action) {
- // Add the fragment to the 'fragment_container' FrameLayout
- // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-
- switch (action) {
- case FRAG_ACTION_START:
- transaction.setCustomAnimations(0, 0);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
- break;
- case FRAG_ACTION_TO_LEFT:
- getSupportFragmentManager().popBackStackImmediate();
- break;
- case FRAG_ACTION_TO_RIGHT:
- transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left,
- R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right);
- transaction.addToBackStack(null);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
- break;
-
- }
- getSupportFragmentManager().executePendingTransactions();
- }
-
- private void hideKeyboard() {
- InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-
- View v = getCurrentFocus();
- if (v == null || inputManager == null) {
- return;
- }
-
- inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
index 8dd09205e..b28385add 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -432,10 +432,6 @@ public class Preferences {
// experimental prefs
- public boolean getExperimentalEnableLinkedIdentities() {
- return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, false);
- }
-
public boolean getExperimentalEnableKeybase() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, false);
}
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png
deleted file mode 100644
index 41719efd6..000000000
Binary files a/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png
deleted file mode 100644
index 2a1ae67d7..000000000
Binary files a/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png
deleted file mode 100644
index 278fac4f8..000000000
Binary files a/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png
deleted file mode 100644
index dd0fce197..000000000
Binary files a/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png
deleted file mode 100644
index c6f3e9a06..000000000
Binary files a/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png
deleted file mode 100644
index ba3d2e4b7..000000000
Binary files a/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png
deleted file mode 100644
index 54b085aaf..000000000
Binary files a/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png
deleted file mode 100644
index 86ca9d46e..000000000
Binary files a/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png
deleted file mode 100644
index ec87cdd1c..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png
deleted file mode 100644
index 0934f1840..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png
deleted file mode 100644
index f627d2b3b..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png
deleted file mode 100644
index 35bb1fd3b..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png
deleted file mode 100644
index 9b3ee8572..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png
deleted file mode 100644
index 19a3421bf..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png
deleted file mode 100644
index c41ab6c1c..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png
deleted file mode 100644
index 0710a12f1..000000000
Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png and /dev/null differ
diff --git a/OpenKeychain/src/main/res/layout/identities_card.xml b/OpenKeychain/src/main/res/layout/identities_card.xml
index a970fd76b..2a5c84db9 100644
--- a/OpenKeychain/src/main/res/layout/identities_card.xml
+++ b/OpenKeychain/src/main/res/layout/identities_card.xml
@@ -18,30 +18,4 @@
android:layout_height="wrap_content"
android:layout_marginBottom="4dp" />
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml b/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml
deleted file mode 100644
index 7fa581905..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml
+++ /dev/null
@@ -1,235 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml
deleted file mode 100644
index 8b6047e21..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml
deleted file mode 100644
index dc6895a54..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml
deleted file mode 100644
index 848ee47f4..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml
deleted file mode 100644
index e66946482..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_verify.xml b/OpenKeychain/src/main/res/layout/linked_create_verify.xml
deleted file mode 100644
index 9f9dbcd97..000000000
--- a/OpenKeychain/src/main/res/layout/linked_create_verify.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_id_item.xml b/OpenKeychain/src/main/res/layout/linked_id_item.xml
deleted file mode 100644
index 0a9f8f7da..000000000
--- a/OpenKeychain/src/main/res/layout/linked_id_item.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
deleted file mode 100644
index c121cf295..000000000
--- a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
+++ /dev/null
@@ -1,193 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_select_fragment.xml b/OpenKeychain/src/main/res/layout/linked_select_fragment.xml
deleted file mode 100644
index a8d7b408b..000000000
--- a/OpenKeychain/src/main/res/layout/linked_select_fragment.xml
+++ /dev/null
@@ -1,188 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml b/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml
deleted file mode 100644
index 8d6e75cee..000000000
--- a/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index a2f96954f..1e52f30d8 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -1647,81 +1647,13 @@
"Fingerprints did not match!"
"Expiry date is in the past!"
- "By creating a Linked Identity of this type, you can link your key to a website you control."
- "To do this, you publish a text file on this website, then create a Linked Identity which links to it."
- "Please enter a URL where you are able to place a text file for proof. Note that your server must support https and have a valid TLS certificate!"
- "Example: https://example.com/pgpkey.txt"
- "The proof file has been created. For the next step, you should save and upload it to the URI you indicated:"
- "A proof file for this URI has been created:"
- "For the next step, you should save and upload this file."
- "Make sure the file is reachable at the correct URI, then verify your setup."
- "After successful verification, touch Finish button to add the Linked Identity to your keyring and finish the process."
-
- "By creating a Linked Identity of this type, you can link your key to a Twitter account you control."
- "To do this, you publish a specific Tweet on your timeline, then create a Linked Identity which links to this Tweet."
- "Please enter your Twitter screen name to proceed."
- Twitter Handle
- "Touch either button to tweet the message!"
- "You can edit the Tweet before posting it, so long as the text inside the brackets is unmodified."
- "Once your Tweet is published as @%s, touch the Verify button to scan your timeline for it."
- "After successful verification, touch Finish button to add the Linked Identity to your keyring and finish the process."
-
- "Verify"
- Text has been copied to clipboard
- "The link between this Website and key was securely verified. If you believe the Website is genuine, confirm this verification with your key."
- "The link between this GitHub account and key was securely verified. If you believe the account is genuine, confirm this verification with your key."
- "The link between this Domain Name and key was securely verified. If you believe the Domain is genuine, confirm this verification with your key."
- "The link between this Twitter account and key was securely verified. If you believe the account is genuine, confirm this verification with your key."
- "Everything looks in order."
- "Everything looks in order."
- "Everything looks in order."
- "Everything looks in order."
-
- "There is one more unknown identity type"
- "There are %d more unknown identity types"
- "A 'linked identity' connects your PGP key to a resource on the web."
- "Please select a type:"
- "This file claims ownership of the OpenPGP key with long id %2$s.\n\nToken for proof:\n%1$s"
- "This Gist confirms the Linked Identity in my OpenPGP key, and links it to this GitHub account.\n\nToken for proof:\n%1$s"
- "Verifying…"
- "Verified!"
- "Verification error!"
- "Not yet verified"
- The resource needs to be verified before you can proceed!
- "Link to Account"
- "Linked Identities"
"Finish"
- "Website (HTTPS)"
- "Domain Name (DNS)"
- "GitHub"
- "Twitter"
- "Linked Identity"
- "Verify"
- "Retry"
- "Retry last step"
- "Confirm"
- "View"
- "Verifying…"
- "Error"
- "Confirming…"
- "%d more unknown identity types"
- "Create Linked Identity"
- "This operation links your key to your GitHub account.\nJust touch the button to continue."
- "Authorize with GitHub…"
- "Post Gist…"
- "Update Key…"
- "Link to GitHub account"
- "Authorization failed!"
- "Connection timeout!"
- "Network error!"
- "Communication error: %s"
- "GitHub Authorization"
- "OpenKeychain Linked Identity"
- "Link your key to GitHub, Twitter or other websites!"
"Overwrite"
"The backup will be secured with a backup code. Write it down before you proceed!"
"Please enter the backup code:"
diff --git a/graphics/drawables/linked_dns.svg b/graphics/drawables/linked_dns.svg
deleted file mode 100644
index c04c265c2..000000000
--- a/graphics/drawables/linked_dns.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/graphics/drawables/linked_github.svg b/graphics/drawables/linked_github.svg
deleted file mode 100644
index 11f4076d5..000000000
--- a/graphics/drawables/linked_github.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/graphics/drawables/linked_https.svg b/graphics/drawables/linked_https.svg
deleted file mode 100644
index 876f46276..000000000
--- a/graphics/drawables/linked_https.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/graphics/drawables/linked_twitter.svg b/graphics/drawables/linked_twitter.svg
deleted file mode 100644
index 38028f2e9..000000000
--- a/graphics/drawables/linked_twitter.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/graphics/update-drawables.sh b/graphics/update-drawables.sh
index 6e28a57f0..42cc2cd2f 100755
--- a/graphics/update-drawables.sh
+++ b/graphics/update-drawables.sh
@@ -41,7 +41,7 @@ inkscape -w 192 -h 192 -e "$XDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
inkscape -w 256 -h 256 -e "$XXDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
done
-for NAME in "create_key_robot" "linked_dns" "linked_https" "linked_github" "linked_twitter" "account_key"
+for NAME in "create_key_robot" "account_key"
do
echo $NAME
inkscape -w 48 -h 48 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"