From 1f324be24316175a111b9424a22fc5fcb6104e2b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 5 Mar 2015 01:58:36 +0100 Subject: do a TON of UI work --- .../keychain/pgp/WrappedUserAttribute.java | 9 + .../keychain/pgp/linked/LinkedCookieResource.java | 100 ++-------- .../keychain/pgp/linked/LinkedIdentity.java | 75 ++++++++ .../keychain/pgp/linked/LinkedResource.java | 101 +++++++++++ .../keychain/pgp/linked/RawLinkedIdentity.java | 44 +---- .../keychain/pgp/linked/resources/DnsResource.java | 9 +- .../pgp/linked/resources/GenericHttpsResource.java | 2 +- .../pgp/linked/resources/TwitterResource.java | 2 +- .../keychain/provider/KeychainDatabase.java | 14 +- .../keychain/provider/KeychainProvider.java | 19 +- .../keychain/provider/ProviderHelper.java | 17 +- .../keychain/ui/ViewKeyActivity.java | 2 +- .../keychain/ui/ViewKeyFragment.java | 36 +++- .../keychain/ui/adapter/LinkedIdsAdapter.java | 201 +++++++++++++-------- .../keychain/ui/adapter/UserAttributesAdapter.java | 1 + .../ui/linked/LinkedIdCreateDnsStep1Fragment.java | 2 +- .../ui/linked/LinkedIdCreateDnsStep2Fragment.java | 8 +- .../linked/LinkedIdCreateHttpsStep1Fragment.java | 2 +- .../linked/LinkedIdCreateHttpsStep2Fragment.java | 7 +- .../linked/LinkedIdCreateTwitterStep1Fragment.java | 2 +- .../linked/LinkedIdCreateTwitterStep2Fragment.java | 4 +- .../keychain/ui/linked/LinkedIdViewFragment.java | 45 +++++ .../src/main/res/layout/linked_id_item_dns.xml | 63 +++++++ .../src/main/res/layout/linked_id_item_unknown.xml | 54 ++++++ .../main/res/layout/linked_id_view_fragment.xml | 94 ++++++++++ .../src/main/res/layout/view_key_fragment.xml | 1 + .../main/res/transition/linked_id_card_trans.xml | 4 + 27 files changed, 672 insertions(+), 246 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java create mode 100644 OpenKeychain/src/main/res/layout/linked_id_item_dns.xml create mode 100644 OpenKeychain/src/main/res/layout/linked_id_item_unknown.xml create mode 100644 OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml create mode 100644 OpenKeychain/src/main/res/transition/linked_id_card_trans.xml (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java index 8f967499e..49e4d9793 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java @@ -114,6 +114,15 @@ public class WrappedUserAttribute implements Serializable { } + public byte[][] getSubpackets() { + UserAttributeSubpacket[] subpackets = mVector.toSubpacketArray(); + byte[][] ret = new byte[subpackets.length][]; + for (int i = 0; i < subpackets.length; i++) { + ret[i] = subpackets[i].getData(); + } + return ret; + } + private void readObjectNoData() throws ObjectStreamException { } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java index 6228b29ec..fb3f2433a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java @@ -19,27 +19,10 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -public abstract class LinkedCookieResource { - - protected final URI mSubUri; - protected final Set mFlags; - protected final HashMap mParams; - - static Pattern magicPattern = - Pattern.compile("\\[Verifying my PGP key: openpgp4fpr:([a-zA-Z0-9]+)#([a-zA-Z0-9]+)\\]"); +public abstract class LinkedCookieResource extends LinkedResource { protected LinkedCookieResource(Set flags, HashMap params, URI uri) { - mFlags = flags; - mParams = params; - mSubUri = uri; - } - - public Set getFlags () { - return new HashSet(mFlags); - } - - public HashMap getParams () { - return new HashMap(mParams); + super(flags, params, uri); } public URI toUri () { @@ -82,10 +65,10 @@ public abstract class LinkedCookieResource { return mSubUri; } - public static String generate (Context context, byte[] fingerprint, String nonce) { + public static String generate (Context context, byte[] fingerprint, int nonce) { return "[Verifying my PGP key: openpgp4fpr:" - + KeyFormattingUtils.convertFingerprintToHex(fingerprint) + "#" + nonce + "]"; + + KeyFormattingUtils.convertFingerprintToHex(fingerprint) + "#" + Integer.toHexString(nonce) + "]"; } @@ -129,7 +112,17 @@ public abstract class LinkedCookieResource { } String candidateFp = match.group(1).toLowerCase(); - int nonceCandidate = Integer.parseInt(match.group(2).toLowerCase(), 16); + try { + int nonceCandidate = Integer.parseInt(match.group(2).toLowerCase(), 16); + + if (nonce != nonceCandidate) { + log.add(LogType.MSG_LV_NONCE_ERROR, indent); + return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log); + } + } catch (NumberFormatException e) { + log.add(LogType.MSG_LV_NONCE_ERROR, indent); + return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log); + } String fp = KeyFormattingUtils.convertFingerprintToHex(fingerprint); @@ -139,72 +132,9 @@ public abstract class LinkedCookieResource { } log.add(LogType.MSG_LV_FP_OK, indent); - if (nonce != nonceCandidate) { - log.add(LogType.MSG_LV_NONCE_ERROR, indent); - return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log); - } - log.add(LogType.MSG_LV_NONCE_OK, indent); return new LinkedVerifyResult(LinkedVerifyResult.RESULT_OK, log); } - protected static LinkedCookieResource fromRawLinkedId (RawLinkedIdentity id) { - return fromUri(id.mNonce, id.mUri); - } - - protected static LinkedCookieResource fromUri (int nonce, URI uri) { - - if ("pgpid".equals(uri.getScheme())) { - Log.e(Constants.TAG, "unknown uri scheme in (suspected) linked id packet"); - return null; - } - - if (!uri.isOpaque()) { - Log.e(Constants.TAG, "non-opaque uri in (suspected) linked id packet"); - return null; - } - - String specific = uri.getSchemeSpecificPart(); - if (!specific.contains("@")) { - Log.e(Constants.TAG, "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(); - { - 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(nonce, flags, params, subUri); - - } - - protected static LinkedCookieResource findResourceType (int nonce, Set flags, - HashMap params, - URI subUri) { - - LinkedCookieResource res; - - res = GenericHttpsResource.create(flags, params, subUri); - if (res != null) { - return res; - } - - return new UnknownResource(flags, params, subUri); - - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java new file mode 100644 index 000000000..f06a23681 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java @@ -0,0 +1,75 @@ +package org.sufficientlysecure.keychain.pgp.linked; + +import org.spongycastle.bcpg.UserAttributeSubpacket; +import org.spongycastle.util.Strings; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; +import org.sufficientlysecure.keychain.util.Log; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.Arrays; + +public class LinkedIdentity extends RawLinkedIdentity { + + public final LinkedResource mResource; + + protected LinkedIdentity(int nonce, URI uri, LinkedResource resource) { + super(nonce, uri); + if (resource == null) { + throw new AssertionError("resource must not be null in a LinkedIdentity!"); + } + mResource = resource; + } + + public static RawLinkedIdentity 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"); + } + + /** This method parses a linked id from a UserAttributeSubpacket, or returns null if the + * subpacket can not be parsed as a valid linked id. + */ + static RawLinkedIdentity fromAttributeSubpacket(UserAttributeSubpacket subpacket) { + if (subpacket.getType() != 100) { + return null; + } + + byte[] data = subpacket.getData(); + + return fromSubpacketData(data); + + } + + static RawLinkedIdentity fromSubpacketData(byte[] data) { + + try { + int nonce = ByteBuffer.wrap(data).getInt(); + String uriStr = Strings.fromUTF8ByteArray(Arrays.copyOfRange(data, 4, data.length)); + URI uri = URI.create(uriStr); + + LinkedResource res = LinkedResource.fromUri(uri); + if (res == null) { + return new RawLinkedIdentity(nonce, uri); + } + + return new LinkedIdentity(nonce, uri, res); + + } catch (IllegalArgumentException e) { + Log.e(Constants.TAG, "error parsing uri in (suspected) linked id packet"); + return null; + } + } + + public static RawLinkedIdentity fromResource (LinkedCookieResource res, int nonce) { + return new RawLinkedIdentity(nonce, res.toUri()); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java new file mode 100644 index 000000000..6077db606 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java @@ -0,0 +1,101 @@ +package org.sufficientlysecure.keychain.pgp.linked; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.linked.resources.DnsResource; +import org.sufficientlysecure.keychain.pgp.linked.resources.GenericHttpsResource; +import org.sufficientlysecure.keychain.pgp.linked.resources.UnknownResource; +import org.sufficientlysecure.keychain.util.Log; + +import java.net.URI; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +public abstract class LinkedResource { + + protected final URI mSubUri; + protected final Set mFlags; + protected final HashMap mParams; + + static Pattern magicPattern = + Pattern.compile("\\[Verifying my PGP key: openpgp4fpr:([a-zA-Z0-9]+)#([a-zA-Z0-9]+)\\]"); + + protected LinkedResource(Set flags, HashMap params, URI uri) { + mFlags = flags; + mParams = params; + mSubUri = uri; + } + + public abstract URI toUri(); + + public Set getFlags () { + return new HashSet<>(mFlags); + } + + public HashMap getParams () { + return new HashMap<>(mParams); + } + + protected static LinkedCookieResource fromUri (URI uri) { + + if ("pgpid+cookie".equals(uri.getScheme())) { + Log.e(Constants.TAG, "unknown uri scheme in (suspected) linked id packet"); + return null; + } + + if (!uri.isOpaque()) { + Log.e(Constants.TAG, "non-opaque uri in (suspected) linked id packet"); + return null; + } + + String specific = uri.getSchemeSpecificPart(); + if (!specific.contains("@")) { + Log.e(Constants.TAG, "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(); + { + String[] rawParams = pieces[0].split(";"); + for (String param : rawParams) { + String[] p = param.split("=", 2); + if ("".equals(p[0])) { + continue; + } + if (p.length == 1) { + flags.add(param); + } else { + params.put(p[0], p[1]); + } + } + } + + return findResourceType(flags, params, subUri); + + } + + protected static LinkedCookieResource findResourceType (Set flags, + HashMap params, + URI subUri) { + + LinkedCookieResource res; + + res = GenericHttpsResource.create(flags, params, subUri); + if (res != null) { + return res; + } + res = DnsResource.create(flags, params, subUri); + if (res != null) { + return res; + } + + return null; + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java index 931f2ec6b..bfde3c3b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java @@ -1,18 +1,10 @@ package org.sufficientlysecure.keychain.pgp.linked; -import org.spongycastle.bcpg.UserAttributeSubpacket; import org.spongycastle.util.Strings; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; -import org.sufficientlysecure.keychain.util.Log; import java.net.URI; import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map.Entry; -import java.util.Set; /** The RawLinkedIdentity contains raw parsed data from a Linked Identity subpacket. */ public class RawLinkedIdentity { @@ -36,50 +28,18 @@ public class RawLinkedIdentity { return buf.array(); } - /** This method parses a linked id from a UserAttributeSubpacket, or returns null if the - * subpacket can not be parsed as a valid linked id. - */ - static RawLinkedIdentity fromAttributeSubpacket(UserAttributeSubpacket subpacket) { - if (subpacket.getType() != 100) { - return null; - } - - byte[] data = subpacket.getData(); - - return fromSubpacketData(data); - - } - - public static RawLinkedIdentity fromSubpacketData(byte[] data) { - - try { - int nonce = ByteBuffer.wrap(data).getInt(); - String uri = Strings.fromUTF8ByteArray(Arrays.copyOfRange(data, 4, data.length)); - - return new RawLinkedIdentity(nonce, URI.create(uri)); - - } catch (IllegalArgumentException e) { - Log.e(Constants.TAG, "error parsing uri in (suspected) linked id packet"); - return null; - } - } - - public static RawLinkedIdentity fromResource (LinkedCookieResource res, int nonce) { - return new RawLinkedIdentity(nonce, res.toUri()); - } - public WrappedUserAttribute toUserAttribute () { return WrappedUserAttribute.fromSubpacket(WrappedUserAttribute.UAT_LINKED_ID, getEncoded()); } - public static String generateNonce() { + public static int generateNonce() { // TODO make this actually random // byte[] data = new byte[4]; // new SecureRandom().nextBytes(data); // return Hex.toHexString(data); // debug for now - return "01234567"; + return 1234567; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java index 796e2f120..5df008ed7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java @@ -39,10 +39,11 @@ public class DnsResource extends LinkedCookieResource { mType = type; } - public static String generateText (Context context, byte[] fingerprint, String nonce) { + public static String generateText (Context context, byte[] fingerprint, int nonce) { return "pgpid+cookie=" - + KeyFormattingUtils.convertFingerprintToHex(fingerprint) + ";" + nonce + ""; + + KeyFormattingUtils.convertFingerprintToHex(fingerprint) + ";" + + Integer.toHexString(nonce) + ""; } @@ -81,6 +82,10 @@ public class DnsResource extends LinkedCookieResource { return new DnsResource(flags, params, uri, fqdn, clazz, type); } + public String getFqdn() { + return mFqdn; + } + @Override protected String fetchResource (OperationLog log, int indent) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java index a0f1cf0aa..ba94bae75 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java @@ -28,7 +28,7 @@ public class GenericHttpsResource extends LinkedCookieResource { super(flags, params, uri); } - public static String generateText (Context context, byte[] fingerprint, String nonce) { + public static String generateText (Context context, byte[] fingerprint, int nonce) { String cookie = LinkedCookieResource.generate(context, fingerprint, nonce); return String.format(context.getResources().getString(R.string.linked_id_generic_text), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java index 84277380d..f6ec4f97a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java @@ -35,7 +35,7 @@ public class TwitterResource extends LinkedCookieResource { super(flags, params, uri); } - public static String generateText (Context context, byte[] fingerprint, String nonce) { + public static String generateText (Context context, byte[] fingerprint, int nonce) { // nothing special here for now, might change this later return LinkedCookieResource.generate(context, fingerprint, nonce); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index b88cd6006..4a162989f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -53,7 +53,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 8; + private static final int DATABASE_VERSION = 9; static Boolean apgHack = false; private Context mContext; @@ -61,7 +61,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String KEY_RINGS_PUBLIC = "keyrings_public"; String KEY_RINGS_SECRET = "keyrings_secret"; String KEYS = "keys"; - String USER_PACKETS = "user_ids"; + String USER_PACKETS = "user_packets"; String CERTS = "certs"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; @@ -119,8 +119,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + UserPacketsColumns.IS_REVOKED + " INTEGER, " + UserPacketsColumns.RANK+ " INTEGER, " - + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.USER_ID + "), " - + "UNIQUE (" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + "FOREIGN KEY(" + UserPacketsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; @@ -267,6 +266,13 @@ public class KeychainDatabase extends SQLiteOpenHelper { } catch (Exception e) { // never mind, the column probably already existed } + case 9: + // tbale name for user_ids changed to user_packets + db.execSQL("DROP TABLE IF EXISTS certs"); + db.execSQL("DROP TABLE IF EXISTS user_ids"); + db.execSQL(CREATE_USER_PACKETS); + db.execSQL(CREATE_CERTS); + } // always do consolidate after upgrade diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 3aa156a8e..31ed89d67 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -62,6 +62,7 @@ public class KeychainProvider extends ContentProvider { private static final int KEY_RING_SECRET = 204; private static final int KEY_RING_CERTS = 205; private static final int KEY_RING_CERTS_SPECIFIC = 206; + private static final int KEY_RING_LINKED_IDS = 207; private static final int API_APPS = 301; private static final int API_APPS_BY_PACKAGE_NAME = 302; @@ -127,6 +128,7 @@ public class KeychainProvider extends ContentProvider { * key_rings/_/unified * key_rings/_/keys * key_rings/_/user_ids + * key_rings/_/linked_ids * key_rings/_/public * key_rings/_/secret * key_rings/_/certs @@ -142,6 +144,9 @@ public class KeychainProvider extends ContentProvider { matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + KeychainContract.PATH_USER_IDS, KEY_RING_USER_IDS); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + + KeychainContract.PATH_LINKED_IDS, + KEY_RING_LINKED_IDS); matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + KeychainContract.PATH_PUBLIC, KEY_RING_PUBLIC); @@ -469,7 +474,8 @@ public class KeychainProvider extends ContentProvider { } case KEY_RINGS_USER_IDS: - case KEY_RING_USER_IDS: { + case KEY_RING_USER_IDS: + case KEY_RING_LINKED_IDS: { HashMap projectionMap = new HashMap<>(); projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); @@ -494,13 +500,14 @@ public class KeychainProvider extends ContentProvider { groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + ", " + Tables.USER_PACKETS + "." + UserPackets.RANK; - // for now, we only respect user ids here, so TYPE must be NULL - // TODO expand with KEY_RING_USER_PACKETS query type which lifts this restriction - qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"); + if (match == KEY_RING_LINKED_IDS) { + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " = 100"); + } else { + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"); + } // If we are searching for a particular keyring's ids, add where - if (match == KEY_RING_USER_IDS) { - // TODO remove with the thing above + if (match == KEY_RING_USER_IDS || match == KEY_RING_LINKED_IDS) { qb.appendWhere(" AND "); qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(1)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 8a9f36c03..2ff4803fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1082,9 +1082,8 @@ public class ProviderHelper { log.add(LogType.MSG_CON_SAVE_SECRET, indent); indent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ - KeyRings.PRIVKEY_DATA, KeyRings.FINGERPRINT, KeyRings.HAS_ANY_SECRET - }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); + final Cursor cursor = mContentResolver.query(KeyRingData.buildSecretKeyRingUri(), + new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1106,8 +1105,7 @@ public class ProviderHelper { if (cursor.isAfterLast()) { return false; } - ring = new ParcelableKeyRing(KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1)), cursor.getBlob(0) - ); + ring = new ParcelableKeyRing(cursor.getBlob(0)); cursor.moveToNext(); return true; } @@ -1144,9 +1142,9 @@ public class ProviderHelper { log.add(LogType.MSG_CON_SAVE_PUBLIC, indent); indent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ - KeyRings.PUBKEY_DATA, KeyRings.FINGERPRINT - }, null, null, null); + final Cursor cursor = mContentResolver.query( + KeyRingData.buildPublicKeyRingUri(), + new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1168,8 +1166,7 @@ public class ProviderHelper { if (cursor.isAfterLast()) { return false; } - ring = new ParcelableKeyRing(KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1)), cursor.getBlob(0) - ); + ring = new ParcelableKeyRing(cursor.getBlob(0)); cursor.moveToNext(); return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 6b1d87941..51dec767c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -281,7 +281,7 @@ public class ViewKeyActivity extends BaseActivity implements // Add the fragment to the 'fragment_container' FrameLayout // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! getSupportFragmentManager().beginTransaction() - .replace(R.id.view_key_fragment, frag) + .replace(R.id.view_key_fragment, frag, "main") .commitAllowingStateLoss(); // do it immediately! getSupportFragmentManager().executePendingTransactions(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index c6df016ff..20386b372 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -20,15 +20,22 @@ package org.sufficientlysecure.keychain.ui; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.widget.CardView; +import android.transition.Explode; +import android.transition.Fade; +import android.transition.Transition; +import android.transition.TransitionInflater; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; @@ -91,11 +98,34 @@ public class ViewKeyFragment extends LoaderFragment implements showUserIdInfo(position); } }); - mLinkedIdsCard.setVisibility(View.GONE); + mLinkedIds.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + showLinkedId(position); + } + }); return root; } + private void showLinkedId(final int position) { + Fragment frag = mLinkedIdsAdapter.getLinkedIdFragment(position); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Transition trans = TransitionInflater.from(getActivity()) + .inflateTransition(R.transition.linked_id_card_trans); + // setSharedElementReturnTransition(trans); + setExitTransition(new Fade()); + frag.setSharedElementEnterTransition(trans); + } + + getFragmentManager().beginTransaction() + .replace(R.id.view_key_fragment, frag) + .addSharedElement(mLinkedIdsCard, "card_linked_ids") + .addToBackStack(null) + .commit(); + } + private void showUserIdInfo(final int position) { if (!mIsSecret) { final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); @@ -140,10 +170,8 @@ public class ViewKeyFragment extends LoaderFragment implements Log.i(Constants.TAG, "mDataUri: " + mDataUri); - // Prepare the loaders. Either re-connect with an existing ones, - // or start new ones. - // TODO Is this loader the same as the one in the activity? getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); + getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); } public Loader onCreateLoader(int id, Bundle args) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java index 1e4968615..a44358172 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java @@ -21,131 +21,130 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.app.Activity; import android.content.Context; import android.database.Cursor; -import android.graphics.Typeface; import android.net.Uri; +import android.support.v4.app.Fragment; import android.support.v4.content.CursorLoader; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.linked.LinkedIdentity; +import org.sufficientlysecure.keychain.pgp.linked.LinkedResource; import org.sufficientlysecure.keychain.pgp.linked.RawLinkedIdentity; +import org.sufficientlysecure.keychain.pgp.linked.resources.DnsResource; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.ui.ViewKeyFragment; +import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import java.io.IOException; +import java.util.WeakHashMap; + + public class LinkedIdsAdapter extends UserAttributesAdapter { protected LayoutInflater mInflater; + WeakHashMap mLinkedIdentityCache = new WeakHashMap<>(); public LinkedIdsAdapter(Context context, Cursor c, int flags) { super(context, c, flags); mInflater = LayoutInflater.from(context); } + @Override + public void bindView(View view, Context context, Cursor cursor) { + + RawLinkedIdentity id = getItem(cursor.getPosition()); + ViewHolder holder = (ViewHolder) view.getTag(); + + int isVerified = cursor.getInt(INDEX_VERIFIED); + switch (isVerified) { + case Certs.VERIFIED_SECRET: + KeyFormattingUtils.setStatusImage(mContext, holder.vVerified, + null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); + break; + case Certs.VERIFIED_SELF: + KeyFormattingUtils.setStatusImage(mContext, holder.vVerified, + null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR); + break; + default: + KeyFormattingUtils.setStatusImage(mContext, holder.vVerified, + null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR); + break; + } + + if (holder instanceof ViewHolderNonRaw) { + ((ViewHolderNonRaw) holder).setData(mContext, (LinkedIdentity) id); + } + + } + @Override public int getItemViewType(int position) { - RawLinkedIdentity id = (RawLinkedIdentity) getItem(position); + RawLinkedIdentity id = getItem(position); - // TODO return different ids by type + if (id instanceof LinkedIdentity) { + LinkedResource res = ((LinkedIdentity) id).mResource; + if (res instanceof DnsResource) { + return 1; + } + } return 0; } @Override public int getViewTypeCount() { - return 1; + return 2; } @Override - public Object getItem(int position) { + public RawLinkedIdentity getItem(int position) { + RawLinkedIdentity ret = mLinkedIdentityCache.get(position); + if (ret != null) { + return ret; + } + Cursor c = getCursor(); c.moveToPosition(position); byte[] data = c.getBlob(INDEX_ATTRIBUTE_DATA); - RawLinkedIdentity identity = RawLinkedIdentity.fromSubpacketData(data); - - return identity; + try { + ret = LinkedIdentity.fromAttributeData(data); + mLinkedIdentityCache.put(position, ret); + return ret; + } catch (IOException e) { + Log.e(Constants.TAG, "could not read linked identity subpacket data", e); + return null; + } } @Override - public void bindView(View view, Context context, Cursor cursor) { - TextView vName = (TextView) view.findViewById(R.id.user_id_item_name); - TextView vAddress = (TextView) view.findViewById(R.id.user_id_item_address); - TextView vComment = (TextView) view.findViewById(R.id.user_id_item_comment); - ImageView vVerified = (ImageView) view.findViewById(R.id.user_id_item_certified); - View vVerifiedLayout = view.findViewById(R.id.user_id_item_certified_layout); - ImageView vEditImage = (ImageView) view.findViewById(R.id.user_id_item_edit_image); - ImageView vDeleteButton = (ImageView) view.findViewById(R.id.user_id_item_delete_button); - vDeleteButton.setVisibility(View.GONE); // not used - - String userId = cursor.getString(INDEX_USER_ID); - String[] splitUserId = KeyRing.splitUserId(userId); - if (splitUserId[0] != null) { - vName.setText(splitUserId[0]); - } else { - vName.setText(R.string.user_id_no_name); - } - if (splitUserId[1] != null) { - vAddress.setText(splitUserId[1]); - vAddress.setVisibility(View.VISIBLE); - } else { - vAddress.setVisibility(View.GONE); - } - if (splitUserId[2] != null) { - vComment.setText(splitUserId[2]); - vComment.setVisibility(View.VISIBLE); - } else { - vComment.setVisibility(View.GONE); - } - - boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0; - boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; - vVerifiedLayout.setVisibility(View.VISIBLE); - - if (isRevoked) { - // set revocation icon (can this even be primary?) - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray); - - // disable revoked user ids - vName.setEnabled(false); - vAddress.setEnabled(false); - vComment.setEnabled(false); - } else { - vName.setEnabled(true); - vAddress.setEnabled(true); - vComment.setEnabled(true); - - if (isPrimary) { - vName.setTypeface(null, Typeface.BOLD); - vAddress.setTypeface(null, Typeface.BOLD); - } else { - vName.setTypeface(null, Typeface.NORMAL); - vAddress.setTypeface(null, Typeface.NORMAL); + public View newView(Context context, Cursor cursor, ViewGroup parent) { + int type = getItemViewType(cursor.getPosition()); + switch(type) { + case 0: { + View v = mInflater.inflate(R.layout.linked_id_item_unknown, null); + ViewHolder holder = new ViewHolder(v); + v.setTag(holder); + return v; } - - int isVerified = cursor.getInt(INDEX_VERIFIED); - switch (isVerified) { - case Certs.VERIFIED_SECRET: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); - break; - case Certs.VERIFIED_SELF: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR); - break; - default: - KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR); - break; + case 1: { + View v = mInflater.inflate(R.layout.linked_id_item_dns, null); + ViewHolder holder = new ViewHolderDns(v); + v.setTag(holder); + return v; } + default: + throw new AssertionError("all cases must be covered in LinkedIdsAdapter.newView!"); } } - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return mInflater.inflate(R.layout.view_key_adv_user_id_item, null); - } - // don't show revoked user ids, irrelevant for average users public static final String LINKED_IDS_WHERE = UserPackets.IS_REVOKED + " = 0"; @@ -155,4 +154,48 @@ public class LinkedIdsAdapter extends UserAttributesAdapter { UserIdsAdapter.USER_PACKETS_PROJECTION, LINKED_IDS_WHERE, null, null); } + public Fragment getLinkedIdFragment(int position) { + RawLinkedIdentity id = getItem(position); + + return LinkedIdViewFragment.newInstance(id); + } + + static class ViewHolder { + ImageView vVerified; + + ViewHolder(View view) { + vVerified = (ImageView) view.findViewById(R.id.user_id_item_certified); + } + } + + static abstract class ViewHolderNonRaw extends ViewHolder { + ViewHolderNonRaw(View view) { + super(view); + } + + abstract void setData(Context context, LinkedIdentity id); + } + + static class ViewHolderDns extends ViewHolderNonRaw { + TextView vFqdn; + + ViewHolderDns(View view) { + super(view); + + vFqdn = (TextView) view.findViewById(R.id.linked_id_dns_fqdn); + } + + @Override + void setData(Context context, LinkedIdentity id) { + DnsResource res = (DnsResource) id.mResource; + vFqdn.setText(res.getFqdn()); + } + + } + + @Override + public void notifyDataSetChanged() { + mLinkedIdentityCache.clear(); + super.notifyDataSetChanged(); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java index 3bc1b200b..345ccccc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java @@ -48,4 +48,5 @@ public abstract class UserAttributesAdapter extends CursorAdapter { mCursor.moveToPosition(position); return mCursor.getInt(INDEX_VERIFIED); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep1Fragment.java index 14d5f3b5d..26b0a0539 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep1Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep1Fragment.java @@ -73,7 +73,7 @@ public class LinkedIdCreateDnsStep1Fragment extends Fragment { return; } - String proofNonce = RawLinkedIdentity.generateNonce(); + int proofNonce = RawLinkedIdentity.generateNonce(); String proofText = DnsResource.generateText(getActivity(), mLinkedIdWizard.mFingerprint, proofNonce); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java index 6c9110ffd..71a3673f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java @@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; +import org.sufficientlysecure.keychain.pgp.linked.LinkedIdentity; import org.sufficientlysecure.keychain.pgp.linked.RawLinkedIdentity; import org.sufficientlysecure.keychain.pgp.linked.resources.DnsResource; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -80,13 +81,13 @@ public class LinkedIdCreateDnsStep2Fragment extends Fragment { * Creates new instance of this fragment */ public static LinkedIdCreateDnsStep2Fragment newInstance - (String uri, String proofNonce, String proofText) { + (String uri, int proofNonce, String proofText) { LinkedIdCreateDnsStep2Fragment frag = new LinkedIdCreateDnsStep2Fragment(); Bundle args = new Bundle(); args.putString(DOMAIN, uri); - args.putString(NONCE, proofNonce); + args.putInt(NONCE, proofNonce); args.putString(TEXT, proofText); frag.setArguments(args); @@ -237,6 +238,7 @@ public class LinkedIdCreateDnsStep2Fragment extends Fragment { mVerifiedResource = resource; } else { setVerifyProgress(false, false); + mVerifiedResource = resource; // on error, show error message result.createNotify(getActivity()).show(); } @@ -308,7 +310,7 @@ public class LinkedIdCreateDnsStep2Fragment extends Fragment { new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint); WrappedUserAttribute ua = - RawLinkedIdentity.fromResource(mVerifiedResource, mResourceNonce).toUserAttribute(); + LinkedIdentity.fromResource(mVerifiedResource, mResourceNonce).toUserAttribute(); skp.mAddUserAttribute.add(ua); 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 index 9fe1d43a3..78ca4cfe9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java @@ -72,7 +72,7 @@ public class LinkedIdCreateHttpsStep1Fragment extends Fragment { return; } - String proofNonce = RawLinkedIdentity.generateNonce(); + int proofNonce = RawLinkedIdentity.generateNonce(); String proofText = GenericHttpsResource.generateText(getActivity(), mLinkedIdWizard.mFingerprint, proofNonce); 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 index f3fcc4410..78c7caf53 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java @@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; +import org.sufficientlysecure.keychain.pgp.linked.LinkedIdentity; import org.sufficientlysecure.keychain.pgp.linked.RawLinkedIdentity; import org.sufficientlysecure.keychain.pgp.linked.resources.GenericHttpsResource; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -83,13 +84,13 @@ public class LinkedIdCreateHttpsStep2Fragment extends Fragment { * Creates new instance of this fragment */ public static LinkedIdCreateHttpsStep2Fragment newInstance - (String uri, String proofNonce, String proofText) { + (String uri, int proofNonce, String proofText) { LinkedIdCreateHttpsStep2Fragment frag = new LinkedIdCreateHttpsStep2Fragment(); Bundle args = new Bundle(); args.putString(URI, uri); - args.putString(NONCE, proofNonce); + args.putInt(NONCE, proofNonce); args.putString(TEXT, proofText); frag.setArguments(args); @@ -315,7 +316,7 @@ public class LinkedIdCreateHttpsStep2Fragment extends Fragment { new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint); WrappedUserAttribute ua = - RawLinkedIdentity.fromResource(mVerifiedResource, mResourceNonce).toUserAttribute(); + LinkedIdentity.fromResource(mVerifiedResource, mResourceNonce).toUserAttribute(); skp.mAddUserAttribute.add(ua); 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 index 8113525be..e966fd71f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java @@ -92,7 +92,7 @@ public class LinkedIdCreateTwitterStep1Fragment extends Fragment { return; } - String proofNonce = RawLinkedIdentity.generateNonce(); + int proofNonce = RawLinkedIdentity.generateNonce(); String proofText = TwitterResource.generateText(getActivity(), mLinkedIdWizard.mFingerprint, proofNonce); 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 index ab56e7a5d..837b84d40 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java @@ -52,13 +52,13 @@ public class LinkedIdCreateTwitterStep2Fragment extends Fragment { * Creates new instance of this fragment */ public static LinkedIdCreateTwitterStep2Fragment newInstance - (String handle, String proofNonce, String proofText) { + (String handle, int proofNonce, String proofText) { LinkedIdCreateTwitterStep2Fragment frag = new LinkedIdCreateTwitterStep2Fragment(); Bundle args = new Bundle(); args.putString(HANDLE, handle); - args.putString(NONCE, proofNonce); + args.putInt(NONCE, proofNonce); args.putString(TEXT, proofText); frag.setArguments(args); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java new file mode 100644 index 000000000..0eb0dcd45 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java @@ -0,0 +1,45 @@ +package org.sufficientlysecure.keychain.ui.linked; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.widget.CardView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.linked.RawLinkedIdentity; + + +public class LinkedIdViewFragment extends Fragment { + + private CardView mLinkedIdsCard; + + public static Fragment newInstance(RawLinkedIdentity id) { + LinkedIdViewFragment frag = new LinkedIdViewFragment(); + + Bundle args = new Bundle(); + frag.setArguments(args); + + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.linked_id_view_fragment, null); + + mLinkedIdsCard = (CardView) root.findViewById(R.id.card_linked_ids); + + root.findViewById(R.id.back_button).setClickable(true); + root.findViewById(R.id.back_button).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + getFragmentManager().popBackStack(); + } + }); + + return root; + } + +} diff --git a/OpenKeychain/src/main/res/layout/linked_id_item_dns.xml b/OpenKeychain/src/main/res/layout/linked_id_item_dns.xml new file mode 100644 index 000000000..36b40f30d --- /dev/null +++ b/OpenKeychain/src/main/res/layout/linked_id_item_dns.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/layout/linked_id_item_unknown.xml b/OpenKeychain/src/main/res/layout/linked_id_item_unknown.xml new file mode 100644 index 000000000..dcd46884d --- /dev/null +++ b/OpenKeychain/src/main/res/layout/linked_id_item_unknown.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml new file mode 100644 index 000000000..c260a35d3 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + +