Import keys with adapter, loader, and new design

This commit is contained in:
Dominik Schürmann
2013-09-22 19:58:33 +02:00
parent 7b2de96d15
commit 917c86b524
30 changed files with 702 additions and 797 deletions

View File

@@ -24,10 +24,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
@@ -36,6 +37,7 @@ import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@@ -100,17 +102,23 @@ public class PgpImportExport {
}
}
public Bundle importKeyRings(InputData data) throws PgpGeneralException, FileNotFoundException,
PGPException, IOException {
/**
* Imports keys from given data. If keyIds is given only those are imported
*
* @param data
* @param keyIds
* @return
* @throws PgpGeneralException
* @throws FileNotFoundException
* @throws PGPException
* @throws IOException
*/
public Bundle importKeyRings(InputData data, ArrayList<Long> keyIds)
throws PgpGeneralException, FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle();
updateProgress(R.string.progress_importingSecretKeys, 0, 100);
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new PgpGeneralException(
mContext.getString(R.string.error_externalStorageNotReady));
}
PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
// need to have access to the bufferedInput, so we can reuse it for the possible
@@ -137,7 +145,16 @@ public class PgpImportExport {
int status = Integer.MIN_VALUE; // out of bounds value
status = storeKeyRingInCache(keyring);
if (keyIds != null) {
if (keyIds.contains(keyring.getPublicKey().getKeyID())) {
status = storeKeyRingInCache(keyring);
} else {
Log.d(Constants.TAG, "not selected! key id: "
+ keyring.getPublicKey().getKeyID());
}
} else {
status = storeKeyRingInCache(keyring);
}
if (status == Id.return_value.error) {
throw new PgpGeneralException(
@@ -264,11 +281,14 @@ public class PgpImportExport {
if (save) {
ProviderHelper.saveKeyRing(mContext, secretKeyRing);
// TODO: preserve certifications (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?)
// TODO: preserve certifications
// (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?)
PGPPublicKeyRing newPubRing = null;
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(secretKeyRing.getPublicKeys())) {
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(
secretKeyRing.getPublicKeys())) {
if (newPubRing == null) {
newPubRing = new PGPPublicKeyRing(key.getEncoded(), new JcaKeyFingerprintCalculator());
newPubRing = new PGPPublicKeyRing(key.getEncoded(),
new JcaKeyFingerprintCalculator());
}
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
}

View File

@@ -137,7 +137,7 @@ public class PgpKeyHelper {
PGPPublicKey masterKey = null;
for (int i = 0; i < encryptKeys.size(); ++i) {
PGPPublicKey key = encryptKeys.get(i);
if (!isExpired(key) && !key.isRevoked()) {
if (!isExpired(key) && !key.isRevoked()) {
if (key.isMasterKey()) {
masterKey = key;
} else {
@@ -488,7 +488,7 @@ public class PgpKeyHelper {
return isSecretKeyPrivateEmpty(secretKey);
}
public static String getSmallFingerPrint(long keyId) {
public static String convertKeyIdToHex(long keyId) {
String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
while (fingerPrint.length() < 8) {
fingerPrint = "0" + fingerPrint;
@@ -496,11 +496,17 @@ public class PgpKeyHelper {
return fingerPrint;
}
public static String keyToHex(long keyId) {
return getSmallFingerPrint(keyId >> 32) + getSmallFingerPrint(keyId);
/**
* TODO: what is the difference to the other function?
*
* @param keyId
* @return
*/
public static String convertKeyToHex(long keyId) {
return convertKeyIdToHex(keyId >> 32) + convertKeyIdToHex(keyId);
}
public static long keyFromHex(String data) {
public static long convertHexToKeyId(String data) {
int len = data.length();
String s2 = data.substring(len - 8);
String s1 = data.substring(0, len - 8);

View File

@@ -27,7 +27,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
@@ -45,6 +47,7 @@ import org.sufficientlysecure.keychain.pgp.PgpOperation;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.KeyServer.KeyInfo;
@@ -142,7 +145,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String IMPORT_INPUT_STREAM = "import_input_stream";
public static final String IMPORT_FILENAME = "import_filename";
public static final String IMPORT_BYTES = "import_bytes";
// public static final String IMPORT_KEY_TYPE = "importKeyType";
public static final String IMPORT_KEY_LIST = "import_key_list";
// export key
public static final String EXPORT_OUTPUT_STREAM = "export_output_stream";
@@ -630,11 +633,6 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Input */
int target = data.getInt(TARGET);
// int keyType = Id.type.public_key;
// if (data.containsKey(IMPORT_KEY_TYPE)) {
// keyType = data.getInt(IMPORT_KEY_TYPE);
// }
/* Operation */
InputStream inStream = null;
long inLength = -1;
@@ -666,8 +664,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
Bundle resultData = new Bundle();
ArrayList<Long> keyIds = (ArrayList<Long>) data.getSerializable(IMPORT_KEY_LIST);
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
resultData = pgpImportExport.importKeyRings(inputData);
resultData = pgpImportExport.importKeyRings(inputData, keyIds);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {

View File

@@ -17,10 +17,6 @@
package org.sufficientlysecure.keychain.service.remote;
import java.util.HashMap;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
@@ -29,7 +25,8 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity;
import org.sufficientlysecure.keychain.util.KeyValueSpinnerAdapter;
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
import org.sufficientlysecure.keychain.util.AlgorithmNames;
import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity;
@@ -114,18 +111,10 @@ public class AppSettingsFragment extends Fragment {
mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm);
mCompression = (Spinner) view.findViewById(R.id.api_app_settings_compression);
HashMap<Integer, String> encryptionMap = new HashMap<Integer, String>();
encryptionMap.put(PGPEncryptedData.AES_128, "AES-128");
encryptionMap.put(PGPEncryptedData.AES_192, "AES-192");
encryptionMap.put(PGPEncryptedData.AES_256, "AES-256");
encryptionMap.put(PGPEncryptedData.BLOWFISH, "Blowfish");
encryptionMap.put(PGPEncryptedData.TWOFISH, "Twofish");
encryptionMap.put(PGPEncryptedData.CAST5, "CAST5");
encryptionMap.put(PGPEncryptedData.DES, "DES");
encryptionMap.put(PGPEncryptedData.TRIPLE_DES, "Triple DES");
encryptionMap.put(PGPEncryptedData.IDEA, "IDEA");
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(), encryptionMap);
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
algorithmNames.getEncryptionNames());
mEncryptionAlgorithm.setAdapter(encryptionAdapter);
mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
@@ -139,16 +128,7 @@ public class AppSettingsFragment extends Fragment {
}
});
HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
hashMap.put(HashAlgorithmTags.MD5, "MD5");
hashMap.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160");
hashMap.put(HashAlgorithmTags.SHA1, "SHA-1");
hashMap.put(HashAlgorithmTags.SHA224, "SHA-224");
hashMap.put(HashAlgorithmTags.SHA256, "SHA-256");
hashMap.put(HashAlgorithmTags.SHA384, "SHA-384");
hashMap.put(HashAlgorithmTags.SHA512, "SHA-512");
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), hashMap);
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
mHashAlgorithm.setAdapter(hashAdapter);
mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
@@ -162,15 +142,8 @@ public class AppSettingsFragment extends Fragment {
}
});
HashMap<Integer, String> compressionMap = new HashMap<Integer, String>();
compressionMap.put(Id.choice.compression.none, getString(R.string.choice_none) + " ("
+ getString(R.string.fast) + ")");
compressionMap.put(Id.choice.compression.zip, "ZIP (" + getString(R.string.fast) + ")");
compressionMap.put(Id.choice.compression.zlib, "ZLIB (" + getString(R.string.fast) + ")");
compressionMap.put(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.very_slow)
+ ")");
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(), compressionMap);
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
algorithmNames.getCompressionNames());
mCompression.setAdapter(compressionAdapter);
mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {

View File

@@ -773,7 +773,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
mSignatureKeyId = returnData
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
mUserIdRest.setText("id: "
+ PgpKeyHelper.getSmallFingerPrint(mSignatureKeyId));
+ PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId));
if (userId == null) {
userId = getResources().getString(R.string.unknownUserId);
}

View File

@@ -17,12 +17,15 @@
package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import java.util.List;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@@ -44,7 +47,6 @@ import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
public class ImportKeysActivity extends SherlockFragmentActivity implements OnNavigationListener {
@@ -152,27 +154,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
mListFragment.load(importData, importFilename);
}
/**
* ActionBar menu is created based on class variables to change it at runtime
*
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1, Id.menu.option.key_server, 0, R.string.menu_keyServer).setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(1, Id.menu.option.import_from_file, 1, R.string.menu_importFromFile)
.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(1, Id.menu.option.import_from_qr_code, 2, R.string.menu_importFromQrCode)
.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(1, Id.menu.option.import_from_nfc, 3, R.string.menu_importFromNfc)
.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@@ -184,23 +165,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
startActivity(intent);
return true;
case Id.menu.option.key_server:
startActivityForResult(new Intent(this, KeyServerQueryActivity.class), 0);
return true;
// case Id.menu.option.import_from_file:
// showImportFromFileDialog();
// return true;
// case Id.menu.option.import_from_qr_code:
// importFromQrCode();
// return true;
//
// case Id.menu.option.import_from_nfc:
// importFromNfc();
// return true;
default:
return super.onOptionsItemSelected(item);
@@ -329,8 +293,16 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
// fill values for this action
Bundle data = new Bundle();
// TODO: check for key type?
// data.putInt(KeychainIntentService.IMPORT_KEY_TYPE, Id.type.secret_key);
// get selected key ids
List<ImportKeysListEntry> listEntries = mListFragment.getData();
ArrayList<Long> selectedKeyIds = new ArrayList<Long>();
for (ImportKeysListEntry entry : listEntries) {
if (entry.isSelected()) {
selectedKeyIds.add(entry.keyId);
}
}
data.putSerializable(KeychainIntentService.IMPORT_KEY_LIST, selectedKeyIds);
if (mListFragment.getKeyBytes() != null) {
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);

View File

@@ -68,8 +68,8 @@ public class ImportKeysFileFragment extends Fragment {
// open .asc or .gpg files
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
// or gpg types!
FileHelper.openFile(ImportKeysFileFragment.this, mFilename.getText().toString(), "*/*",
Id.request.filename);
FileHelper.openFile(ImportKeysFileFragment.this, mFilename.getText().toString(),
"*/*", Id.request.filename);
}
});
@@ -84,7 +84,7 @@ public class ImportKeysFileFragment extends Fragment {
// set default path
String path = Constants.path.APP_DIR + "/";
if (getArguments() != null) {
if (getArguments() != null && getArguments().containsKey(ARG_PATH)) {
path = getArguments().getString(ARG_PATH);
}
mFilename.setText(path);

View File

@@ -17,37 +17,32 @@
package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.ui.widget.ImportKeysListLoader;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
import com.actionbarsherlock.app.SherlockListFragment;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.content.Loader;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import com.actionbarsherlock.app.SherlockListFragment;
public class ImportKeysListFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<List<Map<String, String>>> {
// public static final String ARG_IMPORT_DATA = "bytes";
// public static final String ARG_IMPORT_FILENAME = "filename";
LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> {
private Activity mActivity;
private SimpleAdapter mAdapter;
private ImportKeysAdapter mAdapter;
private byte[] mKeyBytes;
private String mImportFilename;
public byte[] getKeyBytes() {
return mKeyBytes;
@@ -57,38 +52,19 @@ public class ImportKeysListFragment extends SherlockListFragment implements
return mImportFilename;
}
public List<ImportKeysListEntry> getData() {
return mAdapter.getData();
}
/**
* Creates new instance of this fragment
*/
public static ImportKeysListFragment newInstance() {
ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
}
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
// Map<String, String> item = (Map<String, String>) listView.getItemAtPosition(position);
// String userId = item.get(ImportKeysListLoader.MAP_ATTR_USER_ID);
}
/**
* Resume is called after rotating
*/
@Override
public void onResume() {
super.onResume();
// Start out with a progress indicator.
setListShown(false);
// reload list
getLoaderManager().restartLoader(0, null, this);
}
/**
* Define Adapter and Loader on create of Activity
*/
@@ -96,10 +72,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActivity = this.getActivity();
// mKeyBytes = getArguments().getByteArray(ARG_IMPORT_DATA);
// mImportFilename = getArguments().getString(ARG_IMPORT_FILENAME);
mActivity = getActivity();
// register long press context menu
registerForContextMenu(getListView());
@@ -109,11 +82,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements
setEmptyText(mActivity.getString(R.string.error_nothingImport));
// Create an empty adapter we will use to display the loaded data.
String[] from = new String[] {};
int[] to = new int[] {};
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
mAdapter = new SimpleAdapter(getActivity(), data, android.R.layout.two_line_list_item,
from, to);
mAdapter = new ImportKeysAdapter(getActivity());
setListAdapter(mAdapter);
// Start out with a progress indicator.
@@ -124,39 +93,37 @@ public class ImportKeysListFragment extends SherlockListFragment implements
getLoaderManager().initLoader(0, null, this);
}
public void load(byte[] importData, String importFilename) {
mKeyBytes = importData;
mImportFilename = importFilename;
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
getLoaderManager().initLoader(0, null, this);
// Select checkbox!
// Update underlying data and notify adapter of change. The adapter will
// update the view automatically.
ImportKeysListEntry entry = mAdapter.getItem(position);
entry.setSelected(!entry.isSelected());
mAdapter.notifyDataSetChanged();
}
public void load(byte[] importData, String importFilename) {
this.mKeyBytes = importData;
this.mImportFilename = importFilename;
}
@Override
public Loader<List<Map<String, String>>> onCreateLoader(int id, Bundle args) {
public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) {
return new ImportKeysListLoader(mActivity, mKeyBytes, mImportFilename);
}
@Override
public void onLoadFinished(Loader<List<Map<String, String>>> loader,
List<Map<String, String>> data) {
// Set the new data in the adapter.
// for (String item : data) {
// mAdapter.add(item);
// }
public void onLoadFinished(Loader<List<ImportKeysListEntry>> loader,
List<ImportKeysListEntry> data) {
Log.d(Constants.TAG, "data: " + data);
// TODO: real swapping the data to the already defined adapter doesn't work
// Workaround: recreate adapter!
// http://stackoverflow.com/questions/2356091/android-add-function-of-arrayadapter-not-working
// mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.two_line_list_item,
// data);
String[] from = new String[] { ImportKeysListLoader.MAP_ATTR_USER_ID,
ImportKeysListLoader.MAP_ATTR_FINGERPINT };
int[] to = new int[] { android.R.id.text1, android.R.id.text2 };
mAdapter = new SimpleAdapter(getActivity(), data, android.R.layout.two_line_list_item,
from, to);
// swap in the real data!
mAdapter.setData(data);
mAdapter.notifyDataSetChanged();
setListAdapter(mAdapter);
// The list should now be shown.
@@ -168,10 +135,9 @@ public class ImportKeysListFragment extends SherlockListFragment implements
}
@Override
public void onLoaderReset(Loader<List<Map<String, String>>> loader) {
public void onLoaderReset(Loader<List<ImportKeysListEntry>> loader) {
// Clear the data in the adapter.
// Not available in SimpleAdapter!
// mAdapter.clear();
mAdapter.clear();
}
}

View File

@@ -19,13 +19,17 @@ package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.R;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ImportKeysServerFragment extends Fragment {
private Button mButton;
/**
* Creates new instance of this fragment
@@ -44,8 +48,19 @@ public class ImportKeysServerFragment extends Fragment {
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.import_keys_keyserver_fragment, container, false);
View view = inflater.inflate(R.layout.import_keys_keyserver_fragment, container, false);
mButton = (Button) view.findViewById(R.id.import_keyserver_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO: use fragment instead of activity, handle onresult here!
startActivityForResult(new Intent(getActivity(), KeyServerQueryActivity.class), 0);
}
});
return view;
}
}

View File

@@ -23,7 +23,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.ui.widget.KeyListAdapter;
import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
import org.sufficientlysecure.keychain.R;
import android.content.Intent;

View File

@@ -22,7 +22,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.widget.KeyListAdapter;
import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
import android.database.Cursor;
import android.net.Uri;

View File

@@ -140,7 +140,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
if (ACTION_LOOK_UP_KEY_ID.equals(action) || ACTION_LOOK_UP_KEY_ID_AND_RETURN.equals(action)) {
long keyId = intent.getLongExtra(EXTRA_KEY_ID, 0);
if (keyId != 0) {
String query = "0x" + PgpKeyHelper.keyToHex(keyId);
String query = "0x" + PgpKeyHelper.convertKeyToHex(keyId);
mQuery.setText(query);
search(query);
}
@@ -308,7 +308,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
mainUserId.setText(userId);
}
keyId.setText(PgpKeyHelper.getSmallFingerPrint(keyInfo.keyId));
keyId.setText(PgpKeyHelper.convertKeyIdToHex(keyInfo.keyId));
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);

View File

@@ -28,7 +28,7 @@ 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.widget.SelectKeyCursorAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
import android.app.Activity;
import android.database.Cursor;

View File

@@ -26,7 +26,7 @@ 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.widget.SelectKeyCursorAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
import android.database.Cursor;
import android.net.Uri;

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.adapter;
import java.util.List;
import org.sufficientlysecure.keychain.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
protected LayoutInflater mInflater;
protected Activity mActivity;
protected List<ImportKeysListEntry> data;
public ImportKeysAdapter(Activity activity) {
super(activity, -1);
mActivity = activity;
mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@SuppressLint("NewApi")
public void setData(List<ImportKeysListEntry> data) {
clear();
if (data != null) {
if (Build.VERSION.SDK_INT >= 11) {
addAll(data);
} else {
for (ImportKeysListEntry entry : data) {
add(entry);
}
}
this.data = data;
}
}
public List<ImportKeysListEntry> getData() {
return data;
}
@Override
public boolean hasStableIds() {
return true;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImportKeysListEntry entry = data.get(position);
View view = mInflater.inflate(R.layout.import_keys_list_entry, null);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.noKey);
TextView fingerprint = (TextView) view.findViewById(R.id.fingerprint);
TextView algorithm = (TextView) view.findViewById(R.id.algorithm);
algorithm.setText("");
TextView status = (TextView) view.findViewById(R.id.status);
status.setText("");
String userId = entry.userIds.get(0);
if (userId != null) {
String chunks[] = userId.split(" <", 2);
userId = chunks[0];
if (chunks.length > 1) {
mainUserIdRest.setText("<" + chunks[1]);
}
if (entry.secretKey) {
userId = mActivity.getString(R.string.secretKey) + " " + userId;
mainUserId.setTextColor(Color.RED);
}
mainUserId.setText(userId);
}
keyId.setText(entry.hexKeyId);
fingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm);
if (entry.revoked) {
status.setText("revoked");
} else {
status.setVisibility(View.GONE);
}
LinearLayout ll = (LinearLayout) view.findViewById(R.id.list);
if (entry.userIds.size() == 1) {
ll.setVisibility(View.GONE);
} else {
boolean first = true;
boolean second = true;
for (String uid : entry.userIds) {
if (first) {
first = false;
continue;
}
if (!second) {
View sep = new View(mActivity);
sep.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1));
sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark);
ll.addView(sep);
}
TextView uidView = (TextView) mInflater.inflate(
R.layout.import_keys_list_entry_user_id, null);
uidView.setText(uid);
ll.addView(uidView);
second = false;
}
}
CheckBox cBox = (CheckBox) view.findViewById(R.id.selected);
cBox.setChecked(entry.isSelected());
return view;
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.adapter;
import java.io.Serializable;
import java.util.ArrayList;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.AlgorithmNames;
import org.sufficientlysecure.keychain.util.IterableIterator;
public class ImportKeysListEntry implements Serializable {
private static final long serialVersionUID = -7797972103284992662L;
public ArrayList<String> userIds;
public long keyId;
public boolean revoked;
// public Date date;
public String fingerPrint;
public String hexKeyId;
public int bitStrength;
public String algorithm;
public boolean secretKey;
AlgorithmNames algorithmNames;
private boolean selected;
/**
* Constructor for later querying from keyserver
*/
public ImportKeysListEntry() {
secretKey = false;
userIds = new ArrayList<String>();
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
/**
* Constructor based on key object, used for import from NFC, QR Codes, files
*
* @param pgpKey
*/
@SuppressWarnings("unchecked")
public ImportKeysListEntry(PGPKeyRing pgpKeyRing) {
// selected is default
this.selected = true;
if (pgpKeyRing instanceof PGPSecretKeyRing) {
secretKey = true;
} else {
secretKey = false;
}
userIds = new ArrayList<String>();
for (String userId : new IterableIterator<String>(pgpKeyRing.getPublicKey().getUserIDs())) {
userIds.add(userId);
}
this.keyId = pgpKeyRing.getPublicKey().getKeyID();
this.revoked = pgpKeyRing.getPublicKey().isRevoked();
this.fingerPrint = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey()
.getFingerprint());
this.hexKeyId = PgpKeyHelper.convertKeyIdToHex(keyId);
this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength();
int algorithm = pgpKeyRing.getPublicKey().getAlgorithm();
if (algorithm == PGPPublicKey.RSA_ENCRYPT || algorithm == PGPPublicKey.RSA_GENERAL
|| algorithm == PGPPublicKey.RSA_SIGN) {
this.algorithm = "RSA";
} else if (algorithm == PGPPublicKey.DSA) {
this.algorithm = "DSA";
} else if (algorithm == PGPPublicKey.ELGAMAL_ENCRYPT
|| algorithm == PGPPublicKey.ELGAMAL_GENERAL) {
this.algorithm = "ElGamal";
} else if (algorithm == PGPPublicKey.EC || algorithm == PGPPublicKey.ECDSA) {
this.algorithm = "ECC";
} else {
// TODO: with resources
this.algorithm = "unknown";
}
}
}

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.widget;
package org.sufficientlysecure.keychain.ui.adapter;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -23,32 +23,23 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import org.sufficientlysecure.keychain.R;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, String>>> {
public static final String MAP_ATTR_USER_ID = "user_id";
public static final String MAP_ATTR_FINGERPINT = "fingerprint";
ArrayList<Map<String, String>> data = new ArrayList<Map<String, String>>();
public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
Context mContext;
List<String> mItems;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
byte[] mKeyringBytes;
String mImportFilename;
@@ -61,7 +52,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
}
@Override
public List<Map<String, String>> loadInBackground() {
public List<ImportKeysListEntry> loadInBackground() {
InputData inputData = null;
if (mKeyringBytes != null) {
inputData = new InputData(new ByteArrayInputStream(mKeyringBytes), mKeyringBytes.length);
@@ -76,7 +67,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
return data;
}
generateListOfKeyrings(inputData);
if (inputData != null)
generateListOfKeyrings(inputData);
return data;
}
@@ -100,12 +92,12 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
}
@Override
public void deliverResult(List<Map<String, String>> data) {
public void deliverResult(List<ImportKeysListEntry> data) {
super.deliverResult(data);
}
/**
* Similar to PGPMain.importKeyRings
* Reads all PGPKeyRing objects from input
*
* @param keyringBytes
* @return
@@ -144,20 +136,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
}
private void addToData(PGPKeyRing keyring) {
String userId = PgpKeyHelper.getMainUserId(keyring.getPublicKey());
if (keyring instanceof PGPSecretKeyRing) {
userId = mContext.getString(R.string.secretKeyring) + " " + userId;
}
String fingerprint = PgpKeyHelper.convertFingerprintToHex(keyring.getPublicKey()
.getFingerprint());
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(MAP_ATTR_USER_ID, userId);
attrs.put(MAP_ATTR_FINGERPINT, mContext.getString(R.string.fingerprint) + "\n"
+ fingerprint);
data.add(attrs);
ImportKeysListEntry item = new ImportKeysListEntry(keyring);
data.add(item);
}
}

View File

@@ -79,7 +79,7 @@ public class LookupUnknownKeyDialogFragment extends DialogFragment {
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.title_unknownSignatureKey);
alert.setMessage(getString(R.string.lookupUnknownKey,
PgpKeyHelper.getSmallFingerPrint(unknownKeyId)));
PgpKeyHelper.convertKeyIdToHex(unknownKeyId)));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

View File

@@ -152,8 +152,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
}
mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(key));
String keyId1Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID());
String keyId2Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID() >> 32);
String keyId1Str = PgpKeyHelper.convertKeyIdToHex(key.getKeyID());
String keyId2Str = PgpKeyHelper.convertKeyIdToHex(key.getKeyID() >> 32);
mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<Choice> choices = new Vector<Choice>();

View File

@@ -1,273 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sufficientlysecure.keychain.ui.widget;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorTreeAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class KeyListAdapter extends CursorTreeAdapter {
private Context mContext;
private LayoutInflater mInflater;
protected int mKeyType;
private static final int CHILD_KEY = 0;
private static final int CHILD_USER_ID = 1;
private static final int CHILD_FINGERPRINT = 2;
public KeyListAdapter(Context context, Cursor groupCursor, int keyType) {
super(groupCursor, context);
mContext = context;
mInflater = LayoutInflater.from(context);
mKeyType = keyType;
}
/**
* Inflate new view for group items
*/
@Override
public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_group_item, null);
}
/**
* Binds TextViews from group view to results from database group cursor.
*/
@Override
protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = cursor.getString(userIdIndex);
if (userId != null) {
String[] userIdSplit = OtherHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
}
mainUserId.setText(userIdSplit[0]);
}
if (mainUserId.getText().length() == 0) {
mainUserId.setText(R.string.unknownUserId);
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
} else {
mainUserIdRest.setVisibility(View.VISIBLE);
}
}
/**
* Inflate new view for child items
*/
@Override
public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_child_item, null);
}
/**
* Bind TextViews from view of childs based on query results
*/
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
LinearLayout keyLayout = (LinearLayout) view.findViewById(R.id.keyLayout);
LinearLayout userIdLayout = (LinearLayout) view.findViewById(R.id.userIdLayout);
// first entry is fingerprint
if (cursor.getPosition() == 0) {
// show only userId layout
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String fingerprint = PgpKeyHelper.getFingerPrint(context,
cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
fingerprint = fingerprint.replace(" ", "\n");
TextView userId = (TextView) view.findViewById(R.id.userId);
if (userId == null) {
Log.d(Constants.TAG, "userId is null!");
}
userId.setText(context.getString(R.string.fingerprint) + "\n" + fingerprint);
} else {
// differentiate between keys and userIds in MergeCursor
if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
keyLayout.setVisibility(View.VISIBLE);
userIdLayout.setVisibility(View.GONE);
String keyIdStr = PgpKeyHelper.getSmallFingerPrint(cursor.getLong(cursor
.getColumnIndex(Keys.KEY_ID)));
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(keyIdStr);
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
keyDetails.setText("(" + algorithmStr + ")");
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
masterKeyIcon.setVisibility(View.INVISIBLE);
} else {
masterKeyIcon.setVisibility(View.VISIBLE);
}
ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
certifyIcon.setVisibility(View.GONE);
} else {
certifyIcon.setVisibility(View.VISIBLE);
}
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
encryptIcon.setVisibility(View.GONE);
} else {
encryptIcon.setVisibility(View.VISIBLE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
signIcon.setVisibility(View.GONE);
} else {
signIcon.setVisibility(View.VISIBLE);
}
} else {
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String userIdStr = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(userIdStr);
}
}
}
/**
* Given the group cursor, we start cursors for a fingerprint, keys, and userIds, which are
* merged together and build the child cursor
*/
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
final long keyRingRowId = groupCursor.getLong(groupCursor.getColumnIndex(BaseColumns._ID));
Cursor fingerprintCursor = getChildCursor(keyRingRowId, CHILD_FINGERPRINT);
Cursor keyCursor = getChildCursor(keyRingRowId, CHILD_KEY);
Cursor userIdCursor = getChildCursor(keyRingRowId, CHILD_USER_ID);
MergeCursor mergeCursor = new MergeCursor(new Cursor[] { fingerprintCursor, keyCursor,
userIdCursor });
Log.d(Constants.TAG, "mergeCursor:" + DatabaseUtils.dumpCursorToString(mergeCursor));
return mergeCursor;
}
/**
* This builds a cursor for a specific type of children
*
* @param keyRingRowId
* foreign row id of the keyRing
* @param type
* @return
*/
private Cursor getChildCursor(long keyRingRowId, int type) {
Uri uri = null;
String[] projection = null;
String sortOrder = null;
String selection = null;
switch (type) {
case CHILD_FINGERPRINT:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
// use only master key for fingerprint
selection = Keys.IS_MASTER_KEY + " = 1 ";
if (mKeyType == Id.type.public_key) {
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
} else {
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
}
break;
case CHILD_KEY:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
if (mKeyType == Id.type.public_key) {
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
} else {
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
}
break;
case CHILD_USER_ID:
projection = new String[] { UserIds._ID, UserIds.USER_ID, UserIds.RANK, };
sortOrder = UserIds.RANK + " ASC";
// not the main user id
selection = UserIds.RANK + " > 0 ";
if (mKeyType == Id.type.public_key) {
uri = UserIds.buildPublicUserIdsUri(String.valueOf(keyRingRowId));
} else {
uri = UserIds.buildSecretUserIdsUri(String.valueOf(keyRingRowId));
}
break;
default:
return null;
}
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
}
}

View File

@@ -1,140 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.widget;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.R;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
public class SelectKeyCursorAdapter extends CursorAdapter {
protected int mKeyType;
private LayoutInflater mInflater;
private ListView mListView;
public final static String PROJECTION_ROW_AVAILABLE = "available";
public final static String PROJECTION_ROW_VALID = "valid";
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
int keyType) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
mListView = listView;
mKeyType = keyType;
}
public String getUserId(int position) {
mCursor.moveToPosition(position);
return mCursor.getString(mCursor.getColumnIndex(UserIds.USER_ID));
}
public long getMasterKeyId(int position) {
mCursor.moveToPosition(position);
return mCursor.getLong(mCursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
boolean valid = cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_VALID)) > 0;
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknownUserId);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(R.string.noKey);
TextView status = (TextView) view.findViewById(R.id.status);
status.setText(R.string.unknownStatus);
String userId = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
if (userId != null) {
String[] userIdSplit = OtherHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
}
mainUserId.setText(userIdSplit[0]);
}
long masterKeyId = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
keyId.setText(PgpKeyHelper.getSmallFingerPrint(masterKeyId));
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
}
if (valid) {
if (mKeyType == Id.type.public_key) {
status.setText(R.string.canEncrypt);
} else {
status.setText(R.string.canSign);
}
} else {
if (cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_AVAILABLE)) > 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.noKey);
}
}
CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
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);
}
status.setText(status.getText() + " ");
view.setEnabled(valid);
mainUserId.setEnabled(valid);
mainUserIdRest.setEnabled(valid);
keyId.setEnabled(valid);
status.setEnabled(valid);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.select_key_item, null);
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.util;
import java.util.HashMap;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import android.annotation.SuppressLint;
import android.app.Activity;
@SuppressLint("UseSparseArrays")
public class AlgorithmNames {
Activity mActivity;
HashMap<Integer, String> mEncryptionNames = new HashMap<Integer, String>();
HashMap<Integer, String> mHashNames = new HashMap<Integer, String>();
HashMap<Integer, String> mCompressionNames = new HashMap<Integer, String>();
public AlgorithmNames(Activity context) {
super();
this.mActivity = context;
mEncryptionNames.put(PGPEncryptedData.AES_128, "AES-128");
mEncryptionNames.put(PGPEncryptedData.AES_192, "AES-192");
mEncryptionNames.put(PGPEncryptedData.AES_256, "AES-256");
mEncryptionNames.put(PGPEncryptedData.BLOWFISH, "Blowfish");
mEncryptionNames.put(PGPEncryptedData.TWOFISH, "Twofish");
mEncryptionNames.put(PGPEncryptedData.CAST5, "CAST5");
mEncryptionNames.put(PGPEncryptedData.DES, "DES");
mEncryptionNames.put(PGPEncryptedData.TRIPLE_DES, "Triple DES");
mEncryptionNames.put(PGPEncryptedData.IDEA, "IDEA");
mHashNames.put(HashAlgorithmTags.MD5, "MD5");
mHashNames.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160");
mHashNames.put(HashAlgorithmTags.SHA1, "SHA-1");
mHashNames.put(HashAlgorithmTags.SHA224, "SHA-224");
mHashNames.put(HashAlgorithmTags.SHA256, "SHA-256");
mHashNames.put(HashAlgorithmTags.SHA384, "SHA-384");
mHashNames.put(HashAlgorithmTags.SHA512, "SHA-512");
mCompressionNames.put(Id.choice.compression.none, mActivity.getString(R.string.choice_none)
+ " (" + mActivity.getString(R.string.fast) + ")");
mCompressionNames.put(Id.choice.compression.zip,
"ZIP (" + mActivity.getString(R.string.fast) + ")");
mCompressionNames.put(Id.choice.compression.zlib,
"ZLIB (" + mActivity.getString(R.string.fast) + ")");
mCompressionNames.put(Id.choice.compression.bzip2,
"BZIP2 (" + mActivity.getString(R.string.very_slow) + ")");
}
public HashMap<Integer, String> getEncryptionNames() {
return mEncryptionNames;
}
public void setEncryptionNames(HashMap<Integer, String> encryptionNames) {
this.mEncryptionNames = encryptionNames;
}
public HashMap<Integer, String> getHashNames() {
return mHashNames;
}
public void setHashNames(HashMap<Integer, String> hashNames) {
this.mHashNames = hashNames;
}
public HashMap<Integer, String> getCompressionNames() {
return mCompressionNames;
}
public void setCompressionNames(HashMap<Integer, String> compressionNames) {
this.mCompressionNames = compressionNames;
}
}

View File

@@ -179,8 +179,8 @@ public class HkpKeyServer extends KeyServer {
KeyInfo info = new KeyInfo();
info.size = Integer.parseInt(matcher.group(1));
info.algorithm = matcher.group(2);
info.keyId = PgpKeyHelper.keyFromHex(matcher.group(3));
info.fingerPrint = PgpKeyHelper.getSmallFingerPrint(info.keyId);
info.keyId = PgpKeyHelper.convertHexToKeyId(matcher.group(3));
info.fingerPrint = PgpKeyHelper.convertKeyIdToHex(info.keyId);
String chunks[] = matcher.group(4).split("-");
info.date = new GregorianCalendar(Integer.parseInt(chunks[0]),
Integer.parseInt(chunks[1]), Integer.parseInt(chunks[2])).getTime();
@@ -211,7 +211,7 @@ public class HkpKeyServer extends KeyServer {
HttpClient client = new DefaultHttpClient();
try {
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort
+ "/pks/lookup?op=get&search=0x" + PgpKeyHelper.keyToHex(keyId));
+ "/pks/lookup?op=get&search=0x" + PgpKeyHelper.convertKeyToHex(keyId));
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
@@ -235,13 +235,13 @@ public class HkpKeyServer extends KeyServer {
}
@Override
public void add(String armouredText) throws AddKeyException {
public void add(String armoredText) throws AddKeyException {
HttpClient client = new DefaultHttpClient();
try {
HttpPost post = new HttpPost("http://" + mHost + ":" + mPort + "/pks/add");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("keytext", armouredText));
nameValuePairs.add(new BasicNameValuePair("keytext", armoredText));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.util;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import android.content.Context;
import android.widget.ArrayAdapter;
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
private final HashMap<Integer, String> mData;
private final int[] mKeys;
private final String[] mValues;
static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(
Map<K, V> map) {
SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
public KeyValueSpinnerAdapter(Context context, HashMap<Integer, String> objects) {
// To make the drop down a simple text box
super(context, android.R.layout.simple_spinner_item);
mData = objects;
// To make the drop down view a radio button list
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
SortedSet<Map.Entry<Integer, String>> sorted = entriesSortedByValues(objects);
// Assign hash keys with a position so that we can present and retrieve them
int i = 0;
mKeys = new int[mData.size()];
mValues = new String[mData.size()];
for (Map.Entry<Integer, String> entry : sorted) {
mKeys[i] = entry.getKey();
mValues[i] = entry.getValue();
i++;
}
}
public int getCount() {
return mData.size();
}
/**
* Returns the value
*/
@Override
public String getItem(int position) {
// return the value based on the position. This is displayed in the list.
return mValues[position];
}
/**
* Returns item key
*/
public long getItemId(int position) {
// Return an id to represent the item.
return mKeys[position];
}
/**
* Find position from key
*/
public int getPosition(long itemId) {
for (int i = 0; i < mKeys.length; i++) {
if ((int) itemId == mKeys[i]) {
return i;
}
}
return -1;
}
}