Merge remote-tracking branch 'origin/master'

Conflicts:
	OpenPGP-Keychain/src/main/res/menu/key_list_secret.xml
This commit is contained in:
Vincent Breitmoser
2014-03-13 13:40:47 +01:00
18 changed files with 149 additions and 49 deletions

View File

@@ -16,6 +16,17 @@
package org.sufficientlysecure.keychain.helper;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@@ -26,16 +37,6 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
public class ExportHelper {
protected FileDialogFragment mFileDialog;
protected String mExportFilename;
@@ -115,7 +116,7 @@ public class ExportHelper {
Log.d(Constants.TAG, "exportKeys started");
// Send all information needed to service to export key in other thread
Intent intent = new Intent(activity, KeychainIntentService.class);
final Intent intent = new Intent(activity, KeychainIntentService.class);
intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING);
@@ -135,7 +136,12 @@ public class ExportHelper {
// Message is received after exporting is done in ApgService
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(activity,
activity.getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) {
activity.getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
activity.stopService(intent);
}
}) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);

View File

@@ -17,6 +17,9 @@
package org.sufficientlysecure.keychain.helper;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Set;
@@ -58,4 +61,23 @@ public class OtherHelper {
}
}
/**
* Converts the given bytes to a unique RGB color using SHA1 algorithm
* @param bytes
* @return an integer array containing 3 numeric color representations (Red, Green, Black)
* @throws NoSuchAlgorithmException
* @throws DigestException
*/
public static int[] getRgbForData(byte[] bytes) throws NoSuchAlgorithmException, DigestException {
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(bytes);
byte[] digest = md.digest();
int[] result = {((int) digest[0] + 256) % 256,
((int) digest[1] + 256) % 256,
((int) digest[2] + 256) % 256};
return result;
}
}

View File

@@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
import org.sufficientlysecure.keychain.util.KeychainServiceListener;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
@@ -50,15 +51,25 @@ import android.os.Bundle;
import android.os.Environment;
public class PgpImportExport {
private Context mContext;
private ProgressDialogUpdater mProgress;
private KeychainServiceListener mKeychainServiceListener;
public PgpImportExport(Context context, ProgressDialogUpdater progress) {
super();
this.mContext = context;
this.mProgress = progress;
}
public PgpImportExport(Context context, ProgressDialogUpdater progress, KeychainServiceListener keychainListener){
super();
this.mContext = context;
this.mProgress = progress;
this.mKeychainServiceListener = keychainListener;
}
public void updateProgress(int message, int current, int total) {
if (mProgress != null) {
mProgress.setProgress(message, current, total);
@@ -188,8 +199,10 @@ public class PgpImportExport {
if (secretKeyRing != null) {
secretKeyRing.encode(arOutStream);
}
// Else if it's a public key get the PGPPublicKeyRing
// and encode that to the output
if(mKeychainServiceListener.hasServiceStopped()){
arOutStream.close();
return null;
}
} else {
updateProgress(i * 100 / rowIdsSize, 100);
PGPPublicKeyRing publicKeyRing =
@@ -198,6 +211,11 @@ public class PgpImportExport {
if (publicKeyRing != null) {
publicKeyRing.encode(arOutStream);
}
if(mKeychainServiceListener.hasServiceStopped()){
arOutStream.close();
return null;
}
}
arOutStream.close();

View File

@@ -56,6 +56,7 @@ 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.KeychainServiceListener;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
@@ -73,7 +74,7 @@ import android.os.RemoteException;
* data from the activities or other apps, queues these intents, executes them, and stops itself
* after doing them.
*/
public class KeychainIntentService extends IntentService implements ProgressDialogUpdater {
public class KeychainIntentService extends IntentService implements ProgressDialogUpdater, KeychainServiceListener {
/* extras that can be given by intent */
public static final String EXTRA_MESSENGER = "messenger";
@@ -712,10 +713,15 @@ public class KeychainIntentService extends IntentService implements ProgressDial
Bundle resultData;
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
PgpImportExport pgpImportExport = new PgpImportExport(this, this, this);
resultData = pgpImportExport
.exportKeyRings(keyRingRowIds, keyType, outStream);
if(mIsCanceled){
boolean isDeleted = new File(outputFile).delete();
}
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {
sendErrorToHandler(e);
@@ -903,4 +909,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public void setProgress(int progress, int max) {
setProgress(null, progress, max);
}
@Override
public boolean hasServiceStopped() {
return mIsCanceled;
}
}

View File

@@ -29,6 +29,7 @@ import android.support.v4.content.Loader;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
@@ -40,6 +41,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
@@ -47,6 +49,8 @@ import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter;
import org.sufficientlysecure.keychain.util.Log;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
@@ -305,18 +309,40 @@ public class ViewKeyMainFragment extends Fragment implements
private SpannableStringBuilder colorizeFingerprint(String fingerprint) {
SpannableStringBuilder sb = new SpannableStringBuilder(fingerprint);
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.BLACK);
try {
// for each 4 characters of the fingerprint + 1 space
for (int i = 0; i < fingerprint.length(); i += 5) {
int minFingLength = Math.min(i + 4, fingerprint.length());
String fourChars = fingerprint.substring(i, minFingLength);
// for each 4 characters of the fingerprint + 1 space
for (int i = 0; i < fingerprint.length(); i += 5) {
int minFingLength = Math.min(i + 4, fingerprint.length());
String fourChars = fingerprint.substring(i, minFingLength);
int raw = Integer.parseInt(fourChars, 16);
byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)};
int[] color = OtherHelper.getRgbForData(bytes);
// Create a foreground color by converting the 4 fingerprint chars to an int hashcode
// and then converting that int to hex to use as a color
fcs = new ForegroundColorSpan(
Color.parseColor(String.format("#%06X", (0xFFFFFF & fourChars.hashCode()))));
sb.setSpan(fcs, i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// Convert rgb to brightness
int brightness = (int) (0.2126*color[0] + 0.7152*color[1] + 0.0722*color[2]);
// Detect dark colors and invert their background to white to make them more distinguishable
if (brightness < 40) {
sb.setSpan(new BackgroundColorSpan(Color.WHITE),
i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// Detect bright colors and invert their background to black to make them more distinguishable
} else if (brightness > 210) {
sb.setSpan(new BackgroundColorSpan(Color.BLACK),
i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
// Create a foreground color with the 3 digest integers as RGB
// and then converting that int to hex to use as a color
sb.setSpan(new ForegroundColorSpan(Color.rgb(color[0], color[1], color[2])),
i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
} catch (Exception e) {
Log.e(Constants.TAG, "Colorization failed", e);
// if anything goes wrong, then just display the fingerprint without colour,
// instead of partially correct colour or wrong colours
return new SpannableStringBuilder(fingerprint);
}
return sb;

View File

@@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.Choice;
import android.annotation.TargetApi;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
@@ -110,6 +111,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
setExpiryDate(null);
mExpiryDateButton.setOnClickListener(new OnClickListener() {
@TargetApi(11)
public void onClick(View v) {
GregorianCalendar date = mExpiryDate;
if (date == null) {

View File

@@ -0,0 +1,5 @@
package org.sufficientlysecure.keychain.util;
public interface KeychainServiceListener {
boolean hasServiceStopped();
}