key edit: fix crash when create date was after expiry date, change from gregorian calendar to calendar with creation from instance, experimental result status for decrypt activity

This commit is contained in:
Dominik Schürmann 2014-04-14 01:11:08 +02:00
parent 55bad4cac7
commit 13ffd2038d
20 changed files with 210 additions and 171 deletions

View File

@ -600,7 +600,6 @@ public class PgpDecryptVerify {
throw new InvalidDataException(); throw new InvalidDataException();
} }
// go through all signatures // go through all signatures
// and find out for which signature we have a key in our database // and find out for which signature we have a key in our database
Long masterKeyId = null; Long masterKeyId = null;

View File

@ -65,20 +65,21 @@ import java.security.NoSuchProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.SignatureException; import java.security.SignatureException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
/** This class is the single place where ALL operations that actually modify a PGP public or secret /**
* This class is the single place where ALL operations that actually modify a PGP public or secret
* key take place. * key take place.
* * <p/>
* Note that no android specific stuff should be done here, ie no imports from com.android. * Note that no android specific stuff should be done here, ie no imports from com.android.
* * <p/>
* All operations support progress reporting to a ProgressDialogUpdater passed on initialization. * All operations support progress reporting to a ProgressDialogUpdater passed on initialization.
* This indicator may be null. * This indicator may be null.
*
*/ */
public class PgpKeyOperation { public class PgpKeyOperation {
private ProgressDialogUpdater mProgress; private ProgressDialogUpdater mProgress;
@ -129,7 +130,7 @@ public class PgpKeyOperation {
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase, public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
boolean isMasterKey) boolean isMasterKey)
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
PgpGeneralMsgIdException, InvalidAlgorithmParameterException { PgpGeneralMsgIdException, InvalidAlgorithmParameterException {
if (keySize < 512) { if (keySize < 512) {
throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit); throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit);
@ -190,13 +191,13 @@ public class PgpKeyOperation {
PGPEncryptedData.CAST5, sha1Calc) PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
sha1Calc, isMasterKey, keyEncryptor); sha1Calc, isMasterKey, keyEncryptor);
} }
public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassphrase, public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassphrase,
String newPassphrase) String newPassphrase)
throws IOException, PGPException, NoSuchProviderException { throws IOException, PGPException, NoSuchProviderException {
updateProgress(R.string.progress_building_key, 0, 100); updateProgress(R.string.progress_building_key, 0, 100);
if (oldPassphrase == null) { if (oldPassphrase == null) {
@ -261,13 +262,13 @@ public class PgpKeyOperation {
hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
if (saveParcel.keysExpiryDates.get(0) != null) { if (saveParcel.keysExpiryDates.get(0) != null) {
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Calendar creationDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
creationDate.setTime(masterPublicKey.getCreationTime()); creationDate.setTime(masterPublicKey.getCreationTime());
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(0); Calendar expiryDate = saveParcel.keysExpiryDates.get(0);
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
//here we purposefully ignore partial days in each date - long type has no fractional part! //here we purposefully ignore partial days in each date - long type has no fractional part!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000); (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) { if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation); throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
} }
@ -336,13 +337,13 @@ public class PgpKeyOperation {
hashedPacketsGen.setKeyFlags(false, usageId); hashedPacketsGen.setKeyFlags(false, usageId);
if (saveParcel.keysExpiryDates.get(i) != null) { if (saveParcel.keysExpiryDates.get(i) != null) {
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Calendar creationDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
creationDate.setTime(subPublicKey.getCreationTime()); creationDate.setTime(subPublicKey.getCreationTime());
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(i); Calendar expiryDate = saveParcel.keysExpiryDates.get(i);
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
//here we purposefully ignore partial days in each date - long type has no fractional part! //here we purposefully ignore partial days in each date - long type has no fractional part!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000); (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) { if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation); throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
} }
@ -437,13 +438,13 @@ public class PgpKeyOperation {
hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
if (saveParcel.keysExpiryDates.get(0) != null) { if (saveParcel.keysExpiryDates.get(0) != null) {
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Calendar creationDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
creationDate.setTime(masterPublicKey.getCreationTime()); creationDate.setTime(masterPublicKey.getCreationTime());
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(0); Calendar expiryDate = saveParcel.keysExpiryDates.get(0);
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
//here we purposefully ignore partial days in each date - long type has no fractional part! //here we purposefully ignore partial days in each date - long type has no fractional part!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000); (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) { if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation); throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
} }
@ -455,13 +456,13 @@ public class PgpKeyOperation {
} }
if (saveParcel.primaryIDChanged || if (saveParcel.primaryIDChanged ||
!saveParcel.originalIDs.get(0).equals(saveParcel.userIds.get(0))) { !saveParcel.originalIDs.get(0).equals(saveParcel.userIds.get(0))) {
anyIDChanged = true; anyIDChanged = true;
ArrayList<Pair<String, PGPSignature>> sigList = new ArrayList<Pair<String, PGPSignature>>(); ArrayList<Pair<String, PGPSignature>> sigList = new ArrayList<Pair<String, PGPSignature>>();
for (String userId : saveParcel.userIds) { for (String userId : saveParcel.userIds) {
String origID = saveParcel.originalIDs.get(userIDIndex); String origID = saveParcel.originalIDs.get(userIDIndex);
if (origID.equals(userId) && !saveParcel.newIDs[userIDIndex] && if (origID.equals(userId) && !saveParcel.newIDs[userIDIndex] &&
!userId.equals(saveParcel.originalPrimaryID) && userIDIndex != 0) { !userId.equals(saveParcel.originalPrimaryID) && userIDIndex != 0) {
Iterator<PGPSignature> origSigs = masterPublicKey.getSignaturesForID(origID); Iterator<PGPSignature> origSigs = masterPublicKey.getSignaturesForID(origID);
// TODO: make sure this iterator only has signatures we are interested in // TODO: make sure this iterator only has signatures we are interested in
while (origSigs.hasNext()) { while (origSigs.hasNext()) {
@ -489,7 +490,7 @@ public class PgpKeyOperation {
} }
for (Pair<String, PGPSignature> toAdd : sigList) { for (Pair<String, PGPSignature> toAdd : sigList) {
masterPublicKey = masterPublicKey =
PGPPublicKey.addCertification(masterPublicKey, toAdd.first, toAdd.second); PGPPublicKey.addCertification(masterPublicKey, toAdd.first, toAdd.second);
} }
} else { } else {
for (String userId : saveParcel.userIds) { for (String userId : saveParcel.userIds) {
@ -511,7 +512,7 @@ public class PgpKeyOperation {
masterPublicKey = PGPPublicKey.removeCertification(masterPublicKey, origID); masterPublicKey = PGPPublicKey.removeCertification(masterPublicKey, origID);
} }
masterPublicKey = masterPublicKey =
PGPPublicKey.addCertification(masterPublicKey, userId, certification); PGPPublicKey.addCertification(masterPublicKey, userId, certification);
} }
userIDIndex++; userIDIndex++;
} }
@ -606,14 +607,14 @@ public class PgpKeyOperation {
hashedPacketsGen.setKeyFlags(false, usageId); hashedPacketsGen.setKeyFlags(false, usageId);
if (saveParcel.keysExpiryDates.get(i) != null) { if (saveParcel.keysExpiryDates.get(i) != null) {
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Calendar creationDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
creationDate.setTime(subPublicKey.getCreationTime()); creationDate.setTime(subPublicKey.getCreationTime());
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(i); Calendar expiryDate = saveParcel.keysExpiryDates.get(i);
// note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c // note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
// here we purposefully ignore partial days in each date - long type has // here we purposefully ignore partial days in each date - long type has
// no fractional part! // no fractional part!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000); (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) { if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation); throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
} }
@ -696,18 +697,19 @@ public class PgpKeyOperation {
* Certify the given pubkeyid with the given masterkeyid. * Certify the given pubkeyid with the given masterkeyid.
* *
* @param certificationKey Certifying key * @param certificationKey Certifying key
* @param publicKey public key to certify * @param publicKey public key to certify
* @param userIds User IDs to certify, must not be null or empty * @param userIds User IDs to certify, must not be null or empty
* @param passphrase Passphrase of the secret key * @param passphrase Passphrase of the secret key
* @return A keyring with added certifications * @return A keyring with added certifications
*/ */
public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey, public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey,
List<String> userIds, String passphrase) List<String> userIds, String passphrase)
throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException,
PGPException, SignatureException { PGPException, SignatureException {
// create a signatureGenerator from the supplied masterKeyId and passphrase // create a signatureGenerator from the supplied masterKeyId and passphrase
PGPSignatureGenerator signatureGenerator; { PGPSignatureGenerator signatureGenerator;
{
if (certificationKey == null) { if (certificationKey == null) {
throw new PgpGeneralMsgIdException(R.string.error_signature_failed); throw new PgpGeneralMsgIdException(R.string.error_signature_failed);
@ -744,14 +746,16 @@ public class PgpKeyOperation {
return publicKey; return publicKey;
} }
/** Simple static subclass that stores two values. /**
* * Simple static subclass that stores two values.
* <p/>
* This is only used to return a pair of values in one function above. We specifically don't use * This is only used to return a pair of values in one function above. We specifically don't use
* com.android.Pair to keep this class free from android dependencies. * com.android.Pair to keep this class free from android dependencies.
*/ */
public static class Pair<K, V> { public static class Pair<K, V> {
public final K first; public final K first;
public final V second; public final V second;
public Pair(K first, V second) { public Pair(K first, V second) {
this.first = first; this.first = first;
this.second = second; this.second = second;

View File

@ -24,6 +24,7 @@ import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
public class SaveKeyringParcel implements Parcelable { public class SaveKeyringParcel implements Parcelable {
@ -35,7 +36,7 @@ public class SaveKeyringParcel implements Parcelable {
public boolean primaryIDChanged; public boolean primaryIDChanged;
public boolean[] moddedKeys; public boolean[] moddedKeys;
public ArrayList<PGPSecretKey> deletedKeys; public ArrayList<PGPSecretKey> deletedKeys;
public ArrayList<GregorianCalendar> keysExpiryDates; public ArrayList<Calendar> keysExpiryDates;
public ArrayList<Integer> keysUsages; public ArrayList<Integer> keysUsages;
public String newPassphrase; public String newPassphrase;
public String oldPassphrase; public String oldPassphrase;
@ -58,7 +59,7 @@ public class SaveKeyringParcel implements Parcelable {
} else { } else {
deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp); deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp);
} }
keysExpiryDates = (ArrayList<GregorianCalendar>) source.readSerializable(); keysExpiryDates = (ArrayList<Calendar>) source.readSerializable();
keysUsages = source.readArrayList(Integer.class.getClassLoader()); keysUsages = source.readArrayList(Integer.class.getClassLoader());
newPassphrase = source.readString(); newPassphrase = source.readString();
oldPassphrase = source.readString(); oldPassphrase = source.readString();

View File

@ -204,8 +204,8 @@ public class DecryptFileFragment extends DecryptFragment {
decryptVerifyResult.getStatus()) { decryptVerifyResult.getStatus()) {
showPassphraseDialog(Id.key.symmetric); showPassphraseDialog(Id.key.symmetric);
} else { } else {
AppMsg.makeText(getActivity(), R.string.decryption_successful, // display signature result in activity
AppMsg.STYLE_INFO).show(); onResult(decryptVerifyResult);
if (mDeleteAfter.isChecked()) { if (mDeleteAfter.isChecked()) {
// Create and show dialog to delete original file // Create and show dialog to delete original file
@ -213,11 +213,6 @@ public class DecryptFileFragment extends DecryptFragment {
.newInstance(mInputFilename); .newInstance(mInputFilename);
deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
} }
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
// display signature result in activity
onSignatureResult(signatureResult);
} }
} }
} }

View File

@ -26,6 +26,7 @@ import android.support.v4.app.Fragment;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
@ -34,10 +35,8 @@ import com.devspark.appmsg.AppMsg;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
public class DecryptFragment extends Fragment { public class DecryptFragment extends Fragment {
@ -45,19 +44,24 @@ public class DecryptFragment extends Fragment {
protected long mSignatureKeyId = 0; protected long mSignatureKeyId = 0;
protected RelativeLayout mSignatureLayout = null; protected LinearLayout mResultLayout;
protected ImageView mSignatureStatusImage = null; protected RelativeLayout mSignatureLayout;
protected TextView mUserId = null; protected TextView mResultText;
protected TextView mUserIdRest = null;
protected BootstrapButton mLookupKey = null; protected ImageView mSignatureStatusImage;
protected TextView mUserId;
protected TextView mUserIdRest;
protected BootstrapButton mLookupKey;
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
mSignatureLayout = (RelativeLayout) getView().findViewById(R.id.signature); mResultLayout = (LinearLayout) getView().findViewById(R.id.result);
mResultText = (TextView) getView().findViewById(R.id.result_text);
mSignatureLayout = (RelativeLayout) getView().findViewById(R.id.result_signature);
mSignatureStatusImage = (ImageView) getView().findViewById(R.id.ic_signature_status); mSignatureStatusImage = (ImageView) getView().findViewById(R.id.ic_signature_status);
mUserId = (TextView) getView().findViewById(R.id.mainUserId); mUserId = (TextView) getView().findViewById(R.id.mainUserId);
mUserIdRest = (TextView) getView().findViewById(R.id.mainUserIdRest); mUserIdRest = (TextView) getView().findViewById(R.id.mainUserIdRest);
@ -68,8 +72,8 @@ public class DecryptFragment extends Fragment {
lookupUnknownKey(mSignatureKeyId); lookupUnknownKey(mSignatureKeyId);
} }
}); });
mSignatureLayout.setVisibility(View.GONE); mResultLayout.setVisibility(View.GONE);
mSignatureLayout.setOnClickListener(new OnClickListener() { mResultLayout.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
lookupUnknownKey(mSignatureKeyId); lookupUnknownKey(mSignatureKeyId);
} }
@ -102,10 +106,13 @@ public class DecryptFragment extends Fragment {
} }
} }
protected void onSignatureResult(OpenPgpSignatureResult signatureResult) { protected void onResult(PgpDecryptVerifyResult decryptVerifyResult) {
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
mSignatureKeyId = 0; mSignatureKeyId = 0;
mSignatureLayout.setVisibility(View.GONE); mResultLayout.setVisibility(View.VISIBLE);
if (signatureResult != null) { if (signatureResult != null) {
mSignatureStatusImage.setVisibility(View.VISIBLE);
mSignatureKeyId = signatureResult.getKeyId(); mSignatureKeyId = signatureResult.getKeyId();
@ -124,48 +131,63 @@ public class DecryptFragment extends Fragment {
} }
switch (signatureResult.getStatus()) { switch (signatureResult.getStatus()) {
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
mResultText.setText(R.string.decrypt_verified_successful);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_green));
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mLookupKey.setVisibility(View.GONE); mLookupKey.setVisibility(View.GONE);
break; break;
} }
// TODO! case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
// case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { mResultText.setText(R.string.decrypt_verified_successful);
// break;
// } mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_orange));
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mLookupKey.setVisibility(View.GONE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: { case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: {
mResultText.setText(R.string.unknown_signature);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_orange));
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.VISIBLE); mLookupKey.setVisibility(View.VISIBLE);
AppMsg.makeText(getActivity(),
R.string.unknown_signature,
AppMsg.STYLE_ALERT).show();
break; break;
} }
default: { default: {
mResultText.setText(R.string.error);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_red));
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.GONE); mLookupKey.setVisibility(View.GONE);
break; break;
} }
} }
mSignatureLayout.setVisibility(View.VISIBLE); } else {
mSignatureLayout.setVisibility(View.GONE);
// only successful decryption
mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_blue));
mResultText.setText(R.string.decrypt_successful);
} }
} }
protected void showPassphraseDialog(long keyId) { protected void showPassphraseDialog(long keyId) {
PassphraseDialogFragment.show(getActivity(), keyId, PassphraseDialogFragment.show(getActivity(), keyId,
new Handler() { new Handler() {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
String passphrase = String passphrase =
message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE);
decryptStart(passphrase); decryptStart(passphrase);
}
} }
} });
});
} }
/** /**

View File

@ -158,18 +158,13 @@ public class DecryptMessageFragment extends DecryptFragment {
decryptVerifyResult.getStatus()) { decryptVerifyResult.getStatus()) {
showPassphraseDialog(Id.key.symmetric); showPassphraseDialog(Id.key.symmetric);
} else { } else {
AppMsg.makeText(getActivity(), R.string.decryption_successful,
AppMsg.STYLE_INFO).show();
byte[] decryptedMessage = returnData byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
mMessage.setText(new String(decryptedMessage)); mMessage.setText(new String(decryptedMessage));
mMessage.setHorizontallyScrolling(false); mMessage.setHorizontallyScrolling(false);
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
// display signature result in activity // display signature result in activity
onSignatureResult(signatureResult); onResult(decryptVerifyResult);
} }
} }
} }

View File

@ -72,6 +72,7 @@ import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
@ -731,8 +732,8 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
return keysUsages; return keysUsages;
} }
private ArrayList<GregorianCalendar> getKeysExpiryDates(SectionView keysView) throws PgpGeneralException { private ArrayList<Calendar> getKeysExpiryDates(SectionView keysView) throws PgpGeneralException {
ArrayList<GregorianCalendar> keysExpiryDates = new ArrayList<GregorianCalendar>(); ArrayList<Calendar> keysExpiryDates = new ArrayList<Calendar>();
ViewGroup keyEditors = keysView.getEditors(); ViewGroup keyEditors = keysView.getEditors();

View File

@ -320,7 +320,7 @@ public class EncryptFileFragment extends Fragment {
super.handleMessage(message); super.handleMessage(message);
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
AppMsg.makeText(getActivity(), R.string.encryption_successful, AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful,
AppMsg.STYLE_INFO).show(); AppMsg.STYLE_INFO).show();
if (mDeleteAfter.isChecked()) { if (mDeleteAfter.isChecked()) {

View File

@ -229,7 +229,7 @@ public class EncryptMessageFragment extends Fragment {
if (toClipboard) { if (toClipboard) {
ClipboardReflection.copyToClipboard(getActivity(), output); ClipboardReflection.copyToClipboard(getActivity(), output);
AppMsg.makeText(getActivity(), AppMsg.makeText(getActivity(),
R.string.encryption_to_clipboard_successful, AppMsg.STYLE_INFO) R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO)
.show(); .show();
} else { } else {
Intent sendIntent = new Intent(Intent.ACTION_SEND); Intent sendIntent = new Intent(Intent.ACTION_SEND);

View File

@ -64,9 +64,9 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
TextView mKeyId; TextView mKeyId;
TextView mCreationDate; TextView mCreationDate;
BootstrapButton mExpiryDateButton; BootstrapButton mExpiryDateButton;
GregorianCalendar mCreatedDate; Calendar mCreatedDate;
GregorianCalendar mExpiryDate; Calendar mExpiryDate;
GregorianCalendar mOriginalExpiryDate = null; Calendar mOriginalExpiryDate = null;
CheckBox mChkCertify; CheckBox mChkCertify;
CheckBox mChkSign; CheckBox mChkSign;
CheckBox mChkEncrypt; CheckBox mChkEncrypt;
@ -145,9 +145,9 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mExpiryDateButton.setOnClickListener(new OnClickListener() { mExpiryDateButton.setOnClickListener(new OnClickListener() {
@TargetApi(11) @TargetApi(11)
public void onClick(View v) { public void onClick(View v) {
GregorianCalendar date = mExpiryDate; Calendar expiryDate = mExpiryDate;
if (date == null) { if (expiryDate == null) {
date = new GregorianCalendar(TimeZone.getTimeZone("UTC")); expiryDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
} }
/* /*
* Using custom DatePickerDialog which overrides the setTitle because * Using custom DatePickerDialog which overrides the setTitle because
@ -155,8 +155,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
* See: https://code.google.com/p/android/issues/detail?id=49066 * See: https://code.google.com/p/android/issues/detail?id=49066
*/ */
DatePickerDialog dialog = new ExpiryDatePickerDialog(getContext(), DatePickerDialog dialog = new ExpiryDatePickerDialog(getContext(),
mExpiryDateSetListener, date.get(Calendar.YEAR), date.get(Calendar.MONTH), mExpiryDateSetListener, expiryDate.get(Calendar.YEAR), expiryDate.get(Calendar.MONTH),
date.get(Calendar.DAY_OF_MONTH)); expiryDate.get(Calendar.DAY_OF_MONTH));
mDatePickerResultCount = 0; mDatePickerResultCount = 0;
dialog.setCancelable(true); dialog.setCancelable(true);
dialog.setButton(Dialog.BUTTON_NEGATIVE, dialog.setButton(Dialog.BUTTON_NEGATIVE,
@ -179,13 +179,16 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
dialog.getDatePicker().setCalendarViewShown(false); dialog.getDatePicker().setCalendarViewShown(false);
} }
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
if (dialog != null && mCreatedDate != null) {
// will crash with IllegalArgumentException if we set a min date
// that is not before expiry
if (mCreatedDate != null && mCreatedDate.before(expiryDate)) {
dialog.getDatePicker() dialog.getDatePicker()
.setMinDate( .setMinDate(
mCreatedDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS); mCreatedDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS);
} else { } else {
//When created date isn't available // When created date isn't available
dialog.getDatePicker().setMinDate(date.getTime().getTime() + DateUtils.DAY_IN_MILLIS); dialog.getDatePicker().setMinDate(expiryDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS);
} }
} }
@ -243,7 +246,6 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mLabelUsage2.setVisibility(View.INVISIBLE); mLabelUsage2.setVisibility(View.INVISIBLE);
} }
int selectId = 0;
mIsNewKey = isNewKey; mIsNewKey = isNewKey;
if (isNewKey) { if (isNewKey) {
mUsage = usage; mUsage = usage;
@ -263,10 +265,10 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mChkAuthenticate.setChecked(PgpKeyHelper.isAuthenticationKey(key)); mChkAuthenticate.setChecked(PgpKeyHelper.isAuthenticationKey(key));
} }
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(PgpKeyHelper.getCreationDate(key)); cal.setTime(PgpKeyHelper.getCreationDate(key));
setCreatedDate(cal); setCreatedDate(cal);
cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Date expiryDate = PgpKeyHelper.getExpiryDate(key); Date expiryDate = PgpKeyHelper.getExpiryDate(key);
if (expiryDate == null) { if (expiryDate == null) {
setExpiryDate(null); setExpiryDate(null);
@ -296,7 +298,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mEditorListener = listener; mEditorListener = listener;
} }
private void setCreatedDate(GregorianCalendar date) { private void setCreatedDate(Calendar date) {
mCreatedDate = date; mCreatedDate = date;
if (date == null) { if (date == null) {
mCreationDate.setText(getContext().getString(R.string.none)); mCreationDate.setText(getContext().getString(R.string.none));
@ -305,7 +307,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
} }
} }
private void setExpiryDate(GregorianCalendar date) { private void setExpiryDate(Calendar date) {
mExpiryDate = date; mExpiryDate = date;
if (date == null) { if (date == null) {
mExpiryDateButton.setText(getContext().getString(R.string.none)); mExpiryDateButton.setText(getContext().getString(R.string.none));
@ -314,7 +316,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
} }
} }
public GregorianCalendar getExpiryDate() { public Calendar getExpiryDate() {
return mExpiryDate; return mExpiryDate;
} }

View File

@ -1,62 +1,77 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:id="@+id/signature" android:id="@+id/result"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true"
android:orientation="horizontal"
android:padding="4dp" android:padding="4dp"
android:paddingLeft="10dp" android:paddingLeft="10dp"
android:paddingRight="10dp"> android:paddingRight="10dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/relativeLayout">
<ImageView
android:id="@+id/ic_signature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/signed_large" />
<ImageView
android:id="@+id/ic_signature_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/overlay_error" />
</RelativeLayout>
<TextView <TextView
android:id="@+id/mainUserId" android:id="@+id/result_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="@string/label_main_user_id"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_toRightOf="@+id/relativeLayout" /> android:text="result text" />
<TextView <RelativeLayout
android:id="@+id/mainUserIdRest" android:id="@+id/result_signature"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:clickable="true"
android:text="Main User Id Rest" android:orientation="horizontal">
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_below="@+id/mainUserId"
android:layout_toRightOf="@+id/relativeLayout" />
<com.beardedhen.androidbootstrap.BootstrapButton <RelativeLayout
android:id="@+id/lookup_key" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="50dp" android:id="@+id/relativeLayout">
android:padding="4dp"
android:text="@string/btn_lookup_key" <ImageView
bootstrapbutton:bb_icon_left="fa-download" android:id="@+id/ic_signature"
bootstrapbutton:bb_type="info" android:layout_width="wrap_content"
bootstrapbutton:bb_size="small" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:src="@drawable/signed_large" />
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" /> <ImageView
</RelativeLayout> android:id="@+id/ic_signature_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/overlay_error" />
</RelativeLayout>
<TextView
android:id="@+id/mainUserId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="@string/label_main_user_id"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_toRightOf="@+id/relativeLayout" />
<TextView
android:id="@+id/mainUserIdRest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Main User Id Rest"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_below="@+id/mainUserId"
android:layout_toRightOf="@+id/relativeLayout" />
<com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/lookup_key"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:padding="4dp"
android:text="@string/btn_lookup_key"
bootstrapbutton:bb_icon_left="fa-download"
bootstrapbutton:bb_type="info"
bootstrapbutton:bb_size="small"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</LinearLayout>

View File

@ -195,9 +195,9 @@
<string name="file_delete_confirmation">¿Estás seguro de que quieres borrar\n%s?</string> <string name="file_delete_confirmation">¿Estás seguro de que quieres borrar\n%s?</string>
<string name="file_delete_successful">Borrado satisfactoriamente.</string> <string name="file_delete_successful">Borrado satisfactoriamente.</string>
<string name="no_file_selected">Selecciona un archivo antes.</string> <string name="no_file_selected">Selecciona un archivo antes.</string>
<string name="decryption_successful">Descifrado y/o verificado satisfactoriamente.</string> <string name="decrypt_successful">Descifrado y/o verificado satisfactoriamente.</string>
<string name="encryption_successful">Firmado y/o cifrado satisfactoriamente.</string> <string name="encrypt_sign_successful">Firmado y/o cifrado satisfactoriamente.</string>
<string name="encryption_to_clipboard_successful">Firmado y/o cifrado al portapapeles satisfactoriamente.</string> <string name="encrypt_sign_clipboard_successful">Firmado y/o cifrado al portapapeles satisfactoriamente.</string>
<string name="enter_passphrase_twice">Introduce la frase de contraseña dos veces.</string> <string name="enter_passphrase_twice">Introduce la frase de contraseña dos veces.</string>
<string name="select_encryption_key">Selecciona al menos una clave de cifrado.</string> <string name="select_encryption_key">Selecciona al menos una clave de cifrado.</string>
<string name="select_encryption_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string> <string name="select_encryption_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string>

View File

@ -195,9 +195,9 @@
<string name="file_delete_confirmation">Êtes-vous sûr de vouloir supprimer\n%s ?</string> <string name="file_delete_confirmation">Êtes-vous sûr de vouloir supprimer\n%s ?</string>
<string name="file_delete_successful">Supprimé avec succès.</string> <string name="file_delete_successful">Supprimé avec succès.</string>
<string name="no_file_selected">Choisir d\'abord un fichier.</string> <string name="no_file_selected">Choisir d\'abord un fichier.</string>
<string name="decryption_successful">Déchiffré et/ou vérifié avec succès</string> <string name="decrypt_successful">Déchiffré et/ou vérifié avec succès</string>
<string name="encryption_successful">Signé et/ou chiffré avec succès</string> <string name="encrypt_sign_successful">Signé et/ou chiffré avec succès</string>
<string name="encryption_to_clipboard_successful">Signé et/ou chiffré vers le presse-papiers avec succès</string> <string name="encrypt_sign_clipboard_successful">Signé et/ou chiffré vers le presse-papiers avec succès</string>
<string name="enter_passphrase_twice">Saisir la phrase de passe deux fois.</string> <string name="enter_passphrase_twice">Saisir la phrase de passe deux fois.</string>
<string name="select_encryption_key">Choisir au moins une clef de chiffrement.</string> <string name="select_encryption_key">Choisir au moins une clef de chiffrement.</string>
<string name="select_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string> <string name="select_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string>

View File

@ -195,9 +195,9 @@
<string name="file_delete_confirmation">Sei sicuro di voler cancellare\n%s?</string> <string name="file_delete_confirmation">Sei sicuro di voler cancellare\n%s?</string>
<string name="file_delete_successful">Eliminato correttamente.</string> <string name="file_delete_successful">Eliminato correttamente.</string>
<string name="no_file_selected">Seleziona un file prima.</string> <string name="no_file_selected">Seleziona un file prima.</string>
<string name="decryption_successful">Decodifica e/o verifica eseguita con successo.</string> <string name="decrypt_successful">Decodifica e/o verifica eseguita con successo.</string>
<string name="encryption_successful">Firmato e/o codificato con successo.</string> <string name="encrypt_sign_successful">Firmato e/o codificato con successo.</string>
<string name="encryption_to_clipboard_successful">Firmato e/o codificato con successo negli appunti.</string> <string name="encrypt_sign_clipboard_successful">Firmato e/o codificato con successo negli appunti.</string>
<string name="enter_passphrase_twice">Inserisci la frase di accesso due volte.</string> <string name="enter_passphrase_twice">Inserisci la frase di accesso due volte.</string>
<string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string> <string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string>
<string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string> <string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string>

View File

@ -192,9 +192,9 @@
<string name="file_delete_confirmation">%s を削除してもかまいませんか?</string> <string name="file_delete_confirmation">%s を削除してもかまいませんか?</string>
<string name="file_delete_successful">削除に成功しました。</string> <string name="file_delete_successful">削除に成功しました。</string>
<string name="no_file_selected">最初にファイルを選択してください。</string> <string name="no_file_selected">最初にファイルを選択してください。</string>
<string name="decryption_successful">復号化/検証に成功しました。</string> <string name="decrypt_successful">復号化/検証に成功しました。</string>
<string name="encryption_successful">署名/暗号化に成功しました。</string> <string name="encrypt_sign_successful">署名/暗号化に成功しました。</string>
<string name="encryption_to_clipboard_successful">クリップボードの中身の署名/暗号化に成功しました。</string> <string name="encrypt_sign_clipboard_successful">クリップボードの中身の署名/暗号化に成功しました。</string>
<string name="enter_passphrase_twice">もう一度パスフレーズを入れてください。</string> <string name="enter_passphrase_twice">もう一度パスフレーズを入れてください。</string>
<string name="select_encryption_key">少なくとも1つの暗号化鍵を選択して下さい。</string> <string name="select_encryption_key">少なくとも1つの暗号化鍵を選択して下さい。</string>
<string name="select_encryption_or_signature_key">少なくとも1つの暗号化鍵か署名鍵を選択して下さい。</string> <string name="select_encryption_or_signature_key">少なくとも1つの暗号化鍵か署名鍵を選択して下さい。</string>

View File

@ -198,9 +198,9 @@
<string name="file_delete_confirmation">Czy jesteś pewien że chcesz usunąć\n%s?</string> <string name="file_delete_confirmation">Czy jesteś pewien że chcesz usunąć\n%s?</string>
<string name="file_delete_successful">Usunięto pomyślnie.</string> <string name="file_delete_successful">Usunięto pomyślnie.</string>
<string name="no_file_selected">Najpierw wskaż plik.</string> <string name="no_file_selected">Najpierw wskaż plik.</string>
<string name="decryption_successful">Pomyślnie deszyfrowano i/lub zweryfikowano.</string> <string name="decrypt_successful">Pomyślnie deszyfrowano i/lub zweryfikowano.</string>
<string name="encryption_successful">Pomyślnie podpisano i/lub zaszyfrowano.</string> <string name="encrypt_sign_successful">Pomyślnie podpisano i/lub zaszyfrowano.</string>
<string name="encryption_to_clipboard_successful">Pomyslnie podpisano i/lub zaszyfrowano do schowka.</string> <string name="encrypt_sign_clipboard_successful">Pomyslnie podpisano i/lub zaszyfrowano do schowka.</string>
<string name="enter_passphrase_twice">Podaj hasło dwukrotnie.</string> <string name="enter_passphrase_twice">Podaj hasło dwukrotnie.</string>
<string name="select_encryption_key">Wybierz co najmniej jeden klucz szyfrujący.</string> <string name="select_encryption_key">Wybierz co najmniej jeden klucz szyfrujący.</string>
<string name="select_encryption_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string> <string name="select_encryption_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string>

View File

@ -195,9 +195,9 @@
<string name="file_delete_confirmation">Вы уверены, что хотите удалить\n%s ?</string> <string name="file_delete_confirmation">Вы уверены, что хотите удалить\n%s ?</string>
<string name="file_delete_successful">Удалено.</string> <string name="file_delete_successful">Удалено.</string>
<string name="no_file_selected">Сначала выберите файл.</string> <string name="no_file_selected">Сначала выберите файл.</string>
<string name="decryption_successful">Расшифровано и/или проверено.</string> <string name="decrypt_successful">Расшифровано и/или проверено.</string>
<string name="encryption_successful">Подписано и/или зашифровано.</string> <string name="encrypt_sign_successful">Подписано и/или зашифровано.</string>
<string name="encryption_to_clipboard_successful">Подписано и/или зашифровано в буфер обмена.</string> <string name="encrypt_sign_clipboard_successful">Подписано и/или зашифровано в буфер обмена.</string>
<string name="enter_passphrase_twice">Дважды введите пароль.</string> <string name="enter_passphrase_twice">Дважды введите пароль.</string>
<string name="select_encryption_key">Укажите хотя бы один ключ.</string> <string name="select_encryption_key">Укажите хотя бы один ключ.</string>
<string name="select_encryption_or_signature_key">Выберите хотя бы один ключ для шифрования или подписи.</string> <string name="select_encryption_or_signature_key">Выберите хотя бы один ключ для шифрования или подписи.</string>

View File

@ -199,9 +199,9 @@
<string name="file_delete_confirmation">Ви справді хочете вилучити\n%s?</string> <string name="file_delete_confirmation">Ви справді хочете вилучити\n%s?</string>
<string name="file_delete_successful">Успішно вилучено.</string> <string name="file_delete_successful">Успішно вилучено.</string>
<string name="no_file_selected">Виберіть спершу файл.</string> <string name="no_file_selected">Виберіть спершу файл.</string>
<string name="decryption_successful">Успішно розшифровано та/або перевірено.</string> <string name="decrypt_successful">Успішно розшифровано та/або перевірено.</string>
<string name="encryption_successful">Успішно підписано та/або перевірено.</string> <string name="encrypt_sign_successful">Успішно підписано та/або перевірено.</string>
<string name="encryption_to_clipboard_successful">Успішно підписано та/або зашифровано до буфера обміну.</string> <string name="encrypt_sign_clipboard_successful">Успішно підписано та/або зашифровано до буфера обміну.</string>
<string name="enter_passphrase_twice">Введіть двічі парольну фразу.</string> <string name="enter_passphrase_twice">Введіть двічі парольну фразу.</string>
<string name="select_encryption_key">Виберіть принаймні один ключ шифрування.</string> <string name="select_encryption_key">Виберіть принаймні один ключ шифрування.</string>
<string name="select_encryption_or_signature_key">Виберіть принаймні один ключ шифрування або ключ підпису.</string> <string name="select_encryption_or_signature_key">Виберіть принаймні один ключ шифрування або ключ підпису.</string>

View File

@ -4,4 +4,8 @@
<color name="emphasis">#31b6e7</color> <color name="emphasis">#31b6e7</color>
<color name="bg_gray">#cecbce</color> <color name="bg_gray">#cecbce</color>
<color name="result_red">#CC0000</color>
<color name="result_orange">#FF8800</color>
<color name="result_green">#669900</color>
<color name="result_blue">#336699</color>
</resources> </resources>

View File

@ -209,9 +209,10 @@
<string name="file_delete_confirmation">Are you sure you want to delete\n%s?</string> <string name="file_delete_confirmation">Are you sure you want to delete\n%s?</string>
<string name="file_delete_successful">Successfully deleted.</string> <string name="file_delete_successful">Successfully deleted.</string>
<string name="no_file_selected">Select a file first.</string> <string name="no_file_selected">Select a file first.</string>
<string name="decryption_successful">Successfully decrypted and/or verified.</string> <string name="decrypt_successful">Successfully decrypted.</string>
<string name="encryption_successful">Successfully signed and/or encrypted.</string> <string name="decrypt_verified_successful">Successfully decrypted and/or verified.</string>
<string name="encryption_to_clipboard_successful">Successfully signed and/or encrypted to clipboard.</string> <string name="encrypt_sign_successful">Successfully signed and/or encrypted.</string>
<string name="encrypt_sign_clipboard_successful">Successfully signed and/or encrypted to clipboard.</string>
<string name="enter_passphrase_twice">Enter the passphrase twice.</string> <string name="enter_passphrase_twice">Enter the passphrase twice.</string>
<string name="select_encryption_key">Select at least one encryption key.</string> <string name="select_encryption_key">Select at least one encryption key.</string>
<string name="select_encryption_or_signature_key">Select at least one encryption key or a signature key.</string> <string name="select_encryption_or_signature_key">Select at least one encryption key or a signature key.</string>