New key flags icons, subkey adapter redesign, support authanticate flag in database
@@ -43,6 +43,7 @@ public class KeychainContract {
|
||||
String CAN_SIGN = "can_sign";
|
||||
String CAN_ENCRYPT = "can_encrypt";
|
||||
String CAN_CERTIFY = "can_certify";
|
||||
String CAN_AUTHENTICATE = "can_authenticate";
|
||||
String IS_REVOKED = "is_revoked";
|
||||
String HAS_SECRET = "has_secret";
|
||||
|
||||
@@ -114,6 +115,7 @@ public class KeychainContract {
|
||||
public static final String HAS_ENCRYPT = "has_encrypt";
|
||||
public static final String HAS_SIGN = "has_sign";
|
||||
public static final String HAS_CERTIFY = "has_certify";
|
||||
public static final String HAS_AUTHENTICATE = "has_authenticate";
|
||||
public static final String PUBKEY_DATA = "pubkey_data";
|
||||
public static final String PRIVKEY_DATA = "privkey_data";
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ import java.io.IOException;
|
||||
*/
|
||||
public class KeychainDatabase extends SQLiteOpenHelper {
|
||||
private static final String DATABASE_NAME = "openkeychain.db";
|
||||
private static final int DATABASE_VERSION = 4;
|
||||
private static final int DATABASE_VERSION = 5;
|
||||
static Boolean apgHack = false;
|
||||
private Context mContext;
|
||||
|
||||
@@ -96,6 +96,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
||||
+ KeysColumns.CAN_CERTIFY + " BOOLEAN, "
|
||||
+ KeysColumns.CAN_SIGN + " BOOLEAN, "
|
||||
+ KeysColumns.CAN_ENCRYPT + " BOOLEAN, "
|
||||
+ KeysColumns.CAN_AUTHENTICATE + " BOOLEAN, "
|
||||
+ KeysColumns.IS_REVOKED + " BOOLEAN, "
|
||||
+ KeysColumns.HAS_SECRET + " BOOLEAN, "
|
||||
|
||||
@@ -214,21 +215,28 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
||||
// add has_secret for all who are upgrading from a beta version
|
||||
try {
|
||||
db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN");
|
||||
} catch(Exception e){
|
||||
} catch (Exception e){
|
||||
// never mind, the column probably already existed
|
||||
}
|
||||
// fall through
|
||||
case 2:
|
||||
// ECC support
|
||||
try {
|
||||
db.execSQL("ALTER TABLE keys ADD COLUMN " + KeysColumns.KEY_CURVE_OID + " TEXT");
|
||||
} catch(Exception e){
|
||||
db.execSQL("ALTER TABLE keys ADD COLUMN key_curve_oid TEXT");
|
||||
} catch (Exception e){
|
||||
// never mind, the column probably already existed
|
||||
}
|
||||
// fall through
|
||||
case 3:
|
||||
// better s2k detection, we need consolidate
|
||||
// fall through
|
||||
case 4:
|
||||
try {
|
||||
db.execSQL("ALTER TABLE keys ADD COLUMN can_authenticate BOOLEAN");
|
||||
} catch (Exception e){
|
||||
// never mind, the column probably already existed
|
||||
}
|
||||
// fall through
|
||||
}
|
||||
|
||||
// always do consolidate after upgrade
|
||||
|
||||
@@ -251,6 +251,7 @@ public class KeychainProvider extends ContentProvider {
|
||||
projectionMap.put(KeyRings.CAN_CERTIFY, Tables.KEYS + "." + Keys.CAN_CERTIFY);
|
||||
projectionMap.put(KeyRings.CAN_ENCRYPT, Tables.KEYS + "." + Keys.CAN_ENCRYPT);
|
||||
projectionMap.put(KeyRings.CAN_SIGN, Tables.KEYS + "." + Keys.CAN_SIGN);
|
||||
projectionMap.put(KeyRings.CAN_AUTHENTICATE, Tables.KEYS + "." + Keys.CAN_AUTHENTICATE);
|
||||
projectionMap.put(KeyRings.CREATION, Tables.KEYS + "." + Keys.CREATION);
|
||||
projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY);
|
||||
projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM);
|
||||
@@ -333,6 +334,16 @@ public class KeychainProvider extends ContentProvider {
|
||||
+ " AND ( kS." + Keys.EXPIRY + " IS NULL OR kS." + Keys.EXPIRY
|
||||
+ " >= " + new Date().getTime() / 1000 + " )"
|
||||
+ ")" : "")
|
||||
+ (plist.contains(KeyRings.HAS_AUTHENTICATE) ?
|
||||
" LEFT JOIN " + Tables.KEYS + " AS kS ON ("
|
||||
+"kS." + Keys.MASTER_KEY_ID
|
||||
+ " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||
+ " AND kS." + Keys.IS_REVOKED + " = 0"
|
||||
+ " AND kS." + Keys.CAN_AUTHENTICATE + " = 1"
|
||||
+ " AND kS." + Keys.HAS_SECRET + " > 1"
|
||||
+ " AND ( kS." + Keys.EXPIRY + " IS NULL OR kS." + Keys.EXPIRY
|
||||
+ " >= " + new Date().getTime() / 1000 + " )"
|
||||
+ ")" : "")
|
||||
+ (plist.contains(KeyRings.HAS_CERTIFY) ?
|
||||
" LEFT JOIN " + Tables.KEYS + " AS kC ON ("
|
||||
+"kC." + Keys.MASTER_KEY_ID
|
||||
@@ -424,6 +435,7 @@ public class KeychainProvider extends ContentProvider {
|
||||
projectionMap.put(Keys.CAN_CERTIFY, Keys.CAN_CERTIFY);
|
||||
projectionMap.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT);
|
||||
projectionMap.put(Keys.CAN_SIGN, Keys.CAN_SIGN);
|
||||
projectionMap.put(Keys.CAN_AUTHENTICATE, Keys.CAN_AUTHENTICATE);
|
||||
projectionMap.put(Keys.HAS_SECRET, Keys.HAS_SECRET);
|
||||
projectionMap.put(Keys.CREATION, Keys.CREATION);
|
||||
projectionMap.put(Keys.EXPIRY, Keys.EXPIRY);
|
||||
|
||||
@@ -356,10 +356,11 @@ public class ProviderHelper {
|
||||
values.put(Keys.ALGORITHM, key.getAlgorithm());
|
||||
values.put(Keys.FINGERPRINT, key.getFingerprint());
|
||||
|
||||
boolean c = key.canCertify(), e = key.canEncrypt(), s = key.canSign();
|
||||
boolean c = key.canCertify(), e = key.canEncrypt(), s = key.canSign(), a = key.canAuthenticate();
|
||||
values.put(Keys.CAN_CERTIFY, c);
|
||||
values.put(Keys.CAN_ENCRYPT, e);
|
||||
values.put(Keys.CAN_SIGN, s);
|
||||
values.put(Keys.CAN_AUTHENTICATE, a);
|
||||
values.put(Keys.IS_REVOKED, key.isRevoked());
|
||||
if (masterKeyId == keyId) {
|
||||
if (c) {
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.text.Spannable;
|
||||
@@ -62,6 +63,7 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
Keys.CAN_CERTIFY,
|
||||
Keys.CAN_ENCRYPT,
|
||||
Keys.CAN_SIGN,
|
||||
Keys.CAN_AUTHENTICATE,
|
||||
Keys.IS_REVOKED,
|
||||
Keys.CREATION,
|
||||
Keys.EXPIRY,
|
||||
@@ -77,10 +79,11 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
private static final int INDEX_CAN_CERTIFY = 7;
|
||||
private static final int INDEX_CAN_ENCRYPT = 8;
|
||||
private static final int INDEX_CAN_SIGN = 9;
|
||||
private static final int INDEX_IS_REVOKED = 10;
|
||||
private static final int INDEX_CREATION = 11;
|
||||
private static final int INDEX_EXPIRY = 12;
|
||||
private static final int INDEX_FINGERPRINT = 13;
|
||||
private static final int INDEX_CAN_AUTHENTICATE = 10;
|
||||
private static final int INDEX_IS_REVOKED = 11;
|
||||
private static final int INDEX_CREATION = 12;
|
||||
private static final int INDEX_EXPIRY = 13;
|
||||
private static final int INDEX_FINGERPRINT = 14;
|
||||
|
||||
public SubkeysAdapter(Context context, Cursor c, int flags,
|
||||
SaveKeyringParcel saveKeyringParcel) {
|
||||
@@ -135,10 +138,11 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
TextView vKeyDetails = (TextView) view.findViewById(R.id.subkey_item_details);
|
||||
TextView vKeyExpiry = (TextView) view.findViewById(R.id.subkey_item_expiry);
|
||||
ImageView vCertifyIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_certify);
|
||||
ImageView vEncryptIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_encrypt);
|
||||
ImageView vSignIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_sign);
|
||||
ImageView vRevokedIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_revoked);
|
||||
ImageView vEncryptIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_encrypt);
|
||||
ImageView vAuthenticateIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_authenticate);
|
||||
ImageView vEditImage = (ImageView) view.findViewById(R.id.subkey_item_edit_image);
|
||||
ImageView vStatus = (ImageView) view.findViewById(R.id.subkey_item_status);
|
||||
|
||||
// not used:
|
||||
ImageView deleteImage = (ImageView) view.findViewById(R.id.subkey_item_delete_button);
|
||||
@@ -196,7 +200,7 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
vCertifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE);
|
||||
vEncryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE);
|
||||
vSignIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE);
|
||||
// TODO: missing icon for authenticate
|
||||
vAuthenticateIcon.setVisibility(cursor.getInt(INDEX_CAN_AUTHENTICATE) != 0 ? View.VISIBLE : View.GONE);
|
||||
|
||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
||||
|
||||
@@ -245,22 +249,50 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none));
|
||||
}
|
||||
|
||||
if (isRevoked) {
|
||||
vRevokedIcon.setVisibility(View.VISIBLE);
|
||||
// if key is expired or revoked, strike through text
|
||||
boolean isInvalid = isRevoked || isExpired;
|
||||
if (isInvalid) {
|
||||
vStatus.setVisibility(View.VISIBLE);
|
||||
|
||||
vKeyId.setText(FormattingUtils.strikeOutText(vKeyId.getText()));
|
||||
vKeyDetails.setText(FormattingUtils.strikeOutText(vKeyDetails.getText()));
|
||||
vKeyExpiry.setText(FormattingUtils.strikeOutText(vKeyExpiry.getText()));
|
||||
|
||||
vCertifyIcon.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
vSignIcon.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
vEncryptIcon.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
vAuthenticateIcon.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
|
||||
if (isRevoked) {
|
||||
vStatus.setImageResource(R.drawable.status_signature_revoked_cutout);
|
||||
vStatus.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
} else if (isExpired) {
|
||||
vStatus.setImageResource(R.drawable.status_signature_expired_cutout);
|
||||
vStatus.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
} else {
|
||||
vStatus.setVisibility(View.GONE);
|
||||
|
||||
vKeyId.setTextColor(mDefaultTextColor);
|
||||
vKeyDetails.setTextColor(mDefaultTextColor);
|
||||
vKeyExpiry.setTextColor(mDefaultTextColor);
|
||||
|
||||
vRevokedIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// if key is expired or revoked, strike through text
|
||||
boolean isInvalid = isRevoked || isExpired;
|
||||
if (isInvalid) {
|
||||
vKeyId.setText(FormattingUtils.strikeOutText(vKeyId.getText()));
|
||||
vKeyDetails.setText(FormattingUtils.strikeOutText(vKeyDetails.getText()));
|
||||
vKeyExpiry.setText(FormattingUtils.strikeOutText(vKeyExpiry.getText()));
|
||||
vCertifyIcon.clearColorFilter();
|
||||
vSignIcon.clearColorFilter();
|
||||
vEncryptIcon.clearColorFilter();
|
||||
vAuthenticateIcon.clearColorFilter();
|
||||
}
|
||||
vKeyId.setEnabled(!isInvalid);
|
||||
vKeyDetails.setEnabled(!isInvalid);
|
||||
|
||||
@@ -53,8 +53,9 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
public TextView vKeyDetails;
|
||||
public TextView vKeyExpiry;
|
||||
public ImageView vCertifyIcon;
|
||||
public ImageView vEncryptIcon;
|
||||
public ImageView vSignIcon;
|
||||
public ImageView vEncryptIcon;
|
||||
public ImageView vAuthenticateIcon;
|
||||
public ImageButton vDelete;
|
||||
// also hold a reference to the model item
|
||||
public SaveKeyringParcel.SubkeyAdd mModel;
|
||||
@@ -69,16 +70,18 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
holder.vKeyDetails = (TextView) convertView.findViewById(R.id.subkey_item_details);
|
||||
holder.vKeyExpiry = (TextView) convertView.findViewById(R.id.subkey_item_expiry);
|
||||
holder.vCertifyIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_certify);
|
||||
holder.vEncryptIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_encrypt);
|
||||
holder.vSignIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_sign);
|
||||
holder.vEncryptIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_encrypt);
|
||||
holder.vAuthenticateIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_authenticate);
|
||||
|
||||
holder.vDelete = (ImageButton) convertView.findViewById(R.id.subkey_item_delete_button);
|
||||
holder.vDelete.setVisibility(View.VISIBLE); // always visible
|
||||
|
||||
// not used:
|
||||
ImageView editImage = (ImageView) convertView.findViewById(R.id.subkey_item_edit_image);
|
||||
editImage.setVisibility(View.GONE);
|
||||
ImageView revokedIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_revoked);
|
||||
revokedIcon.setVisibility(View.GONE);
|
||||
ImageView vEdit = (ImageView) convertView.findViewById(R.id.subkey_item_edit_image);
|
||||
vEdit.setVisibility(View.GONE);
|
||||
ImageView vStatus = (ImageView) convertView.findViewById(R.id.subkey_item_status);
|
||||
vStatus.setVisibility(View.GONE);
|
||||
|
||||
convertView.setTag(holder);
|
||||
|
||||
@@ -136,7 +139,11 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
} else {
|
||||
holder.vEncryptIcon.setVisibility(View.GONE);
|
||||
}
|
||||
// TODO: missing icon for authenticate
|
||||
if ((flags & KeyFlags.AUTHENTICATION) > 0) {
|
||||
holder.vAuthenticateIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.vAuthenticateIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
BIN
OpenKeychain/src/main/res/drawable-hdpi/key_flag_certify.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
OpenKeychain/src/main/res/drawable-hdpi/key_flag_encrypt.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
OpenKeychain/src/main/res/drawable-hdpi/key_flag_sign.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 897 B |
BIN
OpenKeychain/src/main/res/drawable-mdpi/key_flag_certify.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
OpenKeychain/src/main/res/drawable-mdpi/key_flag_encrypt.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
OpenKeychain/src/main/res/drawable-mdpi/key_flag_sign.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
BIN
OpenKeychain/src/main/res/drawable-xhdpi/key_flag_certify.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
OpenKeychain/src/main/res/drawable-xhdpi/key_flag_encrypt.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
OpenKeychain/src/main/res/drawable-xhdpi/key_flag_sign.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
BIN
OpenKeychain/src/main/res/drawable-xxhdpi/key_flag_certify.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
OpenKeychain/src/main/res/drawable-xxhdpi/key_flag_encrypt.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
OpenKeychain/src/main/res/drawable-xxhdpi/key_flag_sign.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -6,6 +6,16 @@
|
||||
android:orientation="horizontal"
|
||||
android:singleLine="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/subkey_item_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/status_signature_revoked_cutout"
|
||||
android:paddingLeft="8dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentStart="true" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/subkey_item_buttons"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -34,6 +44,7 @@
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_toLeftOf="@id/subkey_item_buttons"
|
||||
android:layout_toRightOf="@id/subkey_item_status"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -60,15 +71,7 @@
|
||||
android:id="@+id/subkey_item_ic_certify"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/certify_small"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/subkey_item_ic_encrypt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/encrypted_small"
|
||||
android:src="@drawable/key_flag_certify"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
@@ -76,15 +79,23 @@
|
||||
android:id="@+id/subkey_item_ic_sign"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/signed_small"
|
||||
android:src="@drawable/key_flag_sign"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/subkey_item_ic_revoked"
|
||||
android:id="@+id/subkey_item_ic_encrypt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/revoked_key_small"
|
||||
android:src="@drawable/key_flag_encrypt"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/subkey_item_ic_authenticate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/key_flag_authenticate"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
|
||||