fixes to clipboard management

This commit is contained in:
Dominik 2012-03-09 15:41:31 +01:00
parent 7a2e1e42d9
commit df6933bfb8
5 changed files with 592 additions and 552 deletions

View File

@ -20,6 +20,7 @@ import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.provider.DataProvider; import org.thialfihar.android.apg.provider.DataProvider;
import org.thialfihar.android.apg.utils.Compatibility;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
@ -29,7 +30,6 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.text.ClipboardManager;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -111,9 +111,9 @@ public class DecryptActivity extends BaseActivity {
mSourcePrevious.setOnClickListener(new OnClickListener() { mSourcePrevious.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this,
R.anim.push_right_in)); R.anim.push_right_in));
mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this,
R.anim.push_right_out)); R.anim.push_right_out));
mSource.showPrevious(); mSource.showPrevious();
updateSource(); updateSource();
} }
@ -123,9 +123,9 @@ public class DecryptActivity extends BaseActivity {
OnClickListener nextSourceClickListener = new OnClickListener() { OnClickListener nextSourceClickListener = new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this,
R.anim.push_left_in)); R.anim.push_left_in));
mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this,
R.anim.push_left_out)); R.anim.push_left_out));
mSource.showNext(); mSource.showNext();
updateSource(); updateSource();
} }
@ -275,18 +275,22 @@ public class DecryptActivity extends BaseActivity {
mReturnResult = true; mReturnResult = true;
} }
if (mSource.getCurrentView().getId() == R.id.sourceMessage && if (mSource.getCurrentView().getId() == R.id.sourceMessage
mMessage.getText().length() == 0) { && mMessage.getText().length() == 0) {
ClipboardManager clip = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
CharSequence clipboardText = Compatibility.getClipboardText(this);
String data = ""; String data = "";
Matcher matcher = Apg.PGP_MESSAGE.matcher(clip.getText()); if (clipboardText != null) {
if (!matcher.matches()) { Matcher matcher = Apg.PGP_MESSAGE.matcher(clipboardText);
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(clip.getText()); if (!matcher.matches()) {
} matcher = Apg.PGP_SIGNED_MESSAGE.matcher(clipboardText);
if (matcher.matches()) { }
data = matcher.group(1); if (matcher.matches()) {
mMessage.setText(data); data = matcher.group(1);
Toast.makeText(this, R.string.usingClipboardContent, Toast.LENGTH_SHORT).show(); mMessage.setText(data);
Toast.makeText(this, R.string.usingClipboardContent, Toast.LENGTH_SHORT).show();
}
} }
} }
@ -334,9 +338,9 @@ public class DecryptActivity extends BaseActivity {
updateSource(); updateSource();
if (mSource.getCurrentView().getId() == R.id.sourceMessage && if (mSource.getCurrentView().getId() == R.id.sourceMessage
(mMessage.getText().length() > 0 || mData != null || mContentUri != null)) { && (mMessage.getText().length() > 0 || mData != null || mContentUri != null)) {
mDecryptButton.performClick(); mDecryptButton.performClick();
} }
} }
@ -369,21 +373,21 @@ public class DecryptActivity extends BaseActivity {
private void updateSource() { private void updateSource() {
switch (mSource.getCurrentView().getId()) { switch (mSource.getCurrentView().getId()) {
case R.id.sourceFile: { case R.id.sourceFile: {
mSourceLabel.setText(R.string.label_file); mSourceLabel.setText(R.string.label_file);
mDecryptButton.setText(R.string.btn_decrypt); mDecryptButton.setText(R.string.btn_decrypt);
break; break;
} }
case R.id.sourceMessage: { case R.id.sourceMessage: {
mSourceLabel.setText(R.string.label_message); mSourceLabel.setText(R.string.label_message);
mDecryptButton.setText(R.string.btn_decrypt); mDecryptButton.setText(R.string.btn_decrypt);
break; break;
} }
default: { default: {
break; break;
} }
} }
} }
@ -411,9 +415,10 @@ public class DecryptActivity extends BaseActivity {
if (mInputFilename.startsWith("file")) { if (mInputFilename.startsWith("file")) {
File file = new File(mInputFilename); File file = new File(mInputFilename);
if (!file.exists() || !file.isFile()) { if (!file.exists() || !file.isFile()) {
Toast.makeText(this, getString(R.string.errorMessage, Toast.makeText(
getString(R.string.error_fileNotFound)), this,
Toast.LENGTH_SHORT).show(); getString(R.string.errorMessage, getString(R.string.error_fileNotFound)),
Toast.LENGTH_SHORT).show();
return; return;
} }
} }
@ -450,8 +455,8 @@ public class DecryptActivity extends BaseActivity {
mAssumeSymmetricEncryption = true; mAssumeSymmetricEncryption = true;
} }
if (getSecretKeyId() == Id.key.symmetric || if (getSecretKeyId() == Id.key.symmetric
Apg.getCachedPassPhrase(getSecretKeyId()) == null) { || Apg.getCachedPassPhrase(getSecretKeyId()) == null) {
showDialog(Id.dialog.pass_phrase); showDialog(Id.dialog.pass_phrase);
} else { } else {
if (mDecryptTarget == Id.target.file) { if (mDecryptTarget == Id.target.file) {
@ -468,8 +473,8 @@ public class DecryptActivity extends BaseActivity {
error = "" + e; error = "" + e;
} }
if (error != null) { if (error != null) {
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT)
Toast.LENGTH_SHORT).show(); .show();
} }
} }
@ -522,22 +527,22 @@ public class DecryptActivity extends BaseActivity {
if (mSignedOnly) { if (mSignedOnly) {
data = Apg.verifyText(this, in, out, this); data = Apg.verifyText(this, in, out, this);
} else { } else {
data = Apg.decrypt(this, in, out, Apg.getCachedPassPhrase(getSecretKeyId()), data = Apg.decrypt(this, in, out, Apg.getCachedPassPhrase(getSecretKeyId()), this,
this, mAssumeSymmetricEncryption); mAssumeSymmetricEncryption);
} }
out.close(); out.close();
if (mDataDestination.getStreamFilename() != null) { if (mDataDestination.getStreamFilename() != null) {
data.putString(Apg.EXTRA_RESULT_URI, "content://" + DataProvider.AUTHORITY + data.putString(Apg.EXTRA_RESULT_URI, "content://" + DataProvider.AUTHORITY
"/data/" + mDataDestination.getStreamFilename()); + "/data/" + mDataDestination.getStreamFilename());
} else if (mDecryptTarget == Id.target.message) { } else if (mDecryptTarget == Id.target.message) {
if (mReturnBinary) { if (mReturnBinary) {
data.putByteArray(Apg.EXTRA_DECRYPTED_DATA, data.putByteArray(Apg.EXTRA_DECRYPTED_DATA,
((ByteArrayOutputStream) out).toByteArray()); ((ByteArrayOutputStream) out).toByteArray());
} else { } else {
data.putString(Apg.EXTRA_DECRYPTED_MESSAGE, data.putString(Apg.EXTRA_DECRYPTED_MESSAGE, new String(
new String(((ByteArrayOutputStream) out).toByteArray())); ((ByteArrayOutputStream) out).toByteArray()));
} }
} }
} catch (PGPException e) { } catch (PGPException e) {
@ -588,7 +593,8 @@ public class DecryptActivity extends BaseActivity {
String error = data.getString(Apg.EXTRA_ERROR); String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) { if (error != null) {
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT)
.show();
return; return;
} }
@ -602,26 +608,26 @@ public class DecryptActivity extends BaseActivity {
} }
switch (mDecryptTarget) { switch (mDecryptTarget) {
case Id.target.message: { case Id.target.message: {
String decryptedMessage = data.getString(Apg.EXTRA_DECRYPTED_MESSAGE); String decryptedMessage = data.getString(Apg.EXTRA_DECRYPTED_MESSAGE);
mMessage.setText(decryptedMessage); mMessage.setText(decryptedMessage);
mMessage.setHorizontallyScrolling(false); mMessage.setHorizontallyScrolling(false);
mReplyButton.setVisibility(View.VISIBLE); mReplyButton.setVisibility(View.VISIBLE);
break; break;
} }
case Id.target.file: { case Id.target.file: {
if (mDeleteAfter.isChecked()) { if (mDeleteAfter.isChecked()) {
setDeleteFile(mInputFilename); setDeleteFile(mInputFilename);
showDialog(Id.dialog.delete_file); showDialog(Id.dialog.delete_file);
}
break;
} }
break;
}
default: { default: {
// shouldn't happen // shouldn't happen
break; break;
} }
} }
if (data.getBoolean(Apg.EXTRA_SIGNATURE)) { if (data.getBoolean(Apg.EXTRA_SIGNATURE)) {
@ -642,7 +648,8 @@ public class DecryptActivity extends BaseActivity {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
} else if (data.getBoolean(Apg.EXTRA_SIGNATURE_UNKNOWN)) { } else if (data.getBoolean(Apg.EXTRA_SIGNATURE_UNKNOWN)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
Toast.makeText(this, R.string.unknownSignatureKeyTouchToLookUp, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.unknownSignatureKeyTouchToLookUp, Toast.LENGTH_LONG)
.show();
} else { } else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
} }
@ -653,51 +660,51 @@ public class DecryptActivity extends BaseActivity {
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case Id.request.filename: { case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString(); String filename = data.getDataString();
if (filename != null) { if (filename != null) {
// Get rid of URI prefix: // Get rid of URI prefix:
if (filename.startsWith("file://")) { if (filename.startsWith("file://")) {
filename = filename.substring(7); filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
mFilename.setText(filename);
} }
// replace %20 and so on
filename = Uri.decode(filename);
mFilename.setText(filename);
} }
return;
} }
return;
}
case Id.request.output_filename: { case Id.request.output_filename: {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString(); String filename = data.getDataString();
if (filename != null) { if (filename != null) {
// Get rid of URI prefix: // Get rid of URI prefix:
if (filename.startsWith("file://")) { if (filename.startsWith("file://")) {
filename = filename.substring(7); filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
FileDialog.setFilename(filename);
} }
} // replace %20 and so on
return; filename = Uri.decode(filename);
}
case Id.request.look_up_key_id: { FileDialog.setFilename(filename);
PausableThread thread = getRunningThread();
if (thread != null && thread.isPaused()) {
thread.unpause();
} }
return;
} }
return;
}
default: { case Id.request.look_up_key_id: {
break; PausableThread thread = getRunningThread();
if (thread != null && thread.isPaused()) {
thread.unpause();
} }
return;
}
default: {
break;
}
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
@ -706,63 +713,57 @@ public class DecryptActivity extends BaseActivity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case Id.dialog.output_filename: { case Id.dialog.output_filename: {
return FileDialog.build(this, getString(R.string.title_decryptToFile), return FileDialog.build(this, getString(R.string.title_decryptToFile),
getString(R.string.specifyFileToDecryptTo), getString(R.string.specifyFileToDecryptTo), mOutputFilename,
mOutputFilename, new FileDialog.OnClickListener() {
new FileDialog.OnClickListener() { public void onOkClick(String filename, boolean checked) {
public void onOkClick(String filename, boolean checked) { removeDialog(Id.dialog.output_filename);
removeDialog(Id.dialog.output_filename); mOutputFilename = filename;
mOutputFilename = filename; decryptStart();
decryptStart(); }
}
public void onCancelClick() { public void onCancelClick() {
removeDialog(Id.dialog.output_filename); removeDialog(Id.dialog.output_filename);
} }
}, }, getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_titleSave), getString(R.string.filemanager_btnSave), null, Id.request.output_filename);
getString(R.string.filemanager_btnSave), }
null,
Id.request.output_filename);
}
case Id.dialog.lookup_unknown_key: { case Id.dialog.lookup_unknown_key: {
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert); alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.title_unknownSignatureKey); alert.setTitle(R.string.title_unknownSignatureKey);
alert.setMessage(getString(R.string.lookupUnknownKey, Apg.getSmallFingerPrint(mUnknownSignatureKeyId))); alert.setMessage(getString(R.string.lookupUnknownKey,
Apg.getSmallFingerPrint(mUnknownSignatureKeyId)));
alert.setPositiveButton(android.R.string.ok, alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) {
public void onClick(DialogInterface dialog, int id) { removeDialog(Id.dialog.lookup_unknown_key);
removeDialog(Id.dialog.lookup_unknown_key); Intent intent = new Intent(DecryptActivity.this, KeyServerQueryActivity.class);
Intent intent = new Intent(DecryptActivity.this, intent.setAction(Apg.Intent.LOOK_UP_KEY_ID);
KeyServerQueryActivity.class); intent.putExtra(Apg.EXTRA_KEY_ID, mUnknownSignatureKeyId);
intent.setAction(Apg.Intent.LOOK_UP_KEY_ID); startActivityForResult(intent, Id.request.look_up_key_id);
intent.putExtra(Apg.EXTRA_KEY_ID, mUnknownSignatureKeyId); }
startActivityForResult(intent, Id.request.look_up_key_id); });
} alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
}); public void onClick(DialogInterface dialog, int id) {
alert.setNegativeButton(android.R.string.cancel, removeDialog(Id.dialog.lookup_unknown_key);
new DialogInterface.OnClickListener() { PausableThread thread = getRunningThread();
public void onClick(DialogInterface dialog, int id) { if (thread != null && thread.isPaused()) {
removeDialog(Id.dialog.lookup_unknown_key); thread.unpause();
PausableThread thread = getRunningThread(); }
if (thread != null && thread.isPaused()) { }
thread.unpause(); });
} alert.setCancelable(true);
}
});
alert.setCancelable(true);
return alert.create(); return alert.create();
} }
default: { default: {
break; break;
} }
} }
return super.onCreateDialog(id); return super.onCreateDialog(id);

View File

@ -23,6 +23,7 @@ import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.provider.DataProvider; import org.thialfihar.android.apg.provider.DataProvider;
import org.thialfihar.android.apg.utils.Choice; import org.thialfihar.android.apg.utils.Choice;
import org.thialfihar.android.apg.utils.Compatibility;
import android.app.Dialog; import android.app.Dialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
@ -30,7 +31,6 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.text.ClipboardManager;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils; import android.view.animation.AnimationUtils;
@ -881,8 +881,7 @@ public class EncryptActivity extends BaseActivity {
switch (mEncryptTarget) { switch (mEncryptTarget) {
case Id.target.clipboard: { case Id.target.clipboard: {
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE); String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
ClipboardManager clip = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); Compatibility.copyToClipboard(this, message);
clip.setText(message);
Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.makeText(this, R.string.encryptionToClipboardSuccessful,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
break; break;

View File

@ -23,9 +23,6 @@ import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds; import org.thialfihar.android.apg.provider.UserIds;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.SearchManager; import android.app.SearchManager;
@ -143,19 +140,19 @@ public class KeyListActivity extends BaseActivity {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case Id.menu.option.import_keys: { case Id.menu.option.import_keys: {
showDialog(Id.dialog.import_keys); showDialog(Id.dialog.import_keys);
return true; return true;
} }
case Id.menu.option.export_keys: { case Id.menu.option.export_keys: {
showDialog(Id.dialog.export_keys); showDialog(Id.dialog.export_keys);
return true; return true;
} }
default: { default: {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
} }
@ -170,21 +167,21 @@ public class KeyListActivity extends BaseActivity {
} }
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case Id.menu.export: { case Id.menu.export: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(Id.dialog.export_key); showDialog(Id.dialog.export_key);
return true; return true;
} }
case Id.menu.delete: { case Id.menu.delete: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
showDialog(Id.dialog.delete_key); showDialog(Id.dialog.delete_key);
return true; return true;
} }
default: { default: {
return super.onContextItemSelected(menuItem); return super.onContextItemSelected(menuItem);
} }
} }
} }
@ -193,101 +190,94 @@ public class KeyListActivity extends BaseActivity {
boolean singleKeyExport = false; boolean singleKeyExport = false;
switch (id) { switch (id) {
case Id.dialog.delete_key: { case Id.dialog.delete_key: {
final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem); final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
mSelectedItem = -1; mSelectedItem = -1;
// TODO: better way to do this? // TODO: better way to do this?
String userId = "<unknown>"; String userId = "<unknown>";
Object keyRing = Apg.getKeyRing(keyRingId); Object keyRing = Apg.getKeyRing(keyRingId);
if (keyRing != null) { if (keyRing != null) {
if (keyRing instanceof PGPPublicKeyRing) { if (keyRing instanceof PGPPublicKeyRing) {
userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey((PGPPublicKeyRing) keyRing)); userId = Apg.getMainUserIdSafe(this,
} else { Apg.getMasterKey((PGPPublicKeyRing) keyRing));
userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey((PGPSecretKeyRing) keyRing)); } else {
} userId = Apg.getMainUserIdSafe(this,
Apg.getMasterKey((PGPSecretKeyRing) keyRing));
} }
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.warning);
builder.setMessage(getString(mKeyType == Id.type.public_key ?
R.string.keyDeletionConfirmation :
R.string.secretKeyDeletionConfirmation, userId));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setPositiveButton(R.string.btn_delete,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
deleteKey(keyRingId);
removeDialog(Id.dialog.delete_key);
}
});
builder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_key);
}
});
return builder.create();
} }
case Id.dialog.import_keys: { AlertDialog.Builder builder = new AlertDialog.Builder(this);
return FileDialog.build(this, getString(R.string.title_importKeys), builder.setTitle(R.string.warning);
getString(R.string.specifyFileToImportFrom), builder.setMessage(getString(
mImportFilename, mKeyType == Id.type.public_key ? R.string.keyDeletionConfirmation
new FileDialog.OnClickListener() { : R.string.secretKeyDeletionConfirmation, userId));
public void onOkClick(String filename, boolean checked) { builder.setIcon(android.R.drawable.ic_dialog_alert);
removeDialog(Id.dialog.import_keys); builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
mDeleteAfterImport = checked; public void onClick(DialogInterface dialog, int id) {
mImportFilename = filename; deleteKey(keyRingId);
importKeys(); removeDialog(Id.dialog.delete_key);
} }
});
builder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
removeDialog(Id.dialog.delete_key);
}
});
return builder.create();
}
public void onCancelClick() { case Id.dialog.import_keys: {
removeDialog(Id.dialog.import_keys); return FileDialog.build(this, getString(R.string.title_importKeys),
} getString(R.string.specifyFileToImportFrom), mImportFilename,
}, new FileDialog.OnClickListener() {
getString(R.string.filemanager_titleOpen), public void onOkClick(String filename, boolean checked) {
getString(R.string.filemanager_btnOpen), removeDialog(Id.dialog.import_keys);
getString(R.string.label_deleteAfterImport), mDeleteAfterImport = checked;
Id.request.filename); mImportFilename = filename;
} importKeys();
}
case Id.dialog.export_key: { public void onCancelClick() {
singleKeyExport = true; removeDialog(Id.dialog.import_keys);
// break intentionally omitted, to use the Id.dialog.export_keys dialog }
} }, getString(R.string.filemanager_titleOpen),
getString(R.string.filemanager_btnOpen),
getString(R.string.label_deleteAfterImport), Id.request.filename);
}
case Id.dialog.export_keys: { case Id.dialog.export_key: {
String title = (singleKeyExport ? singleKeyExport = true;
getString(R.string.title_exportKey) : // break intentionally omitted, to use the Id.dialog.export_keys dialog
getString(R.string.title_exportKeys)); }
final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys); case Id.dialog.export_keys: {
String title = (singleKeyExport ? getString(R.string.title_exportKey)
: getString(R.string.title_exportKeys));
return FileDialog.build(this, title, final int thisDialogId = (singleKeyExport ? Id.dialog.export_key
getString(mKeyType == Id.type.public_key ? : Id.dialog.export_keys);
R.string.specifyFileToExportTo :
R.string.specifyFileToExportSecretKeysTo),
mExportFilename,
new FileDialog.OnClickListener() {
public void onOkClick(String filename, boolean checked) {
removeDialog(thisDialogId);
mExportFilename = filename;
exportKeys();
}
public void onCancelClick() { return FileDialog.build(this, title,
removeDialog(thisDialogId); getString(mKeyType == Id.type.public_key ? R.string.specifyFileToExportTo
} : R.string.specifyFileToExportSecretKeysTo), mExportFilename,
}, new FileDialog.OnClickListener() {
getString(R.string.filemanager_titleSave), public void onOkClick(String filename, boolean checked) {
getString(R.string.filemanager_btnSave), removeDialog(thisDialogId);
null, mExportFilename = filename;
Id.request.filename); exportKeys();
} }
default: { public void onCancelClick() {
return super.onCreateDialog(id); removeDialog(thisDialogId);
} }
}, getString(R.string.filemanager_titleSave),
getString(R.string.filemanager_btnSave), null, Id.request.filename);
}
default: {
return super.onCreateDialog(id);
}
} }
} }
@ -328,13 +318,14 @@ public class KeyListActivity extends BaseActivity {
} }
if (mTask == Id.task.import_keys) { if (mTask == Id.task.import_keys) {
data = Apg.importKeyRings(this, mKeyType, new InputData(importInputStream, size), this); data = Apg.importKeyRings(this, mKeyType, new InputData(importInputStream, size),
this);
} else { } else {
Vector<Integer> keyRingIds = new Vector<Integer>(); Vector<Integer> keyRingIds = new Vector<Integer>();
if (mSelectedItem == -1) { if (mSelectedItem == -1) {
keyRingIds = Apg.getKeyRingIds(mKeyType == Id.type.public_key ? keyRingIds = Apg
Id.database.type_public : .getKeyRingIds(mKeyType == Id.type.public_key ? Id.database.type_public
Id.database.type_secret); : Id.database.type_secret);
} else { } else {
int keyRingId = mListAdapter.getKeyRingId(mSelectedItem); int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
keyRingIds.add(keyRingId); keyRingIds.add(keyRingId);
@ -386,82 +377,78 @@ public class KeyListActivity extends BaseActivity {
if (data != null) { if (data != null) {
int type = data.getInt(Constants.extras.status); int type = data.getInt(Constants.extras.status);
switch (type) { switch (type) {
case Id.message.import_done: { case Id.message.import_done: {
removeDialog(Id.dialog.importing); removeDialog(Id.dialog.importing);
String error = data.getString(Apg.EXTRA_ERROR); String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) { if (error != null) {
Toast.makeText(KeyListActivity.this, Toast.makeText(KeyListActivity.this, getString(R.string.errorMessage, error),
getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
Toast.LENGTH_SHORT).show(); } else {
int added = data.getInt("added");
int updated = data.getInt("updated");
int bad = data.getInt("bad");
String message;
if (added > 0 && updated > 0) {
message = getString(R.string.keysAddedAndUpdated, added, updated);
} else if (added > 0) {
message = getString(R.string.keysAdded, added);
} else if (updated > 0) {
message = getString(R.string.keysUpdated, updated);
} else { } else {
int added = data.getInt("added"); message = getString(R.string.noKeysAddedOrUpdated);
int updated = data.getInt("updated"); }
int bad = data.getInt("bad"); Toast.makeText(KeyListActivity.this, message, Toast.LENGTH_SHORT).show();
String message; if (bad > 0) {
if (added > 0 && updated > 0) { AlertDialog.Builder alert = new AlertDialog.Builder(this);
message = getString(R.string.keysAddedAndUpdated, added, updated);
} else if (added > 0) { alert.setIcon(android.R.drawable.ic_dialog_alert);
message = getString(R.string.keysAdded, added); alert.setTitle(R.string.warning);
} else if (updated > 0) { alert.setMessage(this.getString(R.string.badKeysEncountered, bad));
message = getString(R.string.keysUpdated, updated);
} else { alert.setPositiveButton(android.R.string.ok,
message = getString(R.string.noKeysAddedOrUpdated); new DialogInterface.OnClickListener() {
} public void onClick(DialogInterface dialog, int id) {
Toast.makeText(KeyListActivity.this, message, dialog.cancel();
Toast.LENGTH_SHORT).show(); }
if (bad > 0) { });
AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.setCancelable(true);
alert.create().show();
alert.setIcon(android.R.drawable.ic_dialog_alert); } else if (mDeleteAfterImport) {
alert.setTitle(R.string.warning); // everything went well, so now delete, if that was turned on
alert.setMessage(this.getString(R.string.badKeysEncountered, bad)); setDeleteFile(mImportFilename);
showDialog(Id.dialog.delete_file);
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
alert.setCancelable(true);
alert.create().show();
} else if (mDeleteAfterImport) {
// everything went well, so now delete, if that was turned on
setDeleteFile(mImportFilename);
showDialog(Id.dialog.delete_file);
}
} }
refreshList();
break;
} }
refreshList();
break;
}
case Id.message.export_done: { case Id.message.export_done: {
removeDialog(Id.dialog.exporting); removeDialog(Id.dialog.exporting);
String error = data.getString(Apg.EXTRA_ERROR); String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) { if (error != null) {
Toast.makeText(KeyListActivity.this, Toast.makeText(KeyListActivity.this, getString(R.string.errorMessage, error),
getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
Toast.LENGTH_SHORT).show(); } else {
int exported = data.getInt("exported");
String message;
if (exported == 1) {
message = getString(R.string.keyExported);
} else if (exported > 0) {
message = getString(R.string.keysExported, exported);
} else { } else {
int exported = data.getInt("exported"); message = getString(R.string.noKeysExported);
String message;
if (exported == 1) {
message = getString(R.string.keyExported);
} else if (exported > 0) {
message = getString(R.string.keysExported, exported);
} else{
message = getString(R.string.noKeysExported);
}
Toast.makeText(KeyListActivity.this, message,
Toast.LENGTH_SHORT).show();
} }
break; Toast.makeText(KeyListActivity.this, message, Toast.LENGTH_SHORT).show();
} }
break;
}
default: { default: {
break; break;
} }
} }
} }
} }
@ -489,7 +476,7 @@ public class KeyListActivity extends BaseActivity {
public String fingerPrint; public String fingerPrint;
public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize, public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize,
boolean canSign, boolean canEncrypt) { boolean canSign, boolean canEncrypt) {
this.type = KEY; this.type = KEY;
this.keyId = keyId; this.keyId = keyId;
this.isMasterKey = isMasterKey; this.isMasterKey = isMasterKey;
@ -516,22 +503,19 @@ public class KeyListActivity extends BaseActivity {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDatabase = Apg.getDatabase().db(); mDatabase = Apg.getDatabase().db();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "("
"(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "."
Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + + Keys.KEY_RING_ID + " AND " + Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY
Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + + " = '1'" + ") " + " INNER JOIN " + UserIds.TABLE_NAME + " ON " + "("
") " + + Keys.TABLE_NAME + "." + Keys._ID + " = " + UserIds.TABLE_NAME + "."
" INNER JOIN " + UserIds.TABLE_NAME + " ON " + + UserIds.KEY_ID + " AND " + UserIds.TABLE_NAME + "." + UserIds.RANK
"(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + + " = '0')");
UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " +
UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0')");
if (searchString != null && searchString.trim().length() > 0) { if (searchString != null && searchString.trim().length() > 0) {
String[] chunks = searchString.trim().split(" +"); String[] chunks = searchString.trim().split(" +");
qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + qb.appendWhere("EXISTS (SELECT tmp." + UserIds._ID + " FROM " + UserIds.TABLE_NAME
UserIds.TABLE_NAME + " AS tmp WHERE " + + " AS tmp WHERE " + "tmp." + UserIds.KEY_ID + " = " + Keys.TABLE_NAME
"tmp." + UserIds.KEY_ID + " = " + + "." + Keys._ID);
Keys.TABLE_NAME + "." + Keys._ID);
for (int i = 0; i < chunks.length; ++i) { for (int i = 0; i < chunks.length; ++i) {
qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE "); qb.appendWhere(" AND tmp." + UserIds.USER_ID + " LIKE ");
qb.appendWhereEscapeString("%" + chunks[i] + "%"); qb.appendWhereEscapeString("%" + chunks[i] + "%");
@ -539,32 +523,22 @@ public class KeyListActivity extends BaseActivity {
qb.appendWhere(")"); qb.appendWhere(")");
} }
mCursor = qb.query(mDatabase, mCursor = qb.query(mDatabase, new String[] { KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0
new String[] { KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1
KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0 UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2
KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1 }, KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", new String[] { ""
UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2 + (mKeyType == Id.type.public_key ? Id.database.type_public
}, : Id.database.type_secret) }, null, null, UserIds.TABLE_NAME + "."
KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", + UserIds.USER_ID + " ASC");
new String[] { "" + (mKeyType == Id.type.public_key ?
Id.database.type_public : Id.database.type_secret) },
null, null, UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC");
// content provider way for reference, might have to go back to it sometime: // content provider way for reference, might have to go back to it sometime:
/*Uri contentUri = null; /*
if (mKeyType == Id.type.secret_key) { * Uri contentUri = null; if (mKeyType == Id.type.secret_key) { contentUri =
contentUri = Apg.CONTENT_URI_SECRET_KEY_RINGS; * Apg.CONTENT_URI_SECRET_KEY_RINGS; } else { contentUri =
} else { * Apg.CONTENT_URI_PUBLIC_KEY_RINGS; } mCursor = getContentResolver().query( contentUri,
contentUri = Apg.CONTENT_URI_PUBLIC_KEY_RINGS; * new String[] { DataProvider._ID, // 0 DataProvider.MASTER_KEY_ID, // 1
} * DataProvider.USER_ID, // 2 }, null, null, null);
mCursor = getContentResolver().query( */
contentUri,
new String[] {
DataProvider._ID, // 0
DataProvider.MASTER_KEY_ID, // 1
DataProvider.USER_ID, // 2
},
null, null, null);*/
startManagingCursor(mCursor); startManagingCursor(mCursor);
rebuild(false); rebuild(false);
@ -595,26 +569,22 @@ public class KeyListActivity extends BaseActivity {
mCursor.moveToPosition(groupPosition); mCursor.moveToPosition(groupPosition);
children = new Vector<KeyChild>(); children = new Vector<KeyChild>();
Cursor c = mDatabase.query(Keys.TABLE_NAME, Cursor c = mDatabase.query(Keys.TABLE_NAME, new String[] { Keys._ID, // 0
new String[] { Keys.KEY_ID, // 1
Keys._ID, // 0 Keys.IS_MASTER_KEY, // 2
Keys.KEY_ID, // 1 Keys.ALGORITHM, // 3
Keys.IS_MASTER_KEY, // 2 Keys.KEY_SIZE, // 4
Keys.ALGORITHM, // 3 Keys.CAN_SIGN, // 5
Keys.KEY_SIZE, // 4 Keys.CAN_ENCRYPT, // 6
Keys.CAN_SIGN, // 5 }, Keys.KEY_RING_ID + " = ?", new String[] { mCursor.getString(0) }, null, null,
Keys.CAN_ENCRYPT, // 6 Keys.RANK + " ASC");
},
Keys.KEY_RING_ID + " = ?",
new String[] { mCursor.getString(0) },
null, null, Keys.RANK + " ASC");
int masterKeyId = -1; int masterKeyId = -1;
long fingerPrintId = -1; long fingerPrintId = -1;
for (int i = 0; i < c.getCount(); ++i) { for (int i = 0; i < c.getCount(); ++i) {
c.moveToPosition(i); c.moveToPosition(i);
children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4), children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4),
c.getInt(5) == 1, c.getInt(6) == 1)); c.getInt(5) == 1, c.getInt(6) == 1));
if (i == 0) { if (i == 0) {
masterKeyId = c.getInt(0); masterKeyId = c.getInt(0);
fingerPrintId = c.getLong(1); fingerPrintId = c.getLong(1);
@ -624,19 +594,15 @@ public class KeyListActivity extends BaseActivity {
if (masterKeyId != -1) { if (masterKeyId != -1) {
children.insertElementAt(new KeyChild(Apg.getFingerPrint(fingerPrintId), true), 0); children.insertElementAt(new KeyChild(Apg.getFingerPrint(fingerPrintId), true), 0);
c = mDatabase.query(UserIds.TABLE_NAME, c = mDatabase.query(UserIds.TABLE_NAME, new String[] { UserIds.USER_ID, // 0
new String[] { }, UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0", new String[] { ""
UserIds.USER_ID, // 0 + masterKeyId }, null, null, UserIds.RANK + " ASC");
},
UserIds.KEY_ID + " = ? AND " + UserIds.RANK + " > 0",
new String[] { "" + masterKeyId },
null, null, UserIds.RANK + " ASC");
for (int i = 0; i < c.getCount(); ++i) { for (int i = 0; i < c.getCount(); ++i) {
c.moveToPosition(i); c.moveToPosition(i);
children.add(new KeyChild(c.getString(0))); children.add(new KeyChild(c.getString(0)));
} }
c.close(); c.close();
} }
mChildren.set(groupPosition, children); mChildren.set(groupPosition, children);
@ -682,7 +648,7 @@ public class KeyListActivity extends BaseActivity {
} }
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) { ViewGroup parent) {
mCursor.moveToPosition(groupPosition); mCursor.moveToPosition(groupPosition);
View view = mInflater.inflate(R.layout.key_list_group_item, null); View view = mInflater.inflate(R.layout.key_list_group_item, null);
@ -713,9 +679,8 @@ public class KeyListActivity extends BaseActivity {
return view; return view;
} }
public View getChildView(int groupPosition, int childPosition, public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
boolean isLastChild, View convertView, View convertView, ViewGroup parent) {
ViewGroup parent) {
mCursor.moveToPosition(groupPosition); mCursor.moveToPosition(groupPosition);
Vector<KeyChild> children = getChildrenOfGroup(groupPosition); Vector<KeyChild> children = getChildrenOfGroup(groupPosition);
@ -723,46 +688,46 @@ public class KeyListActivity extends BaseActivity {
KeyChild child = children.get(childPosition); KeyChild child = children.get(childPosition);
View view = null; View view = null;
switch (child.type) { switch (child.type) {
case KeyChild.KEY: { case KeyChild.KEY: {
if (child.isMasterKey) { if (child.isMasterKey) {
view = mInflater.inflate(R.layout.key_list_child_item_master_key, null); view = mInflater.inflate(R.layout.key_list_child_item_master_key, null);
} else { } else {
view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null); view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null);
}
TextView keyId = (TextView) view.findViewById(R.id.keyId);
String keyIdStr = Apg.getSmallFingerPrint(child.keyId);
keyId.setText(keyIdStr);
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
String algorithmStr = Apg.getAlgorithmInfo(child.algorithm, child.keySize);
keyDetails.setText("(" + algorithmStr + ")");
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (!child.canEncrypt) {
encryptIcon.setVisibility(View.GONE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (!child.canSign) {
signIcon.setVisibility(View.GONE);
}
break;
} }
case KeyChild.USER_ID: { TextView keyId = (TextView) view.findViewById(R.id.keyId);
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null); String keyIdStr = Apg.getSmallFingerPrint(child.keyId);
TextView userId = (TextView) view.findViewById(R.id.userId); keyId.setText(keyIdStr);
userId.setText(child.userId); TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
break; String algorithmStr = Apg.getAlgorithmInfo(child.algorithm, child.keySize);
keyDetails.setText("(" + algorithmStr + ")");
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (!child.canEncrypt) {
encryptIcon.setVisibility(View.GONE);
} }
case KeyChild.FINGER_PRINT: { ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null); if (!child.canSign) {
TextView userId = (TextView) view.findViewById(R.id.userId); signIcon.setVisibility(View.GONE);
userId.setText(getString(R.string.fingerprint) + ":\n" +
child.fingerPrint.replace(" ", "\n"));
break;
} }
break;
}
case KeyChild.USER_ID: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(child.userId);
break;
}
case KeyChild.FINGER_PRINT: {
view = mInflater.inflate(R.layout.key_list_child_item_user_id, null);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(getString(R.string.fingerprint) + ":\n"
+ child.fingerPrint.replace(" ", "\n"));
break;
}
} }
return view; return view;
} }
@ -771,26 +736,26 @@ public class KeyListActivity extends BaseActivity {
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case Id.request.filename: { case Id.request.filename: {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
String filename = data.getDataString(); String filename = data.getDataString();
if (filename != null) { if (filename != null) {
// Get rid of URI prefix: // Get rid of URI prefix:
if (filename.startsWith("file://")) { if (filename.startsWith("file://")) {
filename = filename.substring(7); filename = filename.substring(7);
}
// replace %20 and so on
filename = Uri.decode(filename);
FileDialog.setFilename(filename);
} }
// replace %20 and so on
filename = Uri.decode(filename);
FileDialog.setFilename(filename);
} }
return;
}
default: {
break;
} }
return;
}
default: {
break;
}
} }
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }

View File

@ -18,9 +18,6 @@ package org.thialfihar.android.apg;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
@ -41,26 +38,25 @@ public class PublicKeyListActivity extends KeyListActivity {
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys) menu.add(0, Id.menu.option.import_keys, 0, R.string.menu_importKeys).setIcon(
.setIcon(android.R.drawable.ic_menu_add); android.R.drawable.ic_menu_add);
menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys) menu.add(0, Id.menu.option.export_keys, 1, R.string.menu_exportKeys).setIcon(
.setIcon(android.R.drawable.ic_menu_save); android.R.drawable.ic_menu_save);
menu.add(1, Id.menu.option.search, 2, R.string.menu_search) menu.add(1, Id.menu.option.search, 2, R.string.menu_search).setIcon(
.setIcon(android.R.drawable.ic_menu_search); android.R.drawable.ic_menu_search);
menu.add(1, Id.menu.option.preferences, 3, R.string.menu_preferences) menu.add(1, Id.menu.option.preferences, 3, R.string.menu_preferences).setIcon(
.setIcon(android.R.drawable.ic_menu_preferences); android.R.drawable.ic_menu_preferences);
menu.add(1, Id.menu.option.about, 4, R.string.menu_about) menu.add(1, Id.menu.option.about, 4, R.string.menu_about).setIcon(
.setIcon(android.R.drawable.ic_menu_info_details); android.R.drawable.ic_menu_info_details);
menu.add(1, Id.menu.option.scanQRCode, 5, R.string.menu_scanQRCode) menu.add(1, Id.menu.option.scanQRCode, 5, R.string.menu_scanQRCode).setIcon(
.setIcon(android.R.drawable.ic_menu_add); android.R.drawable.ic_menu_add);
return true; return true;
} }
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
ExpandableListView.ExpandableListContextMenuInfo info = ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
int type = ExpandableListView.getPackedPositionType(info.packedPosition); int type = ExpandableListView.getPackedPositionType(info.packedPosition);
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
@ -84,103 +80,103 @@ public class PublicKeyListActivity extends KeyListActivity {
} }
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case Id.menu.update: { case Id.menu.update: {
mSelectedItem = groupPosition; mSelectedItem = groupPosition;
final int keyRingId = mListAdapter.getKeyRingId(groupPosition); final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
long keyId = 0; long keyId = 0;
Object keyRing = Apg.getKeyRing(keyRingId); Object keyRing = Apg.getKeyRing(keyRingId);
if (keyRing != null && keyRing instanceof PGPPublicKeyRing) { if (keyRing != null && keyRing instanceof PGPPublicKeyRing) {
keyId = Apg.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID(); keyId = Apg.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
} }
if (keyId == 0) { if (keyId == 0) {
// this shouldn't happen // this shouldn't happen
return true;
}
Intent intent = new Intent(this, KeyServerQueryActivity.class);
intent.setAction(Apg.Intent.LOOK_UP_KEY_ID_AND_RETURN);
intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
startActivityForResult(intent, Id.request.look_up_key_id);
return true; return true;
} }
case Id.menu.exportToServer: { Intent intent = new Intent(this, KeyServerQueryActivity.class);
mSelectedItem = groupPosition; intent.setAction(Apg.Intent.LOOK_UP_KEY_ID_AND_RETURN);
final int keyRingId = mListAdapter.getKeyRingId(groupPosition); intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
startActivityForResult(intent, Id.request.look_up_key_id);
Intent intent = new Intent(this, SendKeyActivity.class);
intent.setAction(Apg.Intent.EXPORT_KEY_TO_SERVER); return true;
intent.putExtra(Apg.EXTRA_KEY_ID, keyRingId); }
startActivityForResult(intent, Id.request.export_to_server);
case Id.menu.exportToServer: {
mSelectedItem = groupPosition;
final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
Intent intent = new Intent(this, SendKeyActivity.class);
intent.setAction(Apg.Intent.EXPORT_KEY_TO_SERVER);
intent.putExtra(Apg.EXTRA_KEY_ID, keyRingId);
startActivityForResult(intent, Id.request.export_to_server);
return true;
}
case Id.menu.signKey: {
mSelectedItem = groupPosition;
final int keyRingId = mListAdapter.getKeyRingId(groupPosition);
long keyId = 0;
Object keyRing = Apg.getKeyRing(keyRingId);
if (keyRing != null && keyRing instanceof PGPPublicKeyRing) {
keyId = Apg.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
}
if (keyId == 0) {
// this shouldn't happen
return true; return true;
} }
case Id.menu.signKey: { Intent intent = new Intent(this, SignKeyActivity.class);
mSelectedItem = groupPosition; intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
final int keyRingId = mListAdapter.getKeyRingId(groupPosition); startActivity(intent);
long keyId = 0;
Object keyRing = Apg.getKeyRing(keyRingId); return true;
if (keyRing != null && keyRing instanceof PGPPublicKeyRing) { }
keyId = Apg.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID();
} default: {
return super.onContextItemSelected(menuItem);
if (keyId == 0) { }
// this shouldn't happen
return true;
}
Intent intent = new Intent(this, SignKeyActivity.class);
intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
startActivity(intent);
return true;
}
default: {
return super.onContextItemSelected(menuItem);
}
} }
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case Id.menu.option.scanQRCode: { case Id.menu.option.scanQRCode: {
Intent intent = new Intent(this, ImportFromQRCodeActivity.class); Intent intent = new Intent(this, ImportFromQRCodeActivity.class);
intent.setAction(Apg.Intent.IMPORT_FROM_QR_CODE); intent.setAction(Apg.Intent.IMPORT_FROM_QR_CODE);
startActivityForResult(intent, Id.request.import_from_qr_code); startActivityForResult(intent, Id.request.import_from_qr_code);
return true; return true;
} }
default: { default: {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case Id.request.look_up_key_id: { case Id.request.look_up_key_id: {
if (resultCode == RESULT_CANCELED || data == null || if (resultCode == RESULT_CANCELED || data == null
data.getStringExtra(Apg.EXTRA_TEXT) == null) { || data.getStringExtra(Apg.EXTRA_TEXT) == null) {
return; return;
} }
Intent intent = new Intent(this, PublicKeyListActivity.class); Intent intent = new Intent(this, PublicKeyListActivity.class);
intent.setAction(Apg.Intent.IMPORT); intent.setAction(Apg.Intent.IMPORT);
intent.putExtra(Apg.EXTRA_TEXT, data.getStringExtra(Apg.EXTRA_TEXT)); intent.putExtra(Apg.EXTRA_TEXT, data.getStringExtra(Apg.EXTRA_TEXT));
handleIntent(intent); handleIntent(intent);
break; break;
} }
default: { default: {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
break; break;
} }
} }
} }
} }

View File

@ -0,0 +1,79 @@
package org.thialfihar.android.apg.utils;
import java.lang.reflect.Method;
import android.content.Context;
import android.util.Log;
public class Compatibility {
private static final String clipboardLabel = "APG";
/**
* Wrapper around ClipboardManager based on Android version using Reflection API, from
* http://www.projectsexception.com/blog/?p=87
*
* @param context
* @param text
*/
public static void copyToClipboard(Context context, String text) {
Object clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE);
try {
if ("android.text.ClipboardManager".equals(clipboard.getClass().getName())) {
Method method = clipboard.getClass().getMethod("setText", CharSequence.class);
method.invoke(clipboard, text);
} else if ("android.content.ClipboardManager".equals(clipboard.getClass().getName())) {
Class<?> clazz = Class.forName("android.content.ClipData");
Method method = clazz.getMethod("newPlainText", CharSequence.class,
CharSequence.class);
Object clip = method.invoke(null, clipboardLabel, text);
method = clipboard.getClass().getMethod("setPrimaryClip", clazz);
method.invoke(clipboard, clip);
}
} catch (Exception e) {
Log.e("ProjectsException", "There was and error copying the text to the clipboard: "
+ e.getMessage());
}
}
/**
* Wrapper around ClipboardManager based on Android version using Reflection API
*
* @param context
* @param text
*/
public static CharSequence getClipboardText(Context context) {
Object clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE);
try {
if ("android.text.ClipboardManager".equals(clipboard.getClass().getName())) {
// CharSequence text = clipboard.getText();
Method method = clipboard.getClass().getMethod("getText");
Object text = method.invoke(clipboard);
return (CharSequence) text;
} else if ("android.content.ClipboardManager".equals(clipboard.getClass().getName())) {
// ClipData clipData = clipboard.getPrimaryClip();
Method methodGetPrimaryClip = clipboard.getClass().getMethod("getPrimaryClip");
Object clipData = methodGetPrimaryClip.invoke(clipboard);
// ClipData.Item clipDataItem = clipData.getItemAt(0);
Method methodGetItemAt = clipData.getClass().getMethod("getItemAt", Integer.TYPE);
Object clipDataItem = methodGetItemAt.invoke(clipData, 0);
// CharSequence text = clipDataItem.coerceToText(context);
Method methodGetString = clipDataItem.getClass().getMethod("coerceToText",
Context.class);
Object text = methodGetString.invoke(clipDataItem, context);
return (CharSequence) text;
} else {
return null;
}
} catch (Exception e) {
Log.e("ProjectsException", "There was and error getting the text from the clipboard: "
+ e.getMessage());
return null;
}
}
}