mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-10 19:15:06 -05:00
Select*KeyFragment rewrites
- moved all specific Public/Secret logic from the Adapter class into inner subclasses in the Fragments - more versatile status display ("revoked", "expired", "can certify"...) - applied view holder pattern - query logic, including subqueries, moved into provider classes Closes #375
This commit is contained in:
parent
ce6a4041fd
commit
593d6ad3f7
@ -112,6 +112,8 @@ public class KeychainContract {
|
|||||||
public static final String IS_REVOKED = KeysColumns.IS_REVOKED;
|
public static final String IS_REVOKED = KeysColumns.IS_REVOKED;
|
||||||
public static final String VERIFIED = CertsColumns.VERIFIED;
|
public static final String VERIFIED = CertsColumns.VERIFIED;
|
||||||
public static final String HAS_SECRET = "has_secret";
|
public static final String HAS_SECRET = "has_secret";
|
||||||
|
public static final String HAS_ENCRYPT = "has_encrypt";
|
||||||
|
public static final String HAS_SIGN = "has_encrypt";
|
||||||
|
|
||||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_KEY_RINGS).build();
|
.appendPath(BASE_KEY_RINGS).build();
|
||||||
|
@ -38,9 +38,11 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||||
|
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class KeychainProvider extends ContentProvider {
|
public class KeychainProvider extends ContentProvider {
|
||||||
@ -264,7 +266,29 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT);
|
projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT);
|
||||||
projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID);
|
projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID);
|
||||||
projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED);
|
projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED);
|
||||||
projectionMap.put(KeyRings.HAS_SECRET, "(" + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL) AS " + KeyRings.HAS_SECRET);
|
projectionMap.put(KeyRings.HAS_SECRET,
|
||||||
|
"(EXISTS (SELECT * FROM " + Tables.KEY_RINGS_SECRET
|
||||||
|
+ " WHERE " + Tables.KEY_RINGS_SECRET + "." + KeyRingData.MASTER_KEY_ID
|
||||||
|
+ " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||||
|
+ ")) AS " + KeyRings.HAS_SECRET);
|
||||||
|
projectionMap.put(KeyRings.HAS_ENCRYPT,
|
||||||
|
"(EXISTS (SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
||||||
|
+" WHERE k." + Keys.MASTER_KEY_ID
|
||||||
|
+ " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||||
|
+ " AND k." + Keys.IS_REVOKED + " = 0"
|
||||||
|
+ " AND k." + Keys.CAN_ENCRYPT + " = 1"
|
||||||
|
+ " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY
|
||||||
|
+ " >= '" + new Date().getTime() / 1000 + "' )"
|
||||||
|
+ ")) AS " + KeyRings.HAS_ENCRYPT);
|
||||||
|
projectionMap.put(KeyRings.HAS_SIGN,
|
||||||
|
"(EXISTS (SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
||||||
|
+" WHERE k." + Keys.MASTER_KEY_ID
|
||||||
|
+ " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||||
|
+ " AND k." + Keys.IS_REVOKED + " = 0"
|
||||||
|
+ " AND k." + Keys.CAN_SIGN + " = 1"
|
||||||
|
+ " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY
|
||||||
|
+ " >= '" + new Date().getTime() / 1000 + "' )"
|
||||||
|
+ ")) AS " + KeyRings.HAS_SIGN);
|
||||||
qb.setProjectionMap(projectionMap);
|
qb.setProjectionMap(projectionMap);
|
||||||
|
|
||||||
qb.setTables(
|
qb.setTables(
|
||||||
@ -274,10 +298,6 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
+ " = "
|
+ " = "
|
||||||
+ Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID
|
+ Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID
|
||||||
+ " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0"
|
+ " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0"
|
||||||
+ ") LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON ("
|
|
||||||
+ Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
|
||||||
+ " = "
|
|
||||||
+ Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID
|
|
||||||
+ ") LEFT JOIN " + Tables.CERTS + " ON ("
|
+ ") LEFT JOIN " + Tables.CERTS + " ON ("
|
||||||
+ Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
+ Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||||
+ " = "
|
+ " = "
|
||||||
@ -345,9 +365,7 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(sortOrder)) {
|
if (TextUtils.isEmpty(sortOrder)) {
|
||||||
sortOrder =
|
sortOrder = Tables.USER_IDS + "." + UserIds.USER_ID + " ASC";
|
||||||
Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL ASC, "
|
|
||||||
+ Tables.USER_IDS + "." + UserIds.USER_ID + " ASC";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// uri to watch is all /key_rings/
|
// uri to watch is all /key_rings/
|
||||||
|
@ -265,6 +265,10 @@ public class KeyListFragment extends Fragment
|
|||||||
static final int INDEX_VERIFIED = 5;
|
static final int INDEX_VERIFIED = 5;
|
||||||
static final int INDEX_HAS_SECRET = 6;
|
static final int INDEX_HAS_SECRET = 6;
|
||||||
|
|
||||||
|
static final String ORDER = // IN THE COURT
|
||||||
|
KeyRings.HAS_SECRET + " DESC, " + KeyRings.USER_ID + " ASC";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
// This is called when a new Loader needs to be created. This
|
// This is called when a new Loader needs to be created. This
|
||||||
@ -276,9 +280,10 @@ public class KeyListFragment extends Fragment
|
|||||||
where = KeyRings.USER_ID + " LIKE ?";
|
where = KeyRings.USER_ID + " LIKE ?";
|
||||||
whereArgs = new String[]{"%" + mCurQuery + "%"};
|
whereArgs = new String[]{"%" + mCurQuery + "%"};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now create and return a CursorLoader that will take care of
|
// Now create and return a CursorLoader that will take care of
|
||||||
// creating a Cursor for the data being displayed.
|
// creating a Cursor for the data being displayed.
|
||||||
return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, null);
|
return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, ORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,17 +40,12 @@ import android.widget.ListView;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Id;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
|
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
public class SelectPublicKeyFragment extends ListFragmentWorkaround implements TextWatcher,
|
public class SelectPublicKeyFragment extends ListFragmentWorkaround implements TextWatcher,
|
||||||
@ -180,7 +175,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
|
|
||||||
mSearchView.addTextChangedListener(this);
|
mSearchView.addTextChangedListener(this);
|
||||||
|
|
||||||
mAdapter = new SelectKeyCursorAdapter(getActivity(), null, 0, getListView(), Id.type.public_key);
|
mAdapter = new SelectPublicKeyCursorAdapter(getActivity(), null, 0, getListView());
|
||||||
|
|
||||||
setListAdapter(mAdapter);
|
setListAdapter(mAdapter);
|
||||||
|
|
||||||
@ -258,25 +253,14 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
Uri baseUri = KeyRings.buildUnifiedKeyRingsUri();
|
Uri baseUri = KeyRings.buildUnifiedKeyRingsUri();
|
||||||
|
|
||||||
// These are the rows that we will retrieve.
|
// These are the rows that we will retrieve.
|
||||||
long now = new Date().getTime() / 1000;
|
|
||||||
String[] projection = new String[]{
|
String[] projection = new String[]{
|
||||||
KeyRings._ID,
|
KeyRings._ID,
|
||||||
KeyRings.MASTER_KEY_ID,
|
KeyRings.MASTER_KEY_ID,
|
||||||
UserIds.USER_ID,
|
KeyRings.USER_ID,
|
||||||
"(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
KeyRings.EXPIRY,
|
||||||
+" WHERE k." + Keys.MASTER_KEY_ID + " = "
|
KeyRings.IS_REVOKED,
|
||||||
+ KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
KeyRings.HAS_ENCRYPT,
|
||||||
+ " AND k." + Keys.IS_REVOKED + " = '0'"
|
};
|
||||||
+ " AND k." + Keys.CAN_ENCRYPT + " = '1'"
|
|
||||||
+ ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE,
|
|
||||||
"(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
|
||||||
+ " WHERE k." + Keys.MASTER_KEY_ID + " = "
|
|
||||||
+ KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
|
||||||
+ " AND k." + Keys.IS_REVOKED + " = '0'"
|
|
||||||
+ " AND k." + Keys.CAN_ENCRYPT + " = '1'"
|
|
||||||
+ " AND k." + Keys.CREATION + " <= '" + now + "'"
|
|
||||||
+ " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )"
|
|
||||||
+ ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, };
|
|
||||||
|
|
||||||
String inMasterKeyList = null;
|
String inMasterKeyList = null;
|
||||||
if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) {
|
if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) {
|
||||||
@ -290,7 +274,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
inMasterKeyList += ")";
|
inMasterKeyList += ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
String orderBy = UserIds.USER_ID + " ASC";
|
String orderBy = KeyRings.USER_ID + " ASC";
|
||||||
if (inMasterKeyList != null) {
|
if (inMasterKeyList != null) {
|
||||||
// sort by selected master keys
|
// sort by selected master keys
|
||||||
orderBy = inMasterKeyList + " DESC, " + orderBy;
|
orderBy = inMasterKeyList + " DESC, " + orderBy;
|
||||||
@ -298,7 +282,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
String where = null;
|
String where = null;
|
||||||
String whereArgs[] = null;
|
String whereArgs[] = null;
|
||||||
if (mCurQuery != null) {
|
if (mCurQuery != null) {
|
||||||
where = UserIds.USER_ID + " LIKE ?";
|
where = KeyRings.USER_ID + " LIKE ?";
|
||||||
whereArgs = new String[]{"%" + mCurQuery + "%"};
|
whereArgs = new String[]{"%" + mCurQuery + "%"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,4 +332,47 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
mCurQuery = !TextUtils.isEmpty(editable.toString()) ? editable.toString() : null;
|
mCurQuery = !TextUtils.isEmpty(editable.toString()) ? editable.toString() : null;
|
||||||
getLoaderManager().restartLoader(0, null, this);
|
getLoaderManager().restartLoader(0, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SelectPublicKeyCursorAdapter extends SelectKeyCursorAdapter {
|
||||||
|
|
||||||
|
private int mIndexHasEncrypt;
|
||||||
|
|
||||||
|
public SelectPublicKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) {
|
||||||
|
super(context, c, flags, listView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initIndex(Cursor cursor) {
|
||||||
|
super.initIndex(cursor);
|
||||||
|
if (cursor != null) {
|
||||||
|
mIndexHasEncrypt = cursor.getColumnIndexOrThrow(KeyRings.HAS_ENCRYPT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
|
super.bindView(view, context, cursor);
|
||||||
|
ViewHolderItem h = (SelectKeyCursorAdapter.ViewHolderItem) view.getTag();
|
||||||
|
|
||||||
|
// We care about the checkbox
|
||||||
|
h.selected.setVisibility(View.VISIBLE);
|
||||||
|
// the getListView works because this is not a static subclass!
|
||||||
|
h.selected.setChecked(getListView().isItemChecked(cursor.getPosition()));
|
||||||
|
|
||||||
|
boolean enabled = false;
|
||||||
|
if((Boolean) h.status.getTag()) {
|
||||||
|
// Check if key is viable for our purposes
|
||||||
|
if (cursor.getInt(mIndexHasEncrypt) == 0) {
|
||||||
|
h.status.setText(R.string.no_key);
|
||||||
|
} else {
|
||||||
|
h.status.setText(R.string.can_encrypt);
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -30,23 +31,15 @@ import android.widget.AdapterView;
|
|||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Id;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class SelectSecretKeyFragment extends ListFragment implements
|
public class SelectSecretKeyFragment extends ListFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
private SelectSecretKeyActivity mActivity;
|
private SelectSecretKeyActivity mActivity;
|
||||||
private SelectKeyCursorAdapter mAdapter;
|
private SelectKeyCursorAdapter mAdapter;
|
||||||
private ListView mListView;
|
|
||||||
|
|
||||||
private boolean mFilterCertify;
|
private boolean mFilterCertify;
|
||||||
|
|
||||||
@ -80,9 +73,9 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
mActivity = (SelectSecretKeyActivity) getActivity();
|
mActivity = (SelectSecretKeyActivity) getActivity();
|
||||||
mListView = getListView();
|
|
||||||
|
|
||||||
mListView.setOnItemClickListener(new OnItemClickListener() {
|
ListView listView = getListView();
|
||||||
|
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||||
long masterKeyId = mAdapter.getMasterKeyId(position);
|
long masterKeyId = mAdapter.getMasterKeyId(position);
|
||||||
@ -97,7 +90,7 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
// application this would come from a resource.
|
// application this would come from a resource.
|
||||||
setEmptyText(getString(R.string.list_empty));
|
setEmptyText(getString(R.string.list_empty));
|
||||||
|
|
||||||
mAdapter = new SelectKeyCursorAdapter(mActivity, null, 0, mListView, Id.type.secret_key);
|
mAdapter = new SelectSecretKeyCursorAdapter(mActivity, null, 0, listView);
|
||||||
|
|
||||||
setListAdapter(mAdapter);
|
setListAdapter(mAdapter);
|
||||||
|
|
||||||
@ -116,41 +109,22 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
Uri baseUri = KeyRings.buildUnifiedKeyRingsUri();
|
Uri baseUri = KeyRings.buildUnifiedKeyRingsUri();
|
||||||
|
|
||||||
// These are the rows that we will retrieve.
|
// These are the rows that we will retrieve.
|
||||||
long now = new Date().getTime() / 1000;
|
|
||||||
String[] projection = new String[]{
|
String[] projection = new String[]{
|
||||||
KeyRings._ID,
|
KeyRings._ID,
|
||||||
KeyRings.MASTER_KEY_ID,
|
KeyRings.MASTER_KEY_ID,
|
||||||
UserIds.USER_ID,
|
KeyRings.USER_ID,
|
||||||
"(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
KeyRings.EXPIRY,
|
||||||
+ " WHERE k." + Keys.MASTER_KEY_ID + " = "
|
KeyRings.IS_REVOKED,
|
||||||
+ KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID
|
KeyRings.CAN_CERTIFY,
|
||||||
+ " AND k." + Keys.CAN_CERTIFY + " = '1'"
|
KeyRings.HAS_SIGN,
|
||||||
+ ") AS cert",
|
KeyRings.HAS_SECRET
|
||||||
"(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
};
|
||||||
+" WHERE k." + Keys.MASTER_KEY_ID + " = "
|
|
||||||
+ KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
|
||||||
+ " AND k." + Keys.IS_REVOKED + " = '0'"
|
|
||||||
+ " AND k." + Keys.CAN_SIGN + " = '1'"
|
|
||||||
+ ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE,
|
|
||||||
"(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k"
|
|
||||||
+ " WHERE k." + Keys.MASTER_KEY_ID + " = "
|
|
||||||
+ KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
|
||||||
+ " AND k." + Keys.IS_REVOKED + " = '0'"
|
|
||||||
+ " AND k." + Keys.CAN_SIGN + " = '1'"
|
|
||||||
+ " AND k." + Keys.CREATION + " <= '" + now + "'"
|
|
||||||
+ " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )"
|
|
||||||
+ ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, };
|
|
||||||
|
|
||||||
String orderBy = UserIds.USER_ID + " ASC";
|
String where = KeyRings.HAS_SECRET + " = 1";
|
||||||
|
|
||||||
String where = Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL";
|
|
||||||
if (mFilterCertify) {
|
|
||||||
where += " AND (cert > 0)";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now create and return a CursorLoader that will take care of
|
// Now create and return a CursorLoader that will take care of
|
||||||
// creating a Cursor for the data being displayed.
|
// creating a Cursor for the data being displayed.
|
||||||
return new CursorLoader(getActivity(), baseUri, projection, where, null, orderBy);
|
return new CursorLoader(getActivity(), baseUri, projection, where, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -174,4 +148,57 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
// longer using it.
|
// longer using it.
|
||||||
mAdapter.swapCursor(null);
|
mAdapter.swapCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SelectSecretKeyCursorAdapter extends SelectKeyCursorAdapter {
|
||||||
|
|
||||||
|
private int mIndexHasSign, mIndexCanCertify;
|
||||||
|
|
||||||
|
public SelectSecretKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) {
|
||||||
|
super(context, c, flags, listView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initIndex(Cursor cursor) {
|
||||||
|
super.initIndex(cursor);
|
||||||
|
if (cursor != null) {
|
||||||
|
mIndexCanCertify = cursor.getColumnIndexOrThrow(KeyRings.CAN_CERTIFY);
|
||||||
|
mIndexHasSign = cursor.getColumnIndexOrThrow(KeyRings.HAS_SIGN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
|
super.bindView(view, context, cursor);
|
||||||
|
ViewHolderItem h = (SelectKeyCursorAdapter.ViewHolderItem) view.getTag();
|
||||||
|
|
||||||
|
// We don't care about the checkbox
|
||||||
|
h.selected.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Special from superclass: Te
|
||||||
|
boolean enabled = false;
|
||||||
|
if((Boolean) h.status.getTag()) {
|
||||||
|
// Check if key is viable for our purposes (certify or sign)
|
||||||
|
if(mFilterCertify) {
|
||||||
|
if (cursor.getInt(mIndexCanCertify) == 0) {
|
||||||
|
h.status.setText(R.string.can_certify_not);
|
||||||
|
} else {
|
||||||
|
h.status.setText(R.string.can_certify);
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cursor.getInt(mIndexHasSign) == 0) {
|
||||||
|
h.status.setText(R.string.no_key);
|
||||||
|
} else {
|
||||||
|
h.status.setText(R.string.can_sign);
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.setEnabled(enabled);
|
||||||
|
// refresh this, too, for use in the ItemClickListener above
|
||||||
|
h.status.setTag(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -26,35 +26,25 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Id;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
/**
|
||||||
|
* Yes this class is abstract!
|
||||||
protected int mKeyType;
|
*/
|
||||||
|
abstract public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
||||||
|
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
private ListView mListView;
|
|
||||||
|
|
||||||
private int mIndexUserId;
|
protected int mIndexUserId, mIndexMasterKeyId, mIndexRevoked, mIndexExpiry;
|
||||||
private int mIndexMasterKeyId;
|
|
||||||
private int mIndexProjectionValid;
|
|
||||||
private int mIndexProjectionAvailable;
|
|
||||||
|
|
||||||
public static final String PROJECTION_ROW_AVAILABLE = "available";
|
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) {
|
||||||
public static final String PROJECTION_ROW_VALID = "valid";
|
|
||||||
|
|
||||||
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
|
|
||||||
int keyType) {
|
|
||||||
super(context, c, flags);
|
super(context, c, flags);
|
||||||
|
|
||||||
mInflater = LayoutInflater.from(context);
|
mInflater = LayoutInflater.from(context);
|
||||||
mListView = listView;
|
|
||||||
mKeyType = keyType;
|
|
||||||
initIndex(c);
|
initIndex(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +61,12 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
|||||||
*
|
*
|
||||||
* @param cursor
|
* @param cursor
|
||||||
*/
|
*/
|
||||||
private void initIndex(Cursor cursor) {
|
protected void initIndex(Cursor cursor) {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
|
mIndexUserId = cursor.getColumnIndexOrThrow(KeyRings.USER_ID);
|
||||||
mIndexMasterKeyId = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
|
mIndexMasterKeyId = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
|
||||||
mIndexProjectionValid = cursor.getColumnIndexOrThrow(PROJECTION_ROW_VALID);
|
mIndexExpiry= cursor.getColumnIndexOrThrow(KeyRings.EXPIRY);
|
||||||
mIndexProjectionAvailable = cursor.getColumnIndexOrThrow(PROJECTION_ROW_AVAILABLE);
|
mIndexRevoked= cursor.getColumnIndexOrThrow(KeyRings.IS_REVOKED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,70 +80,73 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
|||||||
return mCursor.getLong(mIndexMasterKeyId);
|
return mCursor.getLong(mIndexMasterKeyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ViewHolderItem {
|
||||||
|
public View view;
|
||||||
|
public TextView mainUserId, mainUserIdRest, keyId, status;
|
||||||
|
public CheckBox selected;
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
view.setEnabled(enabled);
|
||||||
|
selected.setEnabled(enabled);
|
||||||
|
mainUserId.setEnabled(enabled);
|
||||||
|
mainUserIdRest.setEnabled(enabled);
|
||||||
|
keyId.setEnabled(enabled);
|
||||||
|
status.setEnabled(enabled);
|
||||||
|
|
||||||
|
// Sorta special: We set an item as clickable to disable it in the ListView. This works
|
||||||
|
// because the list item will handle the clicks itself (which is a nop)
|
||||||
|
view.setClickable(!enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
ViewHolderItem h = (ViewHolderItem) view.getTag();
|
||||||
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
|
|
||||||
TextView keyId = (TextView) view.findViewById(R.id.keyId);
|
|
||||||
TextView status = (TextView) view.findViewById(R.id.status);
|
|
||||||
|
|
||||||
String userId = cursor.getString(mIndexUserId);
|
String userId = cursor.getString(mIndexUserId);
|
||||||
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
|
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
|
||||||
|
|
||||||
if (userIdSplit[0] != null) {
|
if (userIdSplit[0] != null) {
|
||||||
mainUserId.setText(highlightSearchQuery(userIdSplit[0]));
|
h.mainUserId.setText(highlightSearchQuery(userIdSplit[0]));
|
||||||
} else {
|
} else {
|
||||||
mainUserId.setText(R.string.user_id_no_name);
|
h.mainUserId.setText(R.string.user_id_no_name);
|
||||||
}
|
}
|
||||||
if (userIdSplit[1] != null) {
|
if (userIdSplit[1] != null) {
|
||||||
mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1]));
|
h.mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1]));
|
||||||
} else {
|
} else {
|
||||||
mainUserIdRest.setText("");
|
h.mainUserIdRest.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
long masterKeyId = cursor.getLong(mIndexMasterKeyId);
|
long masterKeyId = cursor.getLong(mIndexMasterKeyId);
|
||||||
keyId.setText(PgpKeyHelper.convertKeyIdToHexShort(masterKeyId));
|
h.keyId.setText(PgpKeyHelper.convertKeyIdToHexShort(masterKeyId));
|
||||||
|
|
||||||
boolean valid = cursor.getInt(mIndexProjectionValid) > 0;
|
boolean enabled = true;
|
||||||
if (valid) {
|
if(cursor.getInt(mIndexRevoked) != 0) {
|
||||||
if (mKeyType == Id.type.public_key) {
|
h.status.setText(R.string.revoked);
|
||||||
status.setText(R.string.can_encrypt);
|
enabled = false;
|
||||||
|
} else if (!cursor.isNull(mIndexExpiry)
|
||||||
|
&& new Date(cursor.getLong(mIndexExpiry) * 1000).before(new Date())) {
|
||||||
|
h.status.setText(R.string.expired);
|
||||||
|
enabled = false;
|
||||||
} else {
|
} else {
|
||||||
status.setText(R.string.can_sign);
|
h.status.setText("");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (cursor.getInt(mIndexProjectionAvailable) > 0) {
|
|
||||||
// has some CAN_ENCRYPT keys, but col(ROW_VALID) = 0, so must be revoked or
|
|
||||||
// expired
|
|
||||||
status.setText(R.string.expired);
|
|
||||||
} else {
|
|
||||||
status.setText(R.string.no_key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
|
h.status.setTag(enabled);
|
||||||
if (mKeyType == Id.type.public_key) {
|
|
||||||
selected.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
mListView.setItemChecked(cursor.getPosition(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
selected.setChecked(mListView.isItemChecked(cursor.getPosition()));
|
|
||||||
selected.setEnabled(valid);
|
|
||||||
} else {
|
|
||||||
selected.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
view.setEnabled(valid);
|
|
||||||
mainUserId.setEnabled(valid);
|
|
||||||
mainUserIdRest.setEnabled(valid);
|
|
||||||
keyId.setEnabled(valid);
|
|
||||||
status.setEnabled(valid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||||
return mInflater.inflate(R.layout.select_key_item, null);
|
View view = mInflater.inflate(R.layout.select_key_item, null);
|
||||||
|
ViewHolderItem holder = new ViewHolderItem();
|
||||||
|
holder.view = view;
|
||||||
|
holder.mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
||||||
|
holder.mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
|
||||||
|
holder.keyId = (TextView) view.findViewById(R.id.keyId);
|
||||||
|
holder.status = (TextView) view.findViewById(R.id.status);
|
||||||
|
holder.selected = (CheckBox) view.findViewById(R.id.selected);
|
||||||
|
view.setTag(holder);
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,5 +523,7 @@
|
|||||||
<string name="label_revocation">Revocation Reason</string>
|
<string name="label_revocation">Revocation Reason</string>
|
||||||
<string name="label_verify_status">Verification Status</string>
|
<string name="label_verify_status">Verification Status</string>
|
||||||
<string name="label_cert_type">Type</string>
|
<string name="label_cert_type">Type</string>
|
||||||
|
<string name="can_certify">can certify</string>
|
||||||
|
<string name="can_certify_not">cannot certify</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user