Merge remote-tracking branch 'origin/master' into db-overhaul

Conflicts:
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java
	OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
This commit is contained in:
Vincent Breitmoser 2014-04-03 13:43:28 +02:00
commit 34fca975d7
113 changed files with 1320 additions and 1009 deletions

View File

@ -58,8 +58,8 @@ public class OpenPgpProviderActivity extends Activity {
public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.openpgp_provider);
mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message);
@ -171,7 +171,7 @@ public class OpenPgpProviderActivity extends Activity {
@Override
public void onReturn(Intent result) {
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS: {
try {
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length
@ -218,7 +218,7 @@ public class OpenPgpProviderActivity extends Activity {
data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN));
@ -231,7 +231,7 @@ public class OpenPgpProviderActivity extends Activity {
data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT));
@ -244,7 +244,7 @@ public class OpenPgpProviderActivity extends Activity {
data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT));
@ -256,7 +256,7 @@ public class OpenPgpProviderActivity extends Activity {
data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(true);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY));

View File

@ -47,7 +47,7 @@ public final class Constants {
public static final class Path {
public static final String APP_DIR = Environment.getExternalStorageDirectory()
+ "/OpenPGP-Keychain";
+ "/OpenKeychain";
public static final String APP_DIR_FILE_SEC = APP_DIR + "/secexport.asc";
public static final String APP_DIR_FILE_PUB = APP_DIR + "/pubexport.asc";
}
@ -55,10 +55,10 @@ public final class Constants {
public static final class Pref {
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm";
public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm";
public static final String DEFAULT_ASCII_ARMOUR = "defaultAsciiArmour";
public static final String DEFAULT_ASCII_ARMOR = "defaultAsciiArmor";
public static final String DEFAULT_MESSAGE_COMPRESSION = "defaultMessageCompression";
public static final String DEFAULT_FILE_COMPRESSION = "defaultFileCompression";
public static final String PASS_PHRASE_CACHE_TTL = "passphraseCacheTtl";
public static final String PASSPHRASE_CACHE_TTL = "passphraseCacheTtl";
public static final String LANGUAGE = "language";
public static final String FORCE_V3_SIGNATURES = "forceV3Signatures";
public static final String KEY_SERVERS = "keyServers";
@ -74,7 +74,12 @@ public final class Constants {
public static final Class DECRYPT = DecryptActivity.class;
public static final Class IMPORT_KEYS = ImportKeysActivity.class;
public static final Class REGISTERED_APPS_LIST = AppsListActivity.class;
public static final Class[] ARRAY = new Class[]{KEY_LIST, ENCRYPT, DECRYPT,
IMPORT_KEYS, REGISTERED_APPS_LIST};
public static final Class[] ARRAY = new Class[]{
KEY_LIST,
ENCRYPT,
DECRYPT,
IMPORT_KEYS,
REGISTERED_APPS_LIST
};
}
}

View File

@ -17,16 +17,17 @@
package org.sufficientlysecure.keychain;
import java.io.File;
import java.security.Provider;
import java.security.Security;
import android.app.Application;
import android.os.Environment;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.PRNGFixes;
import android.app.Application;
import android.os.Environment;
import java.io.File;
import java.security.Provider;
import java.security.Security;
public class KeychainApplication extends Application {

View File

@ -17,13 +17,13 @@
package org.sufficientlysecure.keychain.compatibility;
import java.lang.reflect.Method;
import android.content.Context;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log;
import java.lang.reflect.Method;
public class ClipboardReflection {
private static final String clipboardLabel = "Keychain";

View File

@ -30,18 +30,12 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import java.lang.reflect.Array;
import java.security.Provider;
import java.util.ArrayList;
public class ExportHelper {
protected FileDialogFragment mFileDialog;
protected String mExportFilename;
@ -81,7 +75,7 @@ public class ExportHelper {
int type = keyType;
mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
if( data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED) ) {
if (data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED)) {
type = Id.type.public_secret_key;
}

View File

@ -30,7 +30,7 @@ import java.util.Vector;
* Singleton Implementation of a Preference Helper
*/
public class Preferences {
private static Preferences mPreferences;
private static Preferences sPreferences;
private SharedPreferences mSharedPreferences;
public static synchronized Preferences getPreferences(Context context) {
@ -38,10 +38,10 @@ public class Preferences {
}
public static synchronized Preferences getPreferences(Context context, boolean forceNew) {
if (mPreferences == null || forceNew) {
mPreferences = new Preferences(context);
if (sPreferences == null || forceNew) {
sPreferences = new Preferences(context);
}
return mPreferences;
return sPreferences;
}
private Preferences(Context context) {
@ -58,8 +58,8 @@ public class Preferences {
editor.commit();
}
public long getPassPhraseCacheTtl() {
int ttl = mSharedPreferences.getInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, 180);
public long getPassphraseCacheTtl() {
int ttl = mSharedPreferences.getInt(Constants.Pref.PASSPHRASE_CACHE_TTL, 180);
// fix the value if it was set to "never" in previous versions, which currently is not
// supported
if (ttl == 0) {
@ -68,9 +68,9 @@ public class Preferences {
return (long) ttl;
}
public void setPassPhraseCacheTtl(int value) {
public void setPassphraseCacheTtl(int value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, value);
editor.putInt(Constants.Pref.PASSPHRASE_CACHE_TTL, value);
editor.commit();
}
@ -118,13 +118,13 @@ public class Preferences {
editor.commit();
}
public boolean getDefaultAsciiArmour() {
return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, false);
public boolean getDefaultAsciiArmor() {
return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, false);
}
public void setDefaultAsciiArmour(boolean value) {
public void setDefaultAsciiArmor(boolean value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, value);
editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, value);
editor.commit();
}

View File

@ -65,14 +65,16 @@ public class PgpConversionHelper {
try {
while ((obj = factory.nextObject()) != null) {
PGPSecretKey secKey = null;
if(obj instanceof PGPSecretKey) {
if ((secKey = (PGPSecretKey)obj ) == null) {
if (obj instanceof PGPSecretKey) {
secKey = (PGPSecretKey) obj;
if (secKey == null) {
Log.e(Constants.TAG, "No keys given!");
}
keys.add(secKey);
} else if(obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings
} else if (obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings
PGPSecretKeyRing keyRing = null;
if ((keyRing = (PGPSecretKeyRing)obj) == null) {
keyRing = (PGPSecretKeyRing) obj;
if (keyRing == null) {
Log.e(Constants.TAG, "No keys given!");
}
@SuppressWarnings("unchecked")

View File

@ -67,6 +67,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.SignatureException;
import java.util.Iterator;
import java.util.Set;
/**
* This class uses a Builder pattern!
@ -79,7 +80,7 @@ public class PgpDecryptVerify {
private ProgressDialogUpdater mProgressDialogUpdater;
private boolean mAllowSymmetricDecryption;
private String mPassphrase;
private long mEnforcedKeyId;
private Set<Long> mAllowedKeyIds;
private PgpDecryptVerify(Builder builder) {
// private Constructor can only be called from Builder
@ -90,7 +91,7 @@ public class PgpDecryptVerify {
this.mProgressDialogUpdater = builder.mProgressDialogUpdater;
this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption;
this.mPassphrase = builder.mPassphrase;
this.mEnforcedKeyId = builder.mEnforcedKeyId;
this.mAllowedKeyIds = builder.mAllowedKeyIds;
}
public static class Builder {
@ -103,7 +104,7 @@ public class PgpDecryptVerify {
private ProgressDialogUpdater mProgressDialogUpdater = null;
private boolean mAllowSymmetricDecryption = true;
private String mPassphrase = null;
private long mEnforcedKeyId = 0;
private Set<Long> mAllowedKeyIds = null;
public Builder(Context context, InputData data, OutputStream outStream) {
this.mContext = context;
@ -127,14 +128,14 @@ public class PgpDecryptVerify {
}
/**
* Allow this key id alone for decryption.
* This means only ciphertexts encrypted for this private key can be decrypted.
* Allow these key ids alone for decryption.
* This means only ciphertexts encrypted for one of these private key can be decrypted.
*
* @param enforcedKeyId
* @param allowedKeyIds
* @return
*/
public Builder enforcedKeyId(long enforcedKeyId) {
this.mEnforcedKeyId = enforcedKeyId;
public Builder allowedKeyIds(Set<Long> allowedKeyIds) {
this.mAllowedKeyIds = allowedKeyIds;
return this;
}
@ -236,16 +237,16 @@ public class PgpDecryptVerify {
// secret key exists in database
// allow only a specific key for decryption?
if (mEnforcedKeyId != 0) {
if (mAllowedKeyIds != null) {
// TODO: improve this code! get master key directly!
PGPSecretKeyRing secretKeyRing =
ProviderHelper.getPGPSecretKeyRingWithKeyId(mContext, encData.getKeyID());
long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID();
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
Log.d(Constants.TAG, "enforcedKeyId: " + mEnforcedKeyId);
Log.d(Constants.TAG, "allowedKeyIds: " + mAllowedKeyIds);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
if (mEnforcedKeyId != masterKeyId) {
if (!mAllowedKeyIds.contains(masterKeyId)) {
throw new PgpGeneralException(
mContext.getString(R.string.error_no_secret_key_found));
}
@ -683,7 +684,8 @@ public class PgpDecryptVerify {
}
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
PGPPublicKey masterPublicKey,
PGPPublicKey signingPublicKey) {
boolean validPrimaryKeyBinding = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()

View File

@ -21,7 +21,13 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPEncryptedDataList;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -45,8 +51,8 @@ public class PgpHelper {
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
public static final Pattern PGP_CLEARTEXT_SIGNATURE = Pattern
.compile(
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----" +
"BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
Pattern.DOTALL);
public static final Pattern PGP_PUBLIC_KEY = Pattern.compile(

View File

@ -20,8 +20,14 @@ package org.sufficientlysecure.keychain.pgp;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@ -30,13 +36,16 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.*;
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;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.Provider;
import java.util.ArrayList;
import java.util.List;
@ -159,7 +168,8 @@ public class PgpImportExport {
return returnData;
}
public Bundle exportKeyRings(ArrayList<Long> publicKeyRingMasterIds, ArrayList<Long> secretKeyRingMasterIds,
public Bundle exportKeyRings(ArrayList<Long> publicKeyRingMasterIds,
ArrayList<Long> secretKeyRingMasterIds,
OutputStream outStream) throws PgpGeneralException,
PGPException, IOException {
Bundle returnData = new Bundle();

View File

@ -24,7 +24,12 @@ import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@ -35,7 +40,11 @@ import org.sufficientlysecure.keychain.util.Log;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -288,8 +297,7 @@ public class PgpKeyHelper {
return userId;
}
public static int getKeyUsage(PGPSecretKey key)
{
public static int getKeyUsage(PGPSecretKey key) {
return getKeyUsage(key.getPublicKey());
}
@ -298,13 +306,19 @@ public class PgpKeyHelper {
int usage = 0;
if (key.getVersion() >= 4) {
for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) continue;
if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
continue;
}
PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
if (hashed != null) usage |= hashed.getKeyFlags();
if (hashed != null) {
usage |= hashed.getKeyFlags();
}
PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
if (unhashed != null) usage |= unhashed.getKeyFlags();
if (unhashed != null) {
usage |= unhashed.getKeyFlags();
}
}
}
return usage;

View File

@ -17,30 +17,54 @@
package org.sufficientlysecure.keychain.pgp;
import android.util.Pair;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.jce.spec.ElGamalParameterSpec;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyPair;
import org.spongycastle.openpgp.PGPKeyRingGenerator;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
import org.spongycastle.openpgp.operator.jcajce.*;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Primes;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
import org.sufficientlysecure.keychain.util.IterableIterator;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
@ -171,35 +195,35 @@ public class PgpKeyOperation {
sha1Calc, isMasterKey, keyEncryptor);
}
public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
String newPassPhrase) throws IOException, PGPException,
NoSuchProviderException {
public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassphrase,
String newPassphrase)
throws IOException, PGPException, NoSuchProviderException {
updateProgress(R.string.progress_building_key, 0, 100);
if (oldPassPhrase == null) {
oldPassPhrase = "";
if (oldPassphrase == null) {
oldPassphrase = "";
}
if (newPassPhrase == null) {
newPassPhrase = "";
if (newPassphrase == null) {
newPassphrase = "";
}
PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
keyRing,
new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray()),
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()),
new JcePBESecretKeyEncryptorBuilder(keyRing.getSecretKey()
.getKeyEncryptionAlgorithm()).build(newPassPhrase.toCharArray()));
.getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray()));
return newKeyRing;
}
private Pair<PGPSecretKeyRing,PGPPublicKeyRing> buildNewSecretKey(
private Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildNewSecretKey(
ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
ArrayList<GregorianCalendar> keysExpiryDates,
ArrayList<Integer> keysUsages,
String newPassPhrase, String oldPassPhrase)
String newPassphrase, String oldPassphrase)
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
int usageId = keysUsages.get(0);
@ -212,7 +236,7 @@ public class PgpKeyOperation {
PGPPublicKey masterPublicKey = masterKey.getPublicKey();
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
updateProgress(R.string.progress_certifying_master_key, 20, 100);
@ -246,13 +270,16 @@ public class PgpKeyOperation {
GregorianCalendar expiryDate = keysExpiryDates.get(0);
//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!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0)
long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
}
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
} else {
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
//this happens anyway
hashedPacketsGen.setKeyExpirationTime(false, 0);
// do this explicitly, although since we're rebuilding,
// this happens anyway
}
updateProgress(R.string.progress_building_master_key, 30, 100);
@ -267,7 +294,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
newPassPhrase.toCharArray());
newPassphrase.toCharArray());
PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
@ -283,7 +310,7 @@ public class PgpKeyOperation {
PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
oldPassPhrase.toCharArray());
oldPassphrase.toCharArray());
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
// TODO: now used without algorithm and creation time?! (APG 1)
@ -318,15 +345,16 @@ public class PgpKeyOperation {
GregorianCalendar expiryDate = keysExpiryDates.get(i);
//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!
long numDays =
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
}
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
} else {
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
//this happens anyway
hashedPacketsGen.setKeyExpirationTime(false, 0);
// do this explicitly, although since we're rebuilding,
// this happens anyway
}
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
@ -335,11 +363,11 @@ public class PgpKeyOperation {
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
return new Pair<PGPSecretKeyRing,PGPPublicKeyRing>(secretKeyRing, publicKeyRing);
return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(secretKeyRing, publicKeyRing);
}
public Pair<PGPSecretKeyRing,PGPPublicKeyRing> buildSecretKey (PGPSecretKeyRing mKR,
public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildSecretKey(PGPSecretKeyRing mKR,
PGPPublicKeyRing pKR,
SaveKeyringParcel saveParcel)
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
@ -347,16 +375,16 @@ public class PgpKeyOperation {
updateProgress(R.string.progress_building_key, 0, 100);
PGPSecretKey masterKey = saveParcel.keys.get(0);
if (saveParcel.oldPassPhrase == null) {
saveParcel.oldPassPhrase = "";
if (saveParcel.oldPassphrase == null) {
saveParcel.oldPassphrase = "";
}
if (saveParcel.newPassPhrase == null) {
saveParcel.newPassPhrase = "";
if (saveParcel.newPassphrase == null) {
saveParcel.newPassphrase = "";
}
if (mKR == null) {
return buildNewSecretKey(saveParcel.userIDs, saveParcel.keys, saveParcel.keysExpiryDates,
saveParcel.keysUsages, saveParcel.newPassPhrase, saveParcel.oldPassPhrase); //new Keyring
saveParcel.keysUsages, saveParcel.newPassphrase, saveParcel.oldPassphrase); //new Keyring
}
/*
@ -395,7 +423,7 @@ public class PgpKeyOperation {
String mainUserId = saveParcel.userIDs.get(0);
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(saveParcel.oldPassPhrase.toCharArray());
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(saveParcel.oldPassphrase.toCharArray());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
updateProgress(R.string.progress_certifying_master_key, 20, 100);
@ -423,22 +451,28 @@ public class PgpKeyOperation {
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(0);
//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!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0)
long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
}
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
} else {
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
//this happens anyway
hashedPacketsGen.setKeyExpirationTime(false, 0);
// do this explicitly, although since we're rebuilding,
// this happens anyway
}
if (saveParcel.primaryIDChanged || !saveParcel.originalIDs.get(0).equals(saveParcel.userIDs.get(0))) {
if (saveParcel.primaryIDChanged ||
!saveParcel.originalIDs.get(0).equals(saveParcel.userIDs.get(0))) {
anyIDChanged = true;
ArrayList<Pair<String, PGPSignature>> sigList = new ArrayList<Pair<String, PGPSignature>>();
for (String userId : saveParcel.userIDs) {
String origID = saveParcel.originalIDs.get(userIDIndex);
if (origID.equals(userId) && !userId.equals(saveParcel.originalPrimaryID) && userIDIndex != 0) {
Iterator<PGPSignature> origSigs = masterPublicKey.getSignaturesForID(origID); //TODO: make sure this iterator only has signatures we are interested in
if (origID.equals(userId) && !saveParcel.newIDs[userIDIndex] &&
!userId.equals(saveParcel.originalPrimaryID) && userIDIndex != 0) {
Iterator<PGPSignature> origSigs = masterPublicKey.getSignaturesForID(origID);
// TODO: make sure this iterator only has signatures we are interested in
while (origSigs.hasNext()) {
PGPSignature origSig = origSigs.next();
sigList.add(new Pair<String, PGPSignature>(origID, origSig));
@ -457,18 +491,19 @@ public class PgpKeyOperation {
PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
sigList.add(new Pair<String, PGPSignature>(userId, certification));
}
if (!origID.equals("")) {
if (!saveParcel.newIDs[userIDIndex]) {
masterPublicKey = PGPPublicKey.removeCertification(masterPublicKey, origID);
}
userIDIndex++;
}
for (Pair<String, PGPSignature> toAdd : sigList) {
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, toAdd.first, toAdd.second);
masterPublicKey =
PGPPublicKey.addCertification(masterPublicKey, toAdd.first, toAdd.second);
}
} else {
for (String userId : saveParcel.userIDs) {
String origID = saveParcel.originalIDs.get(userIDIndex);
if (!origID.equals(userId)) {
if (!origID.equals(userId) || saveParcel.newIDs[userIDIndex]) {
anyIDChanged = true;
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
@ -481,10 +516,11 @@ public class PgpKeyOperation {
sGen.setUnhashedSubpackets(unhashedPacketsGen.generate());
}
PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
if (!origID.equals("")) {
if (!saveParcel.newIDs[userIDIndex]) {
masterPublicKey = PGPPublicKey.removeCertification(masterPublicKey, origID);
}
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
masterPublicKey =
PGPPublicKey.addCertification(masterPublicKey, userId, certification);
}
userIDIndex++;
}
@ -496,15 +532,14 @@ public class PgpKeyOperation {
for (String userId : saveParcel.userIDs) {
String origID = saveParcel.originalIDs.get(userIDIndex);
if (!(origID.equals(saveParcel.originalPrimaryID) && !saveParcel.primaryIDChanged)) {
Iterator<PGPSignature> sigs = masterPublicKey.getSignaturesForID(userId); //TODO: make sure this iterator only has signatures we are interested in
Iterator<PGPSignature> sigs = masterPublicKey.getSignaturesForID(userId);
// TODO: make sure this iterator only has signatures we are interested in
while (sigs.hasNext()) {
PGPSignature sig = sigs.next();
sigList.add(new Pair<String, PGPSignature>(userId, sig));
}
}
if (!userId.equals("")) {
masterPublicKey = PGPPublicKey.removeCertification(masterPublicKey, userId);
}
userIDIndex++;
}
anyIDChanged = true;
@ -530,7 +565,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
saveParcel.oldPassPhrase.toCharArray());
saveParcel.oldPassphrase.toCharArray());
//this generates one more signature than necessary...
PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
@ -551,7 +586,7 @@ public class PgpKeyOperation {
} else {
keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
saveParcel.oldPassPhrase.toCharArray());
saveParcel.oldPassphrase.toCharArray());
}
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey, subPrivateKey);
@ -583,23 +618,27 @@ public class PgpKeyOperation {
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
creationDate.setTime(subPublicKey.getCreationTime());
GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(i);
//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!
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0)
// 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!
long numDays = (expiryDate.getTimeInMillis() / 86400000) -
(creationDate.getTimeInMillis() / 86400000);
if (numDays <= 0) {
throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation);
}
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
} else {
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
//this happens anyway
hashedPacketsGen.setKeyExpirationTime(false, 0);
// do this explicitly, although since we're rebuilding,
// this happens anyway
}
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
//certifications will be discarded if the key is changed, because I think, for a start,
//they will be invalid. Binding certs are regenerated anyway, and other certs which
//need to be kept are on IDs and attributes
//TODO: don't let revoked keys be edited, other than removed - changing one would result in the
//revocation being wrong?
// certifications will be discarded if the key is changed, because I think, for a start,
// they will be invalid. Binding certs are regenerated anyway, and other certs which
// need to be kept are on IDs and attributes
// TODO: don't let revoked keys be edited, other than removed - changing one would
// result in the revocation being wrong?
}
}
@ -628,7 +667,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
saveParcel.newPassPhrase.toCharArray());
saveParcel.newPassphrase.toCharArray());
//update the passphrase
mKR = PGPSecretKeyRing.copyWithNewPassword(mKR, keyDecryptor, keyEncryptorNew);
@ -638,8 +677,10 @@ public class PgpKeyOperation {
Log.d(Constants.TAG, " ------- in private key -------");
for(String uid : new IterableIterator<String>(secretKeyRing.getPublicKey().getUserIDs())) {
for(PGPSignature sig : new IterableIterator<PGPSignature>(secretKeyRing.getPublicKey().getSignaturesForID(uid))) {
Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
for(PGPSignature sig : new IterableIterator<PGPSignature>(
secretKeyRing.getPublicKey().getSignaturesForID(uid))) {
Log.d(Constants.TAG, "sig: " +
PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
}
}
@ -647,14 +688,16 @@ public class PgpKeyOperation {
Log.d(Constants.TAG, " ------- in public key -------");
for(String uid : new IterableIterator<String>(publicKeyRing.getPublicKey().getUserIDs())) {
for(PGPSignature sig : new IterableIterator<PGPSignature>(publicKeyRing.getPublicKey().getSignaturesForID(uid))) {
Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
for(PGPSignature sig : new IterableIterator<PGPSignature>(
publicKeyRing.getPublicKey().getSignaturesForID(uid))) {
Log.d(Constants.TAG, "sig: " +
PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
}
}
*/
return new Pair<PGPSecretKeyRing,PGPPublicKeyRing>(mKR, pKR);
return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(mKR, pKR);
}
@ -667,7 +710,8 @@ public class PgpKeyOperation {
* @param passphrase Passphrase of the secret key
* @return A keyring with added certifications
*/
public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey, List<String> userIds, String passphrase)
public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey,
List<String> userIds, String passphrase)
throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException,
PGPException, SignatureException {
@ -701,7 +745,7 @@ public class PgpKeyOperation {
}
// fetch public key ring, add the certification and return it
for(String userId : new IterableIterator<String>(userIds.iterator())) {
for (String userId : new IterableIterator<String>(userIds.iterator())) {
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
}

View File

@ -21,9 +21,25 @@ import android.content.Context;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.BCPGOutputStream;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPCompressedDataGenerator;
import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData;
import org.spongycastle.openpgp.PGPLiteralDataGenerator;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPV3SignatureGenerator;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.*;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -33,7 +49,11 @@ import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;

View File

@ -18,7 +18,13 @@
package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.asn1.DERObjectIdentifier;
import org.spongycastle.asn1.x509.*;
import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
import org.spongycastle.asn1.x509.BasicConstraints;
import org.spongycastle.asn1.x509.GeneralName;
import org.spongycastle.asn1.x509.GeneralNames;
import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
import org.spongycastle.asn1.x509.X509Extensions;
import org.spongycastle.asn1.x509.X509Name;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey;
@ -29,13 +35,14 @@ import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
@ -43,6 +50,11 @@ import java.util.Date;
import java.util.Iterator;
import java.util.Vector;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class PgpToX509 {
public static final String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";
public static final String DN_COMMON_PART_OU = "OpenPGP Keychain cert";
@ -71,8 +83,9 @@ public class PgpToX509 {
* @throws Exception
* @author Bruno Harbulot
*/
public static X509Certificate createSelfSignedCert(PublicKey pubKey, PrivateKey privKey,
X509Name subject, Date startDate, Date endDate, String subjAltNameURI)
public static X509Certificate createSelfSignedCert(
PublicKey pubKey, PrivateKey privKey, X509Name subject, Date startDate, Date endDate,
String subjAltNameURI)
throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException,
SignatureException, CertificateException, NoSuchProviderException {
@ -170,10 +183,10 @@ public class PgpToX509 {
/**
* Creates a self-signed certificate from a PGP Secret Key.
*
* @param pgpSecKey PGP Secret Key (from which one can extract the public and private keys and other
* attributes).
* @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks should be done
* before calling this method)
* @param pgpSecKey PGP Secret Key (from which one can extract the public and private
* keys and other attributes).
* @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks
* should be done before calling this method)
* @param subjAltNameURI optional URI to embed in the subject alternative-name
* @return self-signed certificate
* @throws PGPException
@ -184,9 +197,9 @@ public class PgpToX509 {
* @throws CertificateException
* @author Bruno Harbulot
*/
public static X509Certificate createSelfSignedCert(PGPSecretKey pgpSecKey,
PGPPrivateKey pgpPrivKey, String subjAltNameURI) throws PGPException,
NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException,
public static X509Certificate createSelfSignedCert(
PGPSecretKey pgpSecKey, PGPPrivateKey pgpPrivKey, String subjAltNameURI)
throws PGPException, NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException,
SignatureException, CertificateException {
// get public key from secret key
PGPPublicKey pgpPubKey = pgpSecKey.getPublicKey();

View File

@ -22,14 +22,14 @@ import android.content.Context;
public class PgpGeneralMsgIdException extends Exception {
static final long serialVersionUID = 0xf812773343L;
private final int msgId;
private final int mMessageId;
public PgpGeneralMsgIdException(int msgId) {
super("msg[" + msgId + "]");
this.msgId = msgId;
public PgpGeneralMsgIdException(int messageId) {
super("msg[" + messageId + "]");
mMessageId = messageId;
}
public PgpGeneralException getContextualized(Context context) {
return new PgpGeneralException(context.getString(msgId), this);
return new PgpGeneralException(context.getString(mMessageId), this);
}
}

View File

@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;

View File

@ -17,7 +17,11 @@
package org.sufficientlysecure.keychain.provider;
import android.content.*;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
@ -48,6 +52,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class ProviderHelper {
@ -628,10 +634,10 @@ public class ProviderHelper {
return settings;
}
public static AccountSettings getApiAccountSettings(Context context, Uri uri) {
public static AccountSettings getApiAccountSettings(Context context, Uri accountUri) {
AccountSettings settings = null;
Cursor cur = context.getContentResolver().query(uri, null, null, null, null);
Cursor cur = context.getContentResolver().query(accountUri, null, null, null, null);
if (cur != null && cur.moveToFirst()) {
settings = new AccountSettings();
@ -650,6 +656,20 @@ public class ProviderHelper {
return settings;
}
public static Set<Long> getAllKeyIdsForApp(Context context, Uri uri) {
Set<Long> keyIds = new HashSet<Long>();
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
int keyIdColumn = cursor.getColumnIndex(KeychainContract.ApiAccounts.KEY_ID);
while (cursor.moveToNext()) {
keyIds.add(cursor.getLong(keyIdColumn));
}
}
return keyIds;
}
public static byte[] getApiAppSignature(Context context, String packageName) {
Uri queryUri = ApiApps.buildByPackageNameUri(packageName);

View File

@ -17,10 +17,6 @@
package org.sufficientlysecure.keychain.remote;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Id;
public class AppSettings {
private String mPackageName;
private byte[] mPackageSignature;

View File

@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.util.Log;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
public class OpenPgpService extends RemoteService {
@ -187,7 +188,8 @@ public class OpenPgpService extends RemoteService {
}
private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AccountSettings accSettings, boolean sign) {
ParcelFileDescriptor output, AccountSettings accSettings,
boolean sign) {
try {
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
@ -276,7 +278,7 @@ public class OpenPgpService extends RemoteService {
}
private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AccountSettings accSettings) {
ParcelFileDescriptor output, Set<Long> allowedKeyIds) {
try {
// Get Input- and OutputStream from ParcelFileDescriptor
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
@ -291,7 +293,8 @@ public class OpenPgpService extends RemoteService {
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
builder.allowSymmetricDecryption(false) // no support for symmetric encryption
.enforcedKeyId(accSettings.getKeyId()) // allow only the private key for this app for decryption
.allowedKeyIds(allowedKeyIds) // allow only private keys associated with
// accounts of this app
.passphrase(passphrase);
// TODO: currently does not support binary signed-only content
@ -299,9 +302,11 @@ public class OpenPgpService extends RemoteService {
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
// get PendingIntent for passphrase input, add it to given params and return to client
Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
Intent passphraseBundle =
getPassphraseBundleIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
return passphraseBundle;
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED ==
decryptVerifyResult.getStatus()) {
throw new PgpGeneralException("Decryption of symmetric content not supported by API!");
}
@ -452,7 +457,11 @@ public class OpenPgpService extends RemoteService {
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
return encryptAndSignImpl(data, input, output, accSettings, true);
} else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) {
return decryptAndVerifyImpl(data, input, output, accSettings);
String currentPkg = getCurrentCallingPackage();
Set<Long> allowedKeyIds =
ProviderHelper.getAllKeyIdsForApp(mContext,
KeychainContract.ApiAccounts.buildBaseUri(currentPkg));
return decryptAndVerifyImpl(data, input, output, allowedKeyIds);
} else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
return getKeyImpl(data);
} else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {

View File

@ -127,7 +127,7 @@ public abstract class RemoteService extends Service {
*
* @return package name
*/
private String getCurrentCallingPackage() {
protected String getCurrentCallingPackage() {
// TODO:
// callingPackages contains more than one entry when sharedUserId has been used...
String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
@ -243,7 +243,8 @@ public abstract class RemoteService extends Service {
return true;
} else {
throw new WrongPackageSignatureException(
"PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
"PACKAGE NOT ALLOWED! Signature wrong! (Signature not " +
"equals signature from database)");
}
}

View File

@ -17,7 +17,9 @@
package org.sufficientlysecure.keychain.remote.ui;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
@ -31,6 +33,7 @@ import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.ui.EditKeyActivity;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
@ -40,6 +43,8 @@ import org.sufficientlysecure.keychain.util.AlgorithmNames;
public class AccountSettingsFragment extends Fragment implements
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
private static final int REQUEST_CODE_CREATE_KEY = 0x00008884;
// model
private AccountSettings mAccSettings;
@ -162,7 +167,27 @@ public class AccountSettingsFragment extends Fragment implements
intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
// set default user id to account name TODO: not working currently in EditKey
intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, mAccSettings.getAccountName());
startActivityForResult(intent, 0);
startActivityForResult(intent, REQUEST_CODE_CREATE_KEY);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_CREATE_KEY: {
if (resultCode == Activity.RESULT_OK) {
// select newly created key
Uri newKeyUri = data.getData();
// TODO helper method for this?
mSelectKeyFragment.selectKey(Long.parseLong(newKeyUri.getPathSegments().get(1)));
}
break;
}
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
/**

View File

@ -32,12 +32,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.widget.FixedListView;

View File

@ -37,11 +37,9 @@ import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.util.Log;
public class AppsListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {

View File

@ -95,7 +95,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
if (ACTION_REGISTER.equals(action)) {
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
Log.d(Constants.TAG, "ACTION_REGISTER packageName: "+packageName);
Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName);
// Inflate a "Done"/"Cancel" custom action bar view
ActionBarHelper.setTwoButtonView(getSupportActionBar(),

View File

@ -26,22 +26,49 @@ import android.os.Messenger;
import android.os.RemoteException;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.*;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.*;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpImportExport;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.*;
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;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@ -461,16 +488,16 @@ public class KeychainIntentService extends IntentService
try {
/* Input */
SaveKeyringParcel saveParams = data.getParcelable(SAVE_KEYRING_PARCEL);
String oldPassPhrase = saveParams.oldPassPhrase;
String newPassPhrase = saveParams.newPassPhrase;
String oldPassphrase = saveParams.oldPassphrase;
String newPassphrase = saveParams.newPassphrase;
boolean canSign = true;
if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) {
canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN);
}
if (newPassPhrase == null) {
newPassPhrase = oldPassPhrase;
if (newPassphrase == null) {
newPassphrase = oldPassphrase;
}
long masterKeyId = saveParams.keys.get(0).getKeyID();
@ -480,7 +507,7 @@ public class KeychainIntentService extends IntentService
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 50, 100));
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId);
keyRing = keyOperations.changeSecretKeyPassphrase(keyRing,
oldPassPhrase, newPassPhrase);
oldPassphrase, newPassphrase);
setProgress(R.string.progress_saving_key_ring, 50, 100);
ProviderHelper.saveKeyRing(this, keyRing);
setProgress(R.string.progress_done, 100, 100);
@ -495,7 +522,7 @@ public class KeychainIntentService extends IntentService
ProviderHelper.saveKeyRing(this, pair.second);
setProgress(R.string.progress_done, 100, 100);
}
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
/* Output */
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
@ -746,11 +773,14 @@ public class KeychainIntentService extends IntentService
// verify downloaded key by comparing fingerprints
if (entry.getFingerPrintHex() != null) {
String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex(downloadedKey.getPublicKey().getFingerprint());
String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex(
downloadedKey.getPublicKey().getFingerprint());
if (downloadedKeyFp.equals(entry.getFingerPrintHex())) {
Log.d(Constants.TAG, "fingerprint of downloaded key is the same as the requested fingerprint!");
Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " +
"the requested fingerprint!");
} else {
throw new PgpGeneralException("fingerprint of downloaded key is NOT the same as the requested fingerprint!");
throw new PgpGeneralException("fingerprint of downloaded key is " +
"NOT the same as the requested fingerprint!");
}
}
@ -783,9 +813,9 @@ public class KeychainIntentService extends IntentService
ArrayList<String> userIds = data.getStringArrayList(CERTIFY_KEY_UIDS);
/* Operation */
String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this,
String signaturePassphrase = PassphraseCacheService.getCachedPassphrase(this,
masterKeyId);
if (signaturePassPhrase == null) {
if (signaturePassphrase == null) {
throw new PgpGeneralException("Unable to obtain passphrase");
}
@ -795,7 +825,7 @@ public class KeychainIntentService extends IntentService
PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(this,
masterKeyId);
publicKey = keyOperation.certifyKey(certificationKey, publicKey,
userIds, signaturePassPhrase);
userIds, signaturePassphrase);
publicRing = PGPPublicKeyRing.insertPublicKey(publicRing, publicKey);
// store the signed key in our local cache
@ -818,7 +848,7 @@ public class KeychainIntentService extends IntentService
return;
}
// contextualize the exception, if necessary
if(e instanceof PgpGeneralMsgIdException) {
if (e instanceof PgpGeneralMsgIdException) {
e = ((PgpGeneralMsgIdException) e).getContextualized(this);
}
Log.e(Constants.TAG, "ApgService Exception: ", e);

View File

@ -24,15 +24,24 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.*;
import android.util.Log;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.util.LongSparseArray;
import android.util.Log;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.Preferences;
@ -86,7 +95,7 @@ public class PassphraseCacheService extends Service {
Intent intent = new Intent(context, PassphraseCacheService.class);
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassphraseCacheTtl());
intent.putExtra(EXTRA_PASSPHRASE, passphrase);
intent.putExtra(EXTRA_KEY_ID, keyId);

View File

@ -32,56 +32,59 @@ public class SaveKeyringParcel implements Parcelable {
public ArrayList<String> userIDs;
public ArrayList<String> originalIDs;
public ArrayList<String> deletedIDs;
public boolean[] newIDs;
public boolean primaryIDChanged;
public boolean[] moddedKeys;
public ArrayList<PGPSecretKey> deletedKeys;
public ArrayList<GregorianCalendar> keysExpiryDates;
public ArrayList<Integer> keysUsages;
public String newPassPhrase;
public String oldPassPhrase;
public String newPassphrase;
public String oldPassphrase;
public boolean[] newKeys;
public ArrayList<PGPSecretKey> keys;
public String originalPrimaryID;
public SaveKeyringParcel() {}
private SaveKeyringParcel(Parcel source)
{
userIDs = (ArrayList<String>)source.readSerializable();
originalIDs = (ArrayList<String>)source.readSerializable();
deletedIDs = (ArrayList<String>)source.readSerializable();
private SaveKeyringParcel(Parcel source) {
userIDs = (ArrayList<String>) source.readSerializable();
originalIDs = (ArrayList<String>) source.readSerializable();
deletedIDs = (ArrayList<String>) source.readSerializable();
newIDs = source.createBooleanArray();
primaryIDChanged = source.readByte() != 0;
moddedKeys = source.createBooleanArray();
byte[] tmp = source.createByteArray();
if (tmp == null)
if (tmp == null) {
deletedKeys = null;
else
} else {
deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp);
keysExpiryDates = (ArrayList<GregorianCalendar>)source.readSerializable();
}
keysExpiryDates = (ArrayList<GregorianCalendar>) source.readSerializable();
keysUsages = source.readArrayList(Integer.class.getClassLoader());
newPassPhrase = source.readString();
oldPassPhrase = source.readString();
newPassphrase = source.readString();
oldPassphrase = source.readString();
newKeys = source.createBooleanArray();
keys = PgpConversionHelper.BytesToPGPSecretKeyList(source.createByteArray());
originalPrimaryID = source.readString();
}
@Override
public void writeToParcel(Parcel destination, int flags)
{
public void writeToParcel(Parcel destination, int flags) {
destination.writeSerializable(userIDs); //might not be the best method to store.
destination.writeSerializable(originalIDs);
destination.writeSerializable(deletedIDs);
destination.writeBooleanArray(newIDs);
destination.writeByte((byte) (primaryIDChanged ? 1 : 0));
destination.writeBooleanArray(moddedKeys);
byte[] tmp = null;
if (deletedKeys.size() != 0)
if (deletedKeys.size() != 0) {
tmp = PgpConversionHelper.PGPSecretKeyArrayListToBytes(deletedKeys);
}
destination.writeByteArray(tmp);
destination.writeSerializable(keysExpiryDates);
destination.writeList(keysUsages);
destination.writeString(newPassPhrase);
destination.writeString(oldPassPhrase);
destination.writeString(newPassphrase);
destination.writeString(oldPassphrase);
destination.writeBooleanArray(newKeys);
destination.writeByteArray(PgpConversionHelper.PGPSecretKeyArrayListToBytes(keys));
destination.writeString(originalPrimaryID);
@ -98,8 +101,7 @@ public class SaveKeyringParcel implements Parcelable {
};
@Override
public int describeContents()
{
public int describeContents() {
return 0;
}
}

View File

@ -32,13 +32,18 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@ -200,7 +205,8 @@ public class CertifyKeyActivity extends ActionBarActivity implements
byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
((TextView) findViewById(R.id.fingerprint)).setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
((TextView) findViewById(R.id.fingerprint))
.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
}
break;
case LOADER_ID_USER_IDS:
@ -294,7 +300,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements
// Bail out if there is not at least one user id selected
ArrayList<String> userIds = mUserIdsAdapter.getSelectedUserIds();
if(userIds.isEmpty()) {
if (userIds.isEmpty()) {
Toast.makeText(CertifyKeyActivity.this, "No User IDs to sign selected!",
Toast.LENGTH_SHORT).show();
return;

View File

@ -77,8 +77,10 @@ public class DecryptActivity extends DrawerActivity {
// Handle intent actions, maybe changes the bundles
handleActions(getIntent());
mTabsAdapter.addTab(DecryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapter.addTab(DecryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file));
mTabsAdapter.addTab(DecryptMessageFragment.class,
mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapter.addTab(DecryptFileFragment.class,
mFileFragmentBundle, getString(R.string.label_file));
mViewPager.setCurrentItem(mSwitchToTab);
}
@ -164,7 +166,8 @@ public class DecryptActivity extends DrawerActivity {
mSwitchToTab = PAGER_TAB_FILE;
} else {
Log.e(Constants.TAG,
"Direct binary data without actual file in filesystem is not supported. Please use the Remote Service API!");
"Direct binary data without actual file in filesystem is not supported. " +
"Please use the Remote Service API!");
Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
.show();
// end activity

View File

@ -200,9 +200,13 @@ public class DecryptFileFragment extends DecryptFragment {
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded());
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED ==
decryptVerifyResult.getStatus()) {
showPassphraseDialog(Id.key.symmetric);
} else {
AppMsg.makeText(getActivity(), R.string.decryption_successful,
AppMsg.STYLE_INFO).show();
if (mDeleteAfter.isChecked()) {
// Create and show dialog to delete original file
DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment

View File

@ -47,10 +47,14 @@ import java.util.regex.Matcher;
public class DecryptMessageFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext";
// view
private EditText mMessage;
private BootstrapButton mDecryptButton;
private BootstrapButton mDecryptFromCLipboardButton;
// model
private String mCiphertext;
/**
* Inflate the layout for this fragment
*/
@ -64,13 +68,13 @@ public class DecryptMessageFragment extends DecryptFragment {
mDecryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
decryptStart(null);
decryptClicked();
}
});
mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
decryptFromClipboard();
decryptFromClipboardClicked();
}
});
@ -88,7 +92,12 @@ public class DecryptMessageFragment extends DecryptFragment {
}
}
private void decryptFromClipboard() {
private void decryptClicked() {
mCiphertext = mMessage.getText().toString();
decryptStart(null);
}
private void decryptFromClipboardClicked() {
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
// only decrypt if clipboard content is available and a pgp message or cleartext signature
@ -98,8 +107,7 @@ public class DecryptMessageFragment extends DecryptFragment {
matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText);
}
if (matcher.matches()) {
String data = matcher.group(1);
mMessage.setText(data);
mCiphertext = matcher.group(1);
decryptStart(null);
} else {
AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_INFO)
@ -125,8 +133,7 @@ public class DecryptMessageFragment extends DecryptFragment {
// data
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
String message = mMessage.getText().toString();
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -147,7 +154,8 @@ public class DecryptMessageFragment extends DecryptFragment {
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded());
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED ==
decryptVerifyResult.getStatus()) {
showPassphraseDialog(Id.key.symmetric);
} else {
AppMsg.makeText(getActivity(), R.string.decryption_successful,

View File

@ -27,9 +27,18 @@ import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.*;
import android.widget.*;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.FontAwesomeText;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@ -58,7 +67,7 @@ public class DrawerActivity extends ActionBarActivity {
// if the left margin of the loaded layout is close to the
// one used in tablets then set drawer as open and locked
if( Math.abs(leftMarginLoaded - leftMarginInTablets) < errorInMarginAllowed) {
if (Math.abs(leftMarginLoaded - leftMarginInTablets) < errorInMarginAllowed) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, mDrawerList);
mDrawerLayout.setScrimColor(Color.TRANSPARENT);
mIsDrawerLocked = true;
@ -82,7 +91,7 @@ public class DrawerActivity extends ActionBarActivity {
// enable ActionBar app icon to behave as action to toggle nav drawer
// if the drawer is not locked
if ( !mIsDrawerLocked ) {
if (!mIsDrawerLocked) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
@ -109,20 +118,18 @@ public class DrawerActivity extends ActionBarActivity {
}
};
if ( !mIsDrawerLocked ) {
if (!mIsDrawerLocked) {
mDrawerLayout.setDrawerListener(mDrawerToggle);
} else {
// If the drawer is locked open make it un-focusable
// so that it doesn't consume all the Back button presses
mDrawerLayout.setFocusableInTouchMode(false);
}
// if (savedInstanceState == null) {
// selectItem(0);
// }
}
/**
* Uses startActivity to call the Intent of the given class
*
* @param drawerItem the class of the drawer item you want to load. Based on Constants.DrawerItems.*
*/
public void callIntentForDrawerItem(Class drawerItem) {
@ -150,16 +157,6 @@ public class DrawerActivity extends ActionBarActivity {
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
// menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
@ -182,26 +179,11 @@ public class DrawerActivity extends ActionBarActivity {
default:
return super.onOptionsItemSelected(item);
}
// Handle action buttons
// switch (item.getItemId()) {
// case R.id.action_websearch:
// // create intent to perform web search for this planet
// Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
// intent.putExtra(SearchManager.QUERY, getSupportActionBar().getTitle());
// // catch event that there's no activity to handle intent
// if (intent.resolveActivity(getPackageManager()) != null) {
// startActivity(intent);
// } else {
// Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
// }
// return true;
// default:
// return super.onOptionsItemSelected(item);
// }
}
/* The click listener for ListView in the navigation drawer */
/**
* The click listener for ListView in the navigation drawer
*/
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@ -218,7 +200,7 @@ public class DrawerActivity extends ActionBarActivity {
// setTitle(mDrawerTitles[position]);
// If drawer isn't locked just close the drawer and
// it will move to the selected item by itself (via drawer toggle listener)
if ( !mIsDrawerLocked ) {
if (!mIsDrawerLocked) {
mDrawerLayout.closeDrawer(mDrawerList);
// else move to the selected item yourself
} else {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -17,13 +17,8 @@
package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Vector;
import org.spongycastle.bcpg.sig.KeyFlags;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -33,19 +28,26 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBarActivity;
import android.view.*;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton;
import com.devspark.appmsg.AppMsg;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -63,20 +65,17 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.Editor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
import org.sufficientlysecure.keychain.ui.widget.SectionView;
import org.sufficientlysecure.keychain.ui.widget.UserIdEditor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import android.app.AlertDialog;
import android.support.v4.app.ActivityCompat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Vector;
public class EditKeyActivity extends ActionBarActivity implements EditorListener {
@ -89,10 +88,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
public static final String EXTRA_NO_PASSPHRASE = "no_passphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys";
// results when saving key
public static final String RESULT_EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String RESULT_EXTRA_USER_ID = "user_id";
// EDIT
private Uri mDataUri;
@ -102,9 +97,9 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
private SectionView mKeysView;
private String mCurrentPassphrase = null;
private String mNewPassPhrase = null;
private String mSavedNewPassPhrase = null;
private boolean mIsPassPhraseSet;
private String mNewPassphrase = null;
private String mSavedNewPassphrase = null;
private boolean mIsPassphraseSet;
private boolean mNeedsSaving;
private boolean mIsBrandNewKeyring = false;
@ -119,8 +114,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
ExportHelper mExportHelper;
public boolean needsSaving()
{
public boolean needsSaving() {
mNeedsSaving = (mUserIdsView == null) ? false : mUserIdsView.needsSaving();
mNeedsSaving |= (mKeysView == null) ? false : mKeysView.needsSaving();
mNeedsSaving |= hasPassphraseChanged();
@ -129,19 +123,15 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
}
public void somethingChanged()
{
public void somethingChanged() {
ActivityCompat.invalidateOptionsMenu(this);
//Toast.makeText(this, "Needs saving: " + Boolean.toString(mNeedsSaving) + "(" + Boolean.toString(mUserIdsView.needsSaving()) + ", " + Boolean.toString(mKeysView.needsSaving()) + ")", Toast.LENGTH_LONG).show();
}
public void onDeleted(Editor e, boolean wasNewItem)
{
public void onDeleted(Editor e, boolean wasNewItem) {
somethingChanged();
}
public void onEdited()
{
public void onEdited() {
somethingChanged();
}
@ -300,7 +290,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(
EditKeyActivity.this, masterKeyId);
finallySaveClicked();
checkEmptyIDsWanted();
}
}
};
@ -338,7 +328,9 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
cancelClicked(); //TODO: why isn't this triggered on my tablet - one of many ui problems I've had with this device. A code compatibility issue or a Samsung fail?
cancelClicked();
// TODO: why isn't this triggered on my tablet - one of many ui problems
// I've had with this device. A code compatibility issue or a Samsung fail?
return true;
case R.id.menu_key_edit_cancel:
cancelClicked();
@ -398,9 +390,10 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
if (!isSet) {
isSet = true;
String[] parts = PgpKeyHelper.splitUserId(userId);
if (parts[0] != null)
if (parts[0] != null) {
setTitle(parts[0]);
}
}
mUserIds.add(userId);
}
}
@ -409,8 +402,8 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
mCurrentPassphrase = "";
buildLayout(false);
mIsPassPhraseSet = PassphraseCacheService.hasPassphrase(this, masterKeyId);
if (!mIsPassPhraseSet) {
mIsPassphraseSet = PassphraseCacheService.hasPassphrase(this, masterKeyId);
if (!mIsPassphraseSet) {
// check "no passphrase" checkbox and remove button
mNoPassphrase.setChecked(true);
mChangePassphrase.setVisibility(View.GONE);
@ -429,10 +422,10 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
Bundle data = message.getData();
// set new returned passphrase!
mNewPassPhrase = data
mNewPassphrase = data
.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
updatePassPhraseButtonText();
updatePassphraseButtonText();
somethingChanged();
}
}
@ -458,6 +451,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
/**
* Build layout based on mUserId, mKeys and mKeysUsages Vectors. It creates Views for every user
* id and key.
*
* @param newKeys
*/
private void buildLayout(boolean newKeys) {
@ -471,23 +465,23 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
if(mIsPassPhraseSet){
if (mIsPassphraseSet) {
mChangePassphrase.setText(getString(R.string.btn_change_passphrase));
}
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mUserIdsView.setType(Id.type.user_id);
mUserIdsView.setCanEdit(mMasterCanSign);
mUserIdsView.setCanBeEdited(mMasterCanSign);
mUserIdsView.setUserIds(mUserIds);
mUserIdsView.setEditorListener(this);
container.addView(mUserIdsView);
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mKeysView.setType(Id.type.key);
mKeysView.setCanEdit(mMasterCanSign);
mKeysView.setCanBeEdited(mMasterCanSign);
mKeysView.setKeys(mKeys, mKeysUsages, newKeys);
mKeysView.setEditorListener(this);
container.addView(mKeysView);
updatePassPhraseButtonText();
updatePassphraseButtonText();
mChangePassphrase.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
@ -502,11 +496,11 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// remove passphrase
mSavedNewPassPhrase = mNewPassPhrase;
mNewPassPhrase = "";
mSavedNewPassphrase = mNewPassphrase;
mNewPassphrase = "";
mChangePassphrase.setVisibility(View.GONE);
} else {
mNewPassPhrase = mSavedNewPassPhrase;
mNewPassphrase = mSavedNewPassphrase;
mChangePassphrase.setVisibility(View.VISIBLE);
}
somethingChanged();
@ -524,23 +518,22 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
public boolean isPassphraseSet() {
if (mNoPassphrase.isChecked()) {
return true;
} else if ((mIsPassPhraseSet)
|| (mNewPassPhrase != null && !mNewPassPhrase.equals(""))) {
} else if ((mIsPassphraseSet)
|| (mNewPassphrase != null && !mNewPassphrase.equals(""))) {
return true;
} else {
return false;
}
}
public boolean hasPassphraseChanged()
{
public boolean hasPassphraseChanged() {
if (mNoPassphrase != null) {
if (mNoPassphrase.isChecked()) {
return mIsPassPhraseSet;
return mIsPassphraseSet;
} else {
return (mNewPassPhrase != null && !mNewPassPhrase.equals(""));
return (mNewPassphrase != null && !mNewPassphrase.equals(""));
}
}else {
} else {
return false;
}
}
@ -554,15 +547,16 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
}
String passphrase;
if (mIsPassPhraseSet)
if (mIsPassphraseSet) {
passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
else
} else {
passphrase = "";
}
if (passphrase == null) {
showPassphraseDialog(masterKeyId);
} else {
mCurrentPassphrase = passphrase;
finallySaveClicked();
checkEmptyIDsWanted();
}
} catch (PgpGeneralException e) {
Toast.makeText(this, getString(R.string.error_message, e.getMessage()),
@ -573,6 +567,50 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
}
}
private void checkEmptyIDsWanted() {
try {
ArrayList<String> userIDs = getUserIds(mUserIdsView);
List<Boolean> newIDs = mUserIdsView.getNewIDFlags();
ArrayList<String> originalIDs = mUserIdsView.getOriginalIDs();
int curID = 0;
for (String userID : userIDs) {
if (userID.equals("") && (!userID.equals(originalIDs.get(curID)) || newIDs.get(curID))) {
AlertDialog.Builder alert = new AlertDialog.Builder(
EditKeyActivity.this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
alert.setMessage(EditKeyActivity.this.getString(R.string.ask_empty_id_ok));
alert.setPositiveButton(EditKeyActivity.this.getString(android.R.string.yes),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
finallySaveClicked();
}
}
);
alert.setNegativeButton(this.getString(android.R.string.no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
}
);
alert.setCancelable(false);
alert.create().show();
return;
}
curID++;
}
} catch (PgpGeneralException e) {
Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage()));
Toast.makeText(this, getString(R.string.error_message, e.getMessage()),
Toast.LENGTH_SHORT).show();
}
finallySaveClicked();
}
private boolean[] toPrimitiveArray(final List<Boolean> booleanList) {
final boolean[] primitives = new boolean[booleanList.size()];
int index = 0;
@ -593,13 +631,14 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
saveParams.userIDs = getUserIds(mUserIdsView);
saveParams.originalIDs = mUserIdsView.getOriginalIDs();
saveParams.deletedIDs = mUserIdsView.getDeletedIDs();
saveParams.newIDs = toPrimitiveArray(mUserIdsView.getNewIDFlags());
saveParams.primaryIDChanged = mUserIdsView.primaryChanged();
saveParams.moddedKeys = toPrimitiveArray(mKeysView.getNeedsSavingArray());
saveParams.deletedKeys = mKeysView.getDeletedKeys();
saveParams.keysExpiryDates = getKeysExpiryDates(mKeysView);
saveParams.keysUsages = getKeysUsages(mKeysView);
saveParams.newPassPhrase = mNewPassPhrase;
saveParams.oldPassPhrase = mCurrentPassphrase;
saveParams.newPassphrase = mNewPassphrase;
saveParams.oldPassphrase = mCurrentPassphrase;
saveParams.newKeys = toPrimitiveArray(mKeysView.getNewKeysArray());
saveParams.keys = getKeys(mKeysView);
saveParams.originalPrimaryID = mUserIdsView.getOriginalPrimaryID();
@ -621,14 +660,12 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
Intent data = new Intent();
data.putExtra(RESULT_EXTRA_MASTER_KEY_ID, getMasterKeyId());
ArrayList<String> userIds = null;
try {
userIds = getUserIds(mUserIdsView);
} catch (PgpGeneralException e) {
Log.e(Constants.TAG, "exception while getting user ids", e);
}
data.putExtra(RESULT_EXTRA_USER_ID, userIds.get(0));
// return uri pointing to new created key
Uri uri = KeychainContract.KeyRings.buildGenericKeyRingUri(
String.valueOf(getMasterKeyId()));
data.setData(uri);
setResult(RESULT_OK, data);
finish();
}
@ -781,7 +818,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
return keysExpiryDates;
}
private void updatePassPhraseButtonText() {
private void updatePassphraseButtonText() {
mChangePassphrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase)
: getString(R.string.btn_set_passphrase));
}

View File

@ -155,12 +155,16 @@ public class EncryptActivity extends DrawerActivity implements
// Handle intent actions
handleActions(getIntent());
mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class, mAsymmetricFragmentBundle, getString(R.string.label_asymmetric));
mTabsAdapterMode.addTab(EncryptSymmetricFragment.class, mSymmetricFragmentBundle, getString(R.string.label_symmetric));
mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class,
mAsymmetricFragmentBundle, getString(R.string.label_asymmetric));
mTabsAdapterMode.addTab(EncryptSymmetricFragment.class,
mSymmetricFragmentBundle, getString(R.string.label_symmetric));
mViewPagerMode.setCurrentItem(mSwitchToMode);
mTabsAdapterContent.addTab(EncryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapterContent.addTab(EncryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file));
mTabsAdapterContent.addTab(EncryptMessageFragment.class,
mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapterContent.addTab(EncryptFileFragment.class,
mFileFragmentBundle, getString(R.string.label_file));
mViewPagerContent.setCurrentItem(mSwitchToContent);
}
@ -212,8 +216,10 @@ public class EncryptActivity extends DrawerActivity implements
long[] encryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
// preselect keys given by intent
mAsymmetricFragmentBundle.putLongArray(EncryptAsymmetricFragment.ARG_ENCRYPTION_KEY_IDS, encryptionKeyIds);
mAsymmetricFragmentBundle.putLong(EncryptAsymmetricFragment.ARG_SIGNATURE_KEY_ID, signatureKeyId);
mAsymmetricFragmentBundle.putLongArray(EncryptAsymmetricFragment.ARG_ENCRYPTION_KEY_IDS,
encryptionKeyIds);
mAsymmetricFragmentBundle.putLong(EncryptAsymmetricFragment.ARG_SIGNATURE_KEY_ID,
signatureKeyId);
mSwitchToMode = PAGER_MODE_ASYMMETRIC;
/**
@ -234,7 +240,8 @@ public class EncryptActivity extends DrawerActivity implements
mSwitchToContent = PAGER_CONTENT_FILE;
} else {
Log.e(Constants.TAG,
"Direct binary data without actual file in filesystem is not supported by Intents. Please use the Remote Service API!");
"Direct binary data without actual file in filesystem is not supported " +
"by Intents. Please use the Remote Service API!");
Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
.show();
// end activity

View File

@ -264,8 +264,8 @@ public class EncryptAsymmetricFragment extends Fragment {
case RESULT_CODE_SECRET_KEYS: {
if (resultCode == Activity.RESULT_OK) {
Uri uri_master_key = data.getData();
setSignatureKeyId(Long.valueOf(uri_master_key.getLastPathSegment()));
Uri uriMasterKey = data.getData();
setSignatureKeyId(Long.valueOf(uriMasterKey.getLastPathSegment()));
} else {
setSignatureKeyId(Id.key.none);
}

View File

@ -112,7 +112,7 @@ public class EncryptFileFragment extends Fragment {
});
mFileCompression = (Spinner) view.findViewById(R.id.fileCompression);
Choice[] choices = new Choice[]{
Choice[] choices = new Choice[] {
new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
+ getString(R.string.compression_fast) + ")"),
new Choice(Id.choice.compression.zip, "ZIP ("
@ -120,7 +120,8 @@ public class EncryptFileFragment extends Fragment {
new Choice(Id.choice.compression.zlib, "ZLIB ("
+ getString(R.string.compression_fast) + ")"),
new Choice(Id.choice.compression.bzip2, "BZIP2 ("
+ getString(R.string.compression_very_slow) + ")"),};
+ getString(R.string.compression_very_slow) + ")"),
};
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(getActivity(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@ -137,8 +138,8 @@ public class EncryptFileFragment extends Fragment {
mDeleteAfter = (CheckBox) view.findViewById(R.id.deleteAfterEncryption);
mShareAfter = (CheckBox) view.findViewById(R.id.shareAfterEncryption);
mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmour);
mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmour());
mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmor);
mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmor());
return view;
}
@ -223,9 +224,9 @@ public class EncryptFileFragment extends Fragment {
if (mEncryptInterface.isModeSymmetric()) {
// symmetric encryption
boolean gotPassPhrase = (mEncryptInterface.getPassphrase() != null
boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null
&& mEncryptInterface.getPassphrase().length() != 0);
if (!gotPassPhrase) {
if (!gotPassphrase) {
AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT)
.show();
return;
@ -252,8 +253,9 @@ public class EncryptFileFragment extends Fragment {
return;
}
if (mEncryptInterface.getSignatureKey() != 0
&& PassphraseCacheService.getCachedPassphrase(getActivity(), mEncryptInterface.getSignatureKey()) == null) {
if (mEncryptInterface.getSignatureKey() != 0 &&
PassphraseCacheService.getCachedPassphrase(getActivity(),
mEncryptInterface.getSignatureKey()) == null) {
showPassphraseDialog();
return;
@ -282,8 +284,10 @@ public class EncryptFileFragment extends Fragment {
}
data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase);
} else {
data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, mEncryptInterface.getSignatureKey());
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptInterface.getEncryptionKeys());
data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID,
mEncryptInterface.getSignatureKey());
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS,
mEncryptInterface.getEncryptionKeys());
}
Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename="

View File

@ -125,9 +125,9 @@ public class EncryptMessageFragment extends Fragment {
if (mEncryptInterface.isModeSymmetric()) {
// symmetric encryption
boolean gotPassPhrase = (mEncryptInterface.getPassphrase() != null
boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null
&& mEncryptInterface.getPassphrase().length() != 0);
if (!gotPassPhrase) {
if (!gotPassphrase) {
AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT)
.show();
return;
@ -150,8 +150,9 @@ public class EncryptMessageFragment extends Fragment {
return;
}
if (mEncryptInterface.getSignatureKey() != 0
&& PassphraseCacheService.getCachedPassphrase(getActivity(), mEncryptInterface.getSignatureKey()) == null) {
if (mEncryptInterface.getSignatureKey() != 0 &&
PassphraseCacheService.getCachedPassphrase(getActivity(),
mEncryptInterface.getSignatureKey()) == null) {
showPassphraseDialog(toClipboard);
return;
@ -182,8 +183,10 @@ public class EncryptMessageFragment extends Fragment {
}
data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase);
} else {
data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, mEncryptInterface.getSignatureKey());
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptInterface.getEncryptionKeys());
data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID,
mEncryptInterface.getSignatureKey());
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS,
mEncryptInterface.getEncryptionKeys());
boolean signOnly = (mEncryptInterface.getEncryptionKeys() == null
|| mEncryptInterface.getEncryptionKeys().length == 0);

View File

@ -168,7 +168,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
}
} else {
Log.e(Constants.TAG,
"IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or 'fingerprint' extra!");
"IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
"'fingerprint' extra!");
return;
}
@ -233,7 +234,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
* onNavigationItemSelected() should check whether the Fragment is already in existence
* inside your Activity."
* <p/>
* from http://stackoverflow.com/questions/10983396/fragment-oncreateview-and-onactivitycreated-called-twice/14295474#14295474
* from http://bit.ly/1dBYThO
* <p/>
* In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint,
* the fragment would be loaded twice resulting in the query being empty after the second load.
@ -337,7 +338,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
// } else {
// status.putString(
// EXTRA_ERROR,
// "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
// "Scanned fingerprint does NOT match the fingerprint of the received key. " +
// "You shouldnt trust this key.");
// }
// }
// } catch (QueryException e) {

View File

@ -65,7 +65,7 @@ public class ImportKeysClipboardFragment extends Fragment {
String sendText = "";
if (clipboardText != null) {
sendText = clipboardText.toString();
if(sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
if (sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
return;
}

View File

@ -29,7 +29,11 @@ import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.ui.adapter.*;
import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log;

View File

@ -17,6 +17,8 @@
package org.sufficientlysecure.keychain.ui;
import com.google.zxing.integration.android.IntentResult;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -28,8 +30,9 @@ import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton;
import com.google.zxing.integration.android.IntentResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;

View File

@ -21,6 +21,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -55,10 +56,6 @@ public class KeyListActivity extends DrawerActivity {
case R.id.menu_key_list_import:
callIntentForDrawerItem(Constants.DrawerItems.IMPORT_KEYS);
return true;
case R.id.menu_key_list_export:
mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB, null);
return true;
case R.id.menu_key_list_create:
createKey();
@ -67,9 +64,15 @@ public class KeyListActivity extends DrawerActivity {
case R.id.menu_key_list_create_expert:
createKeyExpert();
return true;
case R.id.menu_key_list_export_public:
mExportHelper.showExportKeysDialog(null,
Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB, null);
return true;
case R.id.menu_key_list_secret_export:
mExportHelper.showExportKeysDialog(null, Id.type.secret_key, Constants.Path.APP_DIR_FILE_SEC, null);
mExportHelper.showExportKeysDialog(null, Id.type.secret_key,
Constants.Path.APP_DIR_FILE_SEC, null);
return true;
default:

View File

@ -24,7 +24,11 @@ import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.*;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
@ -33,11 +37,21 @@ import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.view.*;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.*;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@ -191,9 +205,11 @@ public class KeyListFragment extends Fragment
ProviderHelper.getPublicKeyRingsRowIds(getActivity());
for (int i = 0; i < ids.length; i++) {
if (allPubRowIds.contains(ids[i])) {
masterKeyIds[i] = ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]);
masterKeyIds[i] =
ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]);
} else {
masterKeyIds[i] = ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]);
masterKeyIds[i] =
ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]);
}
}*/
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());

View File

@ -20,9 +20,15 @@ import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.preference.*;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
@ -38,11 +44,11 @@ public class PreferencesActivity extends PreferenceActivity {
public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
private PreferenceScreen mKeyServerPreference = null;
private static Preferences mPreferences;
private static Preferences sPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
mPreferences = Preferences.getPreferences(this);
sPreferences = Preferences.getPreferences(this);
super.onCreate(savedInstanceState);
// final ActionBar actionBar = getSupportActionBar();
@ -55,11 +61,11 @@ public class PreferencesActivity extends PreferenceActivity {
if (action != null && action.equals(ACTION_PREFS_GEN)) {
addPreferencesFromResource(R.xml.gen_preferences);
initializePassPassPhraceCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASS_PHRASE_CACHE_TTL));
initializePassPassphraceCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL));
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS);
String servers[] = mPreferences.getKeyServers();
String servers[] = sPreferences.getKeyServers();
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
servers.length, servers.length));
mKeyServerPreference
@ -68,7 +74,7 @@ public class PreferencesActivity extends PreferenceActivity {
Intent intent = new Intent(PreferencesActivity.this,
PreferencesKeyServerActivity.class);
intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS,
mPreferences.getKeyServers());
sPreferences.getKeyServers());
startActivityForResult(intent, Id.request.key_server_preference);
return false;
}
@ -104,8 +110,8 @@ public class PreferencesActivity extends PreferenceActivity {
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
entries, values);
initializeAsciiArmour(
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOUR));
initializeAsciiArmor(
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR));
initializeForceV3Signatures(
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
@ -125,7 +131,7 @@ public class PreferencesActivity extends PreferenceActivity {
}
String servers[] = data
.getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS);
mPreferences.setKeyServers(servers);
sPreferences.setKeyServers(servers);
mKeyServerPreference.setSummary(getResources().getQuantityString(
R.plurals.n_key_servers, servers.length, servers.length));
break;
@ -159,11 +165,11 @@ public class PreferencesActivity extends PreferenceActivity {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.gen_preferences);
initializePassPassPhraceCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASS_PHRASE_CACHE_TTL));
initializePassPassphraceCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL));
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS);
String servers[] = mPreferences.getKeyServers();
String servers[] = sPreferences.getKeyServers();
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
servers.length, servers.length));
mKeyServerPreference
@ -172,7 +178,7 @@ public class PreferencesActivity extends PreferenceActivity {
Intent intent = new Intent(getActivity(),
PreferencesKeyServerActivity.class);
intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS,
mPreferences.getKeyServers());
sPreferences.getKeyServers());
startActivityForResult(intent, Id.request.key_server_preference);
return false;
}
@ -188,7 +194,7 @@ public class PreferencesActivity extends PreferenceActivity {
}
String servers[] = data
.getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS);
mPreferences.setKeyServers(servers);
sPreferences.setKeyServers(servers);
mKeyServerPreference.setSummary(getResources().getQuantityString(
R.plurals.n_key_servers, servers.length, servers.length));
break;
@ -241,8 +247,8 @@ public class PreferencesActivity extends PreferenceActivity {
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
entries, values);
initializeAsciiArmour(
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOUR));
initializeAsciiArmor(
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR));
initializeForceV3Signatures(
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
@ -255,15 +261,15 @@ public class PreferencesActivity extends PreferenceActivity {
|| super.isValidFragment(fragmentName);
}
private static void initializePassPassPhraceCacheTtl(final IntegerListPreference mPassphraseCacheTtl) {
mPassphraseCacheTtl.setValue("" + mPreferences.getPassPhraseCacheTtl());
private static void initializePassPassphraceCacheTtl(final IntegerListPreference mPassphraseCacheTtl) {
mPassphraseCacheTtl.setValue("" + sPreferences.getPassphraseCacheTtl());
mPassphraseCacheTtl.setSummary(mPassphraseCacheTtl.getEntry());
mPassphraseCacheTtl
.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mPassphraseCacheTtl.setValue(newValue.toString());
mPassphraseCacheTtl.setSummary(mPassphraseCacheTtl.getEntry());
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
sPreferences.setPassphraseCacheTtl(Integer.parseInt(newValue.toString()));
return false;
}
});
@ -282,14 +288,14 @@ public class PreferencesActivity extends PreferenceActivity {
}
mEncryptionAlgorithm.setEntries(entries);
mEncryptionAlgorithm.setEntryValues(values);
mEncryptionAlgorithm.setValue("" + mPreferences.getDefaultEncryptionAlgorithm());
mEncryptionAlgorithm.setValue("" + sPreferences.getDefaultEncryptionAlgorithm());
mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
mEncryptionAlgorithm
.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mEncryptionAlgorithm.setValue(newValue.toString());
mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
mPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue
sPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue
.toString()));
return false;
}
@ -309,13 +315,13 @@ public class PreferencesActivity extends PreferenceActivity {
}
mHashAlgorithm.setEntries(entries);
mHashAlgorithm.setEntryValues(values);
mHashAlgorithm.setValue("" + mPreferences.getDefaultHashAlgorithm());
mHashAlgorithm.setValue("" + sPreferences.getDefaultHashAlgorithm());
mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
mHashAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mHashAlgorithm.setValue(newValue.toString());
mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
mPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString()));
sPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString()));
return false;
}
});
@ -326,14 +332,14 @@ public class PreferencesActivity extends PreferenceActivity {
int[] valueIds, String[] entries, String[] values) {
mMessageCompression.setEntries(entries);
mMessageCompression.setEntryValues(values);
mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression());
mMessageCompression.setValue("" + sPreferences.getDefaultMessageCompression());
mMessageCompression.setSummary(mMessageCompression.getEntry());
mMessageCompression
.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mMessageCompression.setValue(newValue.toString());
mMessageCompression.setSummary(mMessageCompression.getEntry());
mPreferences.setDefaultMessageCompression(Integer.parseInt(newValue
sPreferences.setDefaultMessageCompression(Integer.parseInt(newValue
.toString()));
return false;
}
@ -344,36 +350,36 @@ public class PreferencesActivity extends PreferenceActivity {
(final IntegerListPreference mFileCompression, String[] entries, String[] values) {
mFileCompression.setEntries(entries);
mFileCompression.setEntryValues(values);
mFileCompression.setValue("" + mPreferences.getDefaultFileCompression());
mFileCompression.setValue("" + sPreferences.getDefaultFileCompression());
mFileCompression.setSummary(mFileCompression.getEntry());
mFileCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mFileCompression.setValue(newValue.toString());
mFileCompression.setSummary(mFileCompression.getEntry());
mPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString()));
sPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString()));
return false;
}
});
}
private static void initializeAsciiArmour(final CheckBoxPreference mAsciiArmour) {
mAsciiArmour.setChecked(mPreferences.getDefaultAsciiArmour());
mAsciiArmour.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
private static void initializeAsciiArmor(final CheckBoxPreference mAsciiArmor) {
mAsciiArmor.setChecked(sPreferences.getDefaultAsciiArmor());
mAsciiArmor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mAsciiArmour.setChecked((Boolean) newValue);
mPreferences.setDefaultAsciiArmour((Boolean) newValue);
mAsciiArmor.setChecked((Boolean) newValue);
sPreferences.setDefaultAsciiArmor((Boolean) newValue);
return false;
}
});
}
private static void initializeForceV3Signatures(final CheckBoxPreference mForceV3Signatures) {
mForceV3Signatures.setChecked(mPreferences.getForceV3Signatures());
mForceV3Signatures.setChecked(sPreferences.getForceV3Signatures());
mForceV3Signatures
.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mForceV3Signatures.setChecked((Boolean) newValue);
mPreferences.setForceV3Signatures((Boolean) newValue);
sPreferences.setForceV3Signatures((Boolean) newValue);
return false;
}
});

View File

@ -32,7 +32,13 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;

View File

@ -187,20 +187,17 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan
return;
}
// Select Secret Key Activity delivers the intent which was sent by it using interface to Select
// Secret Key Fragment.Intent contains the passed Uri
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode & 0xFFFF) {
switch (requestCode) {
case REQUEST_CODE_SELECT_KEY: {
if (resultCode == Activity.RESULT_OK) {
mReceivedUri = data.getData();
//Must be restartLoader() or the data will not be updated on selecting a new key
getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
getActivity().getSupportLoaderManager().restartLoader(0, null, this);
mKeyUserId.setError(null);
}
break;
}

View File

@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import org.sufficientlysecure.keychain.util.Log;

View File

@ -37,7 +37,6 @@ 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;

View File

@ -32,7 +32,6 @@ import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import java.util.ArrayList;
@ -45,12 +44,12 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
protected List<ImportKeysListEntry> mData;
static class ViewHolder {
private TextView mainUserId;
private TextView mainUserIdRest;
private TextView keyId;
private TextView fingerprint;
private TextView algorithm;
private TextView status;
public TextView mainUserId;
public TextView mainUserIdRest;
public TextView keyId;
public TextView fingerprint;
public TextView algorithm;
public TextView status;
}
public ImportKeysAdapter(Activity activity) {

View File

@ -249,7 +249,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
/**
* Based on <a href="http://tools.ietf.org/html/rfc2440#section-9.1">OpenPGP Message Format</a>
*/
private final static SparseArray<String> ALGORITHM_IDS = new SparseArray<String>() {{
private static final SparseArray<String> ALGORITHM_IDS = new SparseArray<String>() {{
put(-1, "unknown"); // TODO: with resources
put(0, "unencrypted");
put(PGPPublicKey.RSA_GENERAL, "RSA");
@ -267,6 +267,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
* Based on <a href="http://tools.ietf.org/html/rfc2440#section-9.1">OpenPGP Message Format</a>
*/
public static String getAlgorithmFromId(int algorithmId) {
return (ALGORITHM_IDS.get(algorithmId) != null ? ALGORITHM_IDS.get(algorithmId) : ALGORITHM_IDS.get(-1));
return (ALGORITHM_IDS.get(algorithmId) != null ?
ALGORITHM_IDS.get(algorithmId) :
ALGORITHM_IDS.get(-1));
}
}

View File

@ -20,7 +20,11 @@ package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context;
import android.widget.ArrayAdapter;
import java.util.*;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
private final HashMap<Integer, String> mData;

View File

@ -21,10 +21,6 @@ import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import java.util.ArrayList;
@ -34,9 +30,9 @@ public class PagerTabStripAdapter extends FragmentPagerAdapter {
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
private final String title;
public final Class<?> clss;
public final Bundle args;
public final String title;
TabInfo(Class<?> clss, Bundle args, String title) {
this.clss = clss;

View File

@ -36,8 +36,8 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
public final Class<?> clss;
public final Bundle args;
TabInfo(Class<?> clss, Bundle args) {
this.clss = clss;

View File

@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context;
import android.content.res.ColorStateList;
import android.database.Cursor;
import android.graphics.Color;
import android.support.v4.widget.CursorAdapter;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
@ -149,8 +148,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter {
DateFormat.getDateFormat(context).format(expiryDate) + ")");
keyExpiry.setVisibility(View.VISIBLE);
}
else {
} else {
keyExpiry.setVisibility(View.GONE);
}
// if key is expired or revoked, strike through text

View File

@ -37,7 +37,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
private int mIndexUserId, mIndexRank;
final private ArrayList<Boolean> mCheckStates;
private final ArrayList<Boolean> mCheckStates;
public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) {
super(context, c, flags);
@ -55,16 +55,17 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
if(mCheckStates != null) {
if (mCheckStates != null) {
mCheckStates.clear();
if(newCursor != null) {
if (newCursor != null) {
int count = newCursor.getCount();
mCheckStates.ensureCapacity(count);
// initialize to true (use case knowledge: we usually want to sign all uids)
for(int i = 0; i < count; i++)
for (int i = 0; i < count; i++) {
mCheckStates.add(true);
}
}
}
return super.swapCursor(newCursor);
}
@ -100,8 +101,9 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
vAddress.setText(userId[1]);
// don't care further if checkboxes aren't shown
if(mCheckStates == null)
if (mCheckStates == null) {
return;
}
final CheckBox vCheckBox = (CheckBox) view.findViewById(R.id.checkBox);
final int position = cursor.getPosition();
@ -124,8 +126,8 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
public ArrayList<String> getSelectedUserIds() {
ArrayList<String> result = new ArrayList<String>();
for(int i = 0; i < mCheckStates.size(); i++) {
if(mCheckStates.get(i)) {
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
result.add(mCursor.getString(mIndexUserId));
}

View File

@ -138,9 +138,10 @@ public class CreateKeyDialogFragment extends DialogFragment {
final AdapterView.OnItemSelectedListener weakRsaListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
final Choice selectedAlgorithm = (Choice)algorithm.getSelectedItem();
final int selectedKeySize = Integer.parseInt((String)keySize.getSelectedItem());
final boolean isWeakRsa = (selectedAlgorithm.getId() == Id.choice.algorithm.rsa && selectedKeySize <= 1024);
final Choice selectedAlgorithm = (Choice) algorithm.getSelectedItem();
final int selectedKeySize = Integer.parseInt((String) keySize.getSelectedItem());
final boolean isWeakRsa = (selectedAlgorithm.getId() == Id.choice.algorithm.rsa &&
selectedKeySize <= 1024);
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(!isWeakRsa);
}

View File

@ -51,12 +51,12 @@ public class DeleteKeyDialogFragment extends DialogFragment {
public static final int MESSAGE_OKAY = 1;
public static final int MESSAGE_ERROR = 0;
private boolean isSingleSelection = false;
private boolean mIsSingleSelection = false;
private TextView mainMessage;
private CheckBox checkDeleteSecret;
private LinearLayout deleteSecretKeyView;
private View inflateView;
private TextView mMainMessage;
private CheckBox mCheckDeleteSecret;
private LinearLayout mDeleteSecretKeyView;
private View mInflateView;
private Messenger mMessenger;
@ -90,12 +90,12 @@ public class DeleteKeyDialogFragment extends DialogFragment {
//Setup custom View to display in AlertDialog
LayoutInflater inflater = activity.getLayoutInflater();
inflateView = inflater.inflate(R.layout.view_key_delete_fragment, null);
builder.setView(inflateView);
mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null);
builder.setView(mInflateView);
deleteSecretKeyView = (LinearLayout) inflateView.findViewById(R.id.deleteSecretKeyView);
mainMessage = (TextView) inflateView.findViewById(R.id.mainMessage);
checkDeleteSecret = (CheckBox) inflateView.findViewById(R.id.checkDeleteSecret);
mDeleteSecretKeyView = (LinearLayout) mInflateView.findViewById(R.id.deleteSecretKeyView);
mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage);
mCheckDeleteSecret = (CheckBox) mInflateView.findViewById(R.id.checkDeleteSecret);
builder.setTitle(R.string.warning);
/* TODO! redo
@ -104,7 +104,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
if (keyRingRowIds.length == 1) {
Uri dataUri;
ArrayList<Long> publicKeyRings; //Any one will do
isSingleSelection = true;
mIsSingleSelection = true;
long selectedRow = keyRingRowIds[0];
long keyType;
@ -120,16 +120,16 @@ public class DeleteKeyDialogFragment extends DialogFragment {
}
String userId = ProviderHelper.getUserId(activity, dataUri);
//Hide the Checkbox and TextView since this is a single selection,user will be notified thru message
deleteSecretKeyView.setVisibility(View.GONE);
//Set message depending on which key it is.
mainMessage.setText(getString(keyType == Id.type.secret_key ? R.string.secret_key_deletion_confirmation
: R.string.public_key_deletetion_confirmation, userId));
// Hide the Checkbox and TextView since this is a single selection,
// user will be notified thru message
mDeleteSecretKeyView.setVisibility(View.GONE);
// Set message depending on which key it is.
mMainMessage.setText(getString(keyType == Id.type.secret_key ?
R.string.secret_key_deletion_confirmation :
R.string.public_key_deletetion_confirmation, userId));
} else {
deleteSecretKeyView.setVisibility(View.VISIBLE);
mainMessage.setText(R.string.key_deletion_confirmation_multi);
mDeleteSecretKeyView.setVisibility(View.VISIBLE);
mMainMessage.setText(R.string.key_deletion_confirmation_multi);
}
@ -149,9 +149,10 @@ public class DeleteKeyDialogFragment extends DialogFragment {
String selectionIDs = "";
for (int i = 0; i < keyRingRowIds.length; i++) {
selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'";
if (i + 1 < keyRingRowIds.length)
if (i + 1 < keyRingRowIds.length) {
selectionIDs += ",";
}
}
selection += selectionIDs + ")";
Cursor cursor = activity.getContentResolver().query(queryUri, projection,
@ -167,30 +168,33 @@ public class DeleteKeyDialogFragment extends DialogFragment {
masterKeyId = cursor.getLong(0);
keyType = cursor.getLong(1);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId
+ ", keyType:" + (keyType == KeychainContract.KeyTypes.PUBLIC ? "Public" : "Private"));
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId +
", keyType:" +
(keyType == KeychainContract.KeyTypes.PUBLIC ?
"Public" : "Private"));
if (keyType == KeychainContract.KeyTypes.SECRET) {
if (checkDeleteSecret.isChecked() || isSingleSelection) {
ProviderHelper.deleteUnifiedKeyRing(activity, String.valueOf(masterKeyId), true);
if (mCheckDeleteSecret.isChecked() || mIsSingleSelection) {
ProviderHelper.deleteUnifiedKeyRing(activity,
String.valueOf(masterKeyId), true);
}
} else {
ProviderHelper.deleteUnifiedKeyRing(activity, String.valueOf(masterKeyId), false);
ProviderHelper.deleteUnifiedKeyRing(activity,
String.valueOf(masterKeyId), false);
}
}
//Check if the selected rows have actually been deleted
cursor = activity.getContentResolver().query(queryUri, projection, selection, null, null);
if (cursor == null || cursor.getCount() == 0 || !checkDeleteSecret.isChecked()) {
cursor = activity.getContentResolver().query(
queryUri, projection, selection, null, null);
if (cursor == null || cursor.getCount() == 0 ||
!mCheckDeleteSecret.isChecked()) {
isSuccessfullyDeleted = true;
}
} finally {
if (cursor != null) {
cursor.close();
}
}
dismiss();
@ -201,9 +205,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
sendMessageToHandler(MESSAGE_ERROR, null);
}
}
}
);
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
@ -234,5 +236,4 @@ public class DeleteKeyDialogFragment extends DialogFragment {
Log.w(Constants.TAG, "Messenger is null!", e);
}
}
}

View File

@ -111,7 +111,7 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
content = keyringArmored.get(0);
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs
// http://stackoverflow.com/questions/2620444/how-to-prevent-a-dialog-from-closing-when-a-button-is-clicked
// http://bit.ly/O5vfaR
alert.setPositiveButton(R.string.btn_next, null);
alert.setNegativeButton(android.R.string.cancel, null);

View File

@ -82,7 +82,7 @@ public class FoldableLinearLayout extends LinearLayout {
* @param attrs
*/
private void processAttributes(Context context, AttributeSet attrs) {
if(attrs != null) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.FoldableLinearLayout, 0, 0);
mFoldedIconName = a.getString(R.styleable.FoldableLinearLayout_foldedIcon);
@ -102,7 +102,7 @@ public class FoldableLinearLayout extends LinearLayout {
protected void onFinishInflate() {
// if the migration has already happened
// there is no need to move any children
if(!mHasMigrated) {
if (!mHasMigrated) {
migrateChildrenToContainer();
mHasMigrated = true;
}
@ -120,10 +120,10 @@ public class FoldableLinearLayout extends LinearLayout {
int childNum = getChildCount();
View[] children = new View[childNum];
for(int i = 0; i < childNum; i++) {
for (int i = 0; i < childNum; i++) {
children[i] = getChildAt(i);
}
if(children[0].getId() == R.id.foldableControl) {
if (children[0].getId() == R.id.foldableControl) {
}
@ -131,14 +131,14 @@ public class FoldableLinearLayout extends LinearLayout {
detachAllViewsFromParent();
// Inflate the inner foldable_linearlayout.xml
LayoutInflater inflator = (LayoutInflater)getContext().getSystemService(
LayoutInflater inflator = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mFoldableLayout = inflator.inflate(R.layout.foldable_linearlayout, this, true);
mFoldableContainer = (LinearLayout) mFoldableLayout.findViewById(R.id.foldableContainer);
// Push previously collected children into foldableContainer.
for(int i = 0; i < childNum; i++) {
for (int i = 0; i < childNum; i++) {
addView(children[i]);
}
}
@ -196,7 +196,7 @@ public class FoldableLinearLayout extends LinearLayout {
*/
@Override
public void addView(View child) {
if(mFoldableContainer != null) {
if (mFoldableContainer != null) {
mFoldableContainer.addView(child);
}
}

View File

@ -16,20 +16,6 @@
package org.sufficientlysecure.keychain.ui.widget;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPKeyFlags;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
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;
@ -47,16 +33,23 @@ import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.Choice;
import java.text.DateFormat;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private PGPSecretKey mKey;
@ -101,11 +94,13 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
date.set(year, monthOfYear, dayOfMonth);
if (mOriginalExpiryDate != null) {
long numDays = (date.getTimeInMillis() / 86400000) - (mOriginalExpiryDate.getTimeInMillis() / 86400000);
if (numDays == 0)
long numDays = (date.getTimeInMillis() / 86400000) -
(mOriginalExpiryDate.getTimeInMillis() / 86400000);
if (numDays == 0) {
setExpiryDate(mOriginalExpiryDate);
else
} else {
setExpiryDate(date);
}
} else {
setExpiryDate(date);
}
@ -201,8 +196,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
super.onFinishInflate();
}
public void setCanEdit(boolean bCanEdit) {
if (!bCanEdit) {
public void setCanBeEdited(boolean canBeEdited) {
if (!canBeEdited) {
mDeleteButton.setVisibility(View.INVISIBLE);
mExpiryDateButton.setEnabled(false);
mChkSign.setEnabled(false); //certify is always disabled
@ -228,23 +223,23 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
boolean isDSAKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.DSA);
if (isElGamalKey) {
mChkSign.setVisibility(View.INVISIBLE);
TableLayout table = (TableLayout)findViewById(R.id.table_keylayout);
TableRow row = (TableRow)findViewById(R.id.row_sign);
TableLayout table = (TableLayout) findViewById(R.id.table_keylayout);
TableRow row = (TableRow) findViewById(R.id.row_sign);
table.removeView(row);
}
if (isDSAKey) {
mChkEncrypt.setVisibility(View.INVISIBLE);
TableLayout table = (TableLayout)findViewById(R.id.table_keylayout);
TableRow row = (TableRow)findViewById(R.id.row_encrypt);
TableLayout table = (TableLayout) findViewById(R.id.table_keylayout);
TableRow row = (TableRow) findViewById(R.id.row_encrypt);
table.removeView(row);
}
if (!mIsMasterKey) {
mChkCertify.setVisibility(View.INVISIBLE);
TableLayout table = (TableLayout)findViewById(R.id.table_keylayout);
TableRow row = (TableRow)findViewById(R.id.row_certify);
TableLayout table = (TableLayout) findViewById(R.id.table_keylayout);
TableRow row = (TableRow) findViewById(R.id.row_certify);
table.removeView(row);
} else {
TextView mLabelUsage2= (TextView) findViewById(R.id.label_usage2);
TextView mLabelUsage2 = (TextView) findViewById(R.id.label_usage2);
mLabelUsage2.setVisibility(View.INVISIBLE);
}
@ -260,8 +255,9 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
} else {
mUsage = PgpKeyHelper.getKeyUsage(key);
mOriginalUsage = mUsage;
if (key.isMasterKey())
if (key.isMasterKey()) {
mChkCertify.setChecked(PgpKeyHelper.isCertificationKey(key));
}
mChkSign.setChecked(PgpKeyHelper.isSigningKey(key));
mChkEncrypt.setChecked(PgpKeyHelper.isEncryptionKey(key));
mChkAuthenticate.setChecked(PgpKeyHelper.isAuthenticationKey(key));
@ -323,19 +319,24 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
}
public int getUsage() {
mUsage = (mUsage & ~KeyFlags.CERTIFY_OTHER) | (mChkCertify.isChecked() ? KeyFlags.CERTIFY_OTHER : 0);
mUsage = (mUsage & ~KeyFlags.SIGN_DATA) | (mChkSign.isChecked() ? KeyFlags.SIGN_DATA : 0);
mUsage = (mUsage & ~KeyFlags.ENCRYPT_COMMS) | (mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_COMMS : 0);
mUsage = (mUsage & ~KeyFlags.ENCRYPT_STORAGE) | (mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_STORAGE : 0);
mUsage = (mUsage & ~KeyFlags.AUTHENTICATION) | (mChkAuthenticate.isChecked() ? KeyFlags.AUTHENTICATION : 0);
mUsage = (mUsage & ~KeyFlags.CERTIFY_OTHER) |
(mChkCertify.isChecked() ? KeyFlags.CERTIFY_OTHER : 0);
mUsage = (mUsage & ~KeyFlags.SIGN_DATA) |
(mChkSign.isChecked() ? KeyFlags.SIGN_DATA : 0);
mUsage = (mUsage & ~KeyFlags.ENCRYPT_COMMS) |
(mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_COMMS : 0);
mUsage = (mUsage & ~KeyFlags.ENCRYPT_STORAGE) |
(mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_STORAGE : 0);
mUsage = (mUsage & ~KeyFlags.AUTHENTICATION) |
(mChkAuthenticate.isChecked() ? KeyFlags.AUTHENTICATION : 0);
return mUsage;
}
public boolean needsSaving()
{
if (mIsNewKey)
public boolean needsSaving() {
if (mIsNewKey) {
return true;
}
boolean retval = (getUsage() != mOriginalUsage);
@ -345,21 +346,21 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
if (mOEDNull != mEDNull) {
dateChanged = true;
} else {
if(mOEDNull) //both null, no change
if (mOEDNull) {
//both null, no change
dateChanged = false;
else
} else {
dateChanged = ((mExpiryDate.compareTo(mOriginalExpiryDate)) != 0);
}
}
retval |= dateChanged;
return retval;
}
public boolean getIsNewKey()
{
public boolean getIsNewKey() {
return mIsNewKey;
}
}
class ExpiryDatePickerDialog extends DatePickerDialog {

View File

@ -16,23 +16,6 @@
package org.sufficientlysecure.keychain.ui.widget;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.spongycastle.openpgp.PGPKeyFlags;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.util.Choice;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -49,7 +32,10 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.spongycastle.openpgp.PGPKeyFlags;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
@ -61,7 +47,9 @@ import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.util.Choice;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Editor {
private LayoutInflater mInflater;
@ -73,10 +61,10 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize;
private boolean oldItemDeleted = false;
private boolean mOldItemDeleted = false;
private ArrayList<String> mDeletedIDs = new ArrayList<String>();
private ArrayList<PGPSecretKey> mDeletedKeys = new ArrayList<PGPSecretKey>();
private boolean mCanEdit = true;
private boolean mCanBeEdited = true;
private ActionBarActivity mActivity;
@ -119,9 +107,9 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
}
public void setCanEdit(boolean bCanEdit) {
mCanEdit = bCanEdit;
if (!mCanEdit) {
public void setCanBeEdited(boolean canBeEdited) {
mCanBeEdited = canBeEdited;
if (!mCanBeEdited) {
mPlusButton.setVisibility(View.INVISIBLE);
}
}
@ -150,13 +138,13 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
* {@inheritDoc}
*/
public void onDeleted(Editor editor, boolean wasNewItem) {
oldItemDeleted |= !wasNewItem;
if (oldItemDeleted) {
if (mType == Id.type.user_id)
mDeletedIDs.add(((UserIdEditor)editor).getOriginalID());
else if (mType == Id.type.key)
mDeletedKeys.add(((KeyEditor)editor).getValue());
mOldItemDeleted |= !wasNewItem;
if (mOldItemDeleted) {
if (mType == Id.type.user_id) {
mDeletedIDs.add(((UserIdEditor) editor).getOriginalID());
} else if (mType == Id.type.key) {
mDeletedKeys.add(((KeyEditor) editor).getValue());
}
}
this.updateEditorsVisible();
if (mEditorListener != null) {
@ -176,74 +164,71 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE);
}
public boolean needsSaving()
{
public boolean needsSaving() {
//check each view for needs saving, take account of deleted items
boolean ret = oldItemDeleted;
boolean ret = mOldItemDeleted;
for (int i = 0; i < mEditors.getChildCount(); ++i) {
Editor editor = (Editor) mEditors.getChildAt(i);
ret |= editor.needsSaving();
if (mType == Id.type.user_id)
ret |= ((UserIdEditor)editor).primarySwapped();
if (mType == Id.type.user_id) {
ret |= ((UserIdEditor) editor).primarySwapped();
}
}
return ret;
}
public boolean primaryChanged()
{
public boolean primaryChanged() {
boolean ret = false;
for (int i = 0; i < mEditors.getChildCount(); ++i) {
Editor editor = (Editor) mEditors.getChildAt(i);
if (mType == Id.type.user_id)
ret |= ((UserIdEditor)editor).primarySwapped();
if (mType == Id.type.user_id) {
ret |= ((UserIdEditor) editor).primarySwapped();
}
}
return ret;
}
public String getOriginalPrimaryID()
{ //NB: this will have to change when we change how Primary IDs are chosen, and so we need to be
public String getOriginalPrimaryID() {
//NB: this will have to change when we change how Primary IDs are chosen, and so we need to be
// careful about where Master key capabilities are stored... multiple primaries and
// revoked ones make this harder than the simple case we are continuing to assume here
for (int i = 0; i < mEditors.getChildCount(); ++i) {
Editor editor = (Editor) mEditors.getChildAt(i);
if (mType == Id.type.user_id) {
if(((UserIdEditor)editor).getIsOriginallyMainUserID()) {
return ((UserIdEditor)editor).getOriginalID();
if (((UserIdEditor) editor).getIsOriginallyMainUserID()) {
return ((UserIdEditor) editor).getOriginalID();
}
}
}
return null;
}
public ArrayList<String> getOriginalIDs()
{
public ArrayList<String> getOriginalIDs() {
ArrayList<String> orig = new ArrayList<String>();
if (mType == Id.type.user_id) {
for (int i = 0; i < mEditors.getChildCount(); ++i) {
UserIdEditor editor = (UserIdEditor) mEditors.getChildAt(i);
if (editor.isMainUserId())
if (editor.isMainUserId()) {
orig.add(0, editor.getOriginalID());
else
} else {
orig.add(editor.getOriginalID());
}
}
return orig;
} else {
return null;
}
}
public ArrayList<String> getDeletedIDs()
{
public ArrayList<String> getDeletedIDs() {
return mDeletedIDs;
}
public ArrayList<PGPSecretKey> getDeletedKeys()
{
public ArrayList<PGPSecretKey> getDeletedKeys() {
return mDeletedKeys;
}
public List<Boolean> getNeedsSavingArray()
{
public List<Boolean> getNeedsSavingArray() {
ArrayList<Boolean> mList = new ArrayList<Boolean>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
Editor editor = (Editor) mEditors.getChildAt(i);
@ -252,8 +237,20 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
return mList;
}
public List<Boolean> getNewKeysArray()
{
public List<Boolean> getNewIDFlags() {
ArrayList<Boolean> mList = new ArrayList<Boolean>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
UserIdEditor editor = (UserIdEditor) mEditors.getChildAt(i);
if (editor.isMainUserId()) {
mList.add(0, editor.getIsNewID());
} else {
mList.add(editor.getIsNewID());
}
}
return mList;
}
public List<Boolean> getNewKeysArray() {
ArrayList<Boolean> mList = new ArrayList<Boolean>();
if (mType == Id.type.key) {
for (int i = 0; i < mEditors.getChildCount(); ++i) {
@ -268,7 +265,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
* {@inheritDoc}
*/
public void onClick(View v) {
if (mCanEdit) {
if (mCanBeEdited) {
switch (mType) {
case Id.type.user_id: {
UserIdEditor view = (UserIdEditor) mInflater.inflate(
@ -318,7 +315,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
mEditors, false);
view.setEditorListener(this);
view.setValue(userId, mEditors.getChildCount() == 0, false);
view.setCanEdit(mCanEdit);
view.setCanBeEdited(mCanBeEdited);
mEditors.addView(view);
}
@ -339,7 +336,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(list.get(i), isMasterKey, usages.get(i), newKeys);
view.setCanEdit(mCanEdit);
view.setCanBeEdited(mCanBeEdited);
mEditors.addView(view);
}
@ -419,8 +416,9 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
mEditors, false);
view.setEditorListener(SectionView.this);
int usage = 0;
if (mEditors.getChildCount() == 0)
if (mEditors.getChildCount() == 0) {
usage = PGPKeyFlags.CAN_CERTIFY;
}
view.setValue(newKey, newKey.isMasterKey(), usage, true);
mEditors.addView(view);
SectionView.this.updateEditorsVisible();

View File

@ -16,11 +16,6 @@
package org.sufficientlysecure.keychain.ui.widget;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
@ -29,10 +24,18 @@ import android.util.Patterns;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.helper.ContactHelper;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ContactHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import java.util.regex.Matcher;
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
@ -49,8 +52,8 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
private boolean mOriginallyMainUserID;
private boolean mIsNewId;
public void setCanEdit(boolean bCanEdit) {
if (!bCanEdit) {
public void setCanBeEdited(boolean canBeEdited) {
if (!canBeEdited) {
mDeleteButton.setVisibility(View.INVISIBLE);
mName.setEnabled(false);
mIsMainUserId.setEnabled(false);
@ -85,8 +88,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
}
@Override
public void afterTextChanged(Editable s)
{
public void afterTextChanged(Editable s) {
if (mEditorListener != null) {
mEditorListener.onEdited();
}
@ -240,25 +242,24 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
@Override
public boolean needsSaving() {
boolean retval = false; //(mOriginallyMainUserID != isMainUserId());
retval |= !(mOriginalName.equals( ("" + mName.getText()).trim() ) );
retval |= !(mOriginalEmail.equals( ("" + mEmail.getText()).trim() ) );
retval |= !(mOriginalComment.equals( ("" + mComment.getText()).trim() ) );
retval |= !(mOriginalName.equals(("" + mName.getText()).trim()));
retval |= !(mOriginalEmail.equals(("" + mEmail.getText()).trim()));
retval |= !(mOriginalComment.equals(("" + mComment.getText()).trim()));
retval |= mIsNewId;
return retval;
}
public boolean getIsOriginallyMainUserID()
{
public boolean getIsOriginallyMainUserID() {
return mOriginallyMainUserID;
}
public boolean primarySwapped()
{
public boolean primarySwapped() {
return (mOriginallyMainUserID != isMainUserId());
}
public String getOriginalID()
{
public String getOriginalID() {
return mOriginalID;
}
public boolean getIsNewID() { return mIsNewId; }
}

View File

@ -29,22 +29,30 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.*;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry.getAlgorithmFromId;
public class HkpKeyServer extends KeyServer {
private static class HttpError extends Exception {
private static final long serialVersionUID = 1718783705229428893L;
@ -72,20 +80,22 @@ public class HkpKeyServer extends KeyServer {
/**
* pub:%keyid%:%algo%:%keylen%:%creationdate%:%expirationdate%:%flags%
* <ul>
* <li>%<b>keyid</b>% = this is either the fingerprint or the key ID of the key. Either the 16-digit or 8-digit
* key IDs are acceptable, but obviously the fingerprint is best.</li>
* <li>%<b>keyid</b>% = this is either the fingerprint or the key ID of the key.
* Either the 16-digit or 8-digit key IDs are acceptable, but obviously the fingerprint is best.
* </li>
* <li>%<b>algo</b>% = the algorithm number, (i.e. 1==RSA, 17==DSA, etc).
* See <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a></li>
* <li>%<b>keylen</b>% = the key length (i.e. 1024, 2048, 4096, etc.)</li>
* <li>%<b>creationdate</b>% = creation date of the key in standard
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of seconds since
* 1/1/1970 UTC time)</li>
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* seconds since 1/1/1970 UTC time)</li>
* <li>%<b>expirationdate</b>% = expiration date of the key in standard
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of seconds since
* 1/1/1970 UTC time)</li>
* <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any order. The
* meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
* the absence of a given flag does not necessarily mean the absence of the detail.
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* seconds since 1/1/1970 UTC time)</li>
* <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any
* order. The meaning of "disabled" is implementation-specific. Note that individual flags may
* be unimplemented, so the absence of a given flag does not necessarily mean the absence of the
* detail.
* <ul>
* <li>r == revoked</li>
* <li>d == disabled</li>
@ -94,7 +104,8 @@ public class HkpKeyServer extends KeyServer {
* </li>
* </ul>
*
* @see <a href="http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5.2">5.2. Machine Readable Indexes</a>
* @see <a href="http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5.2">
* 5.2. Machine Readable Indexes</a>
* in Internet-Draft OpenPGP HTTP Keyserver Protocol Document
*/
public static final Pattern PUB_KEY_LINE = Pattern
@ -105,17 +116,19 @@ public class HkpKeyServer extends KeyServer {
/**
* uid:%escaped uid string%:%creationdate%:%expirationdate%:%flags%
* <ul>
* <li>%<b>escaped uid string</b>% = the user ID string, with HTTP %-escaping for anything that isn't 7-bit
* safe as well as for the ":" character. Any other characters may be escaped, as desired.</li>
* <li>%<b>escaped uid string</b>% = the user ID string, with HTTP %-escaping for anything that
* isn't 7-bit safe as well as for the ":" character. Any other characters may be escaped, as
* desired.</li>
* <li>%<b>creationdate</b>% = creation date of the key in standard
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of seconds since
* 1/1/1970 UTC time)</li>
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* seconds since 1/1/1970 UTC time)</li>
* <li>%<b>expirationdate</b>% = expiration date of the key in standard
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of seconds since
* 1/1/1970 UTC time)</li>
* <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any order. The
* meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
* the absence of a given flag does not necessarily mean the absence of the detail.
* <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* seconds since 1/1/1970 UTC time)</li>
* <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any
* order. The meaning of "disabled" is implementation-specific. Note that individual flags may
* be unimplemented, so the absence of a given flag does not necessarily mean the absence of
* the detail.
* <ul>
* <li>r == revoked</li>
* <li>d == disabled</li>
@ -244,11 +257,10 @@ public class HkpKeyServer extends KeyServer {
entry.setBitStrength(Integer.parseInt(matcher.group(3)));
final int algorithmId = Integer.decode(matcher.group(2));
entry.setAlgorithm(getAlgorithmFromId(algorithmId));
entry.setAlgorithm(ImportKeysListEntry.getAlgorithmFromId(algorithmId));
// group 1 contains the full fingerprint (v4) or the long key id if available
// see https://bitbucket.org/skskeyserver/sks-keyserver/pull-request/12/fixes-for-machine-readable-indexes/diff
// and https://github.com/openpgp-keychain/openpgp-keychain/issues/259#issuecomment-38168176
// see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr
String fingerprintOrKeyId = matcher.group(1);
if (fingerprintOrKeyId.length() > 16) {
entry.setFingerPrintHex(fingerprintOrKeyId.toLowerCase(Locale.US));

View File

@ -1,4 +1,6 @@
/*
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

View File

@ -16,9 +16,10 @@
package org.sufficientlysecure.keychain.util;
import com.google.zxing.integration.android.IntentIntegrator;
import android.content.Intent;
import android.support.v4.app.Fragment;
import com.google.zxing.integration.android.IntentIntegrator;
/**
* IntentIntegrator for the V4 Android compatibility package.

View File

@ -24,7 +24,7 @@ public class IterableIterator<T> implements Iterable<T> {
public IterableIterator(Iterator<T> iter, boolean failsafe) {
mIter = iter;
if(failsafe && mIter == null) {
if (failsafe && mIter == null) {
// is there a better way?
mIter = new ArrayList<T>().iterator();
}

View File

@ -1,16 +1,20 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* http://www.apache.org/licenses/LICENSE-2.0
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.util;
public interface KeychainServiceListener {

View File

@ -17,7 +17,11 @@
package org.sufficientlysecure.keychain.util;
import java.util.concurrent.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

View File

@ -1,4 +1,6 @@
/*
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

View File

@ -36,7 +36,7 @@ public class ProgressScaler implements ProgressDialogUpdater {
* Set progressDialogUpdater of ProgressDialog by sending message to handler on UI thread
*/
public void setProgress(String message, int progress, int max) {
mWrapped.setProgress(message, mFrom+ progress*(mTo-mFrom)/max, mMax);
mWrapped.setProgress(message, mFrom + progress * (mTo - mFrom) / max, mMax);
}
public void setProgress(int resourceId, int progress, int max) {

View File

@ -18,14 +18,16 @@
package org.sufficientlysecure.keychain.util;
import android.graphics.Bitmap;
import android.graphics.Color;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import android.graphics.Bitmap;
import android.graphics.Color;
import org.sufficientlysecure.keychain.Constants;
import java.util.Hashtable;

View File

@ -54,7 +54,7 @@
android:orientation="horizontal">
<CheckBox
android:id="@+id/asciiArmour"
android:id="@+id/asciiArmor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"

View File

@ -2,11 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_key_list_import"
app:showAsAction="ifRoom|withText"
android:icon="@drawable/ic_action_add_person"
android:title="@string/menu_import" />
<item
android:id="@+id/menu_key_list_search"
@ -15,6 +10,17 @@
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|ifRoom" />
<item
android:id="@+id/menu_key_list_add"
app:showAsAction="ifRoom|withText"
android:icon="@drawable/ic_action_add_person"
android:title="@string/menu_add_keys">
<menu>
<item
android:id="@+id/menu_key_list_import"
app:showAsAction="never"
android:title="@string/menu_import" />
<item
android:id="@+id/menu_key_list_create"
app:showAsAction="never"
@ -24,15 +30,25 @@
android:id="@+id/menu_key_list_create_expert"
app:showAsAction="never"
android:title="@string/menu_create_key_expert" />
</menu>
</item>
<item
android:id="@+id/menu_key_list_export"
app:showAsAction="ifRoom|withText"
android:icon="@drawable/ic_action_import_export"
android:title="@string/menu_export_keys">
<menu>
<item
android:id="@+id/menu_key_list_export_public"
app:showAsAction="never"
android:title="@string/menu_export_keys" />
android:title="@string/menu_export_public_keys" />
<item
android:id="@+id/menu_key_list_secret_export"
app:showAsAction="never"
android:title="@string/menu_export_secret_keys" />
</menu>
</item>
</menu>

View File

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_key_list_multi_select_all"
android:icon="@drawable/ic_action_select_all"
android:title="@string/menu_select_all" />
<item
android:id="@+id/menu_key_list_multi_export"
android:icon="@drawable/ic_action_import_export"
@ -17,5 +13,9 @@
android:id="@+id/menu_key_list_multi_delete"
android:icon="@drawable/ic_action_discard"
android:title="@string/menu_delete_key" />
<item
android:id="@+id/menu_key_list_multi_select_all"
android:icon="@drawable/ic_action_select_all"
android:title="@string/menu_select_all" />
</menu>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
<p>¡Gracias a todos los solicitantes de Google Summer of Code 2014, por hacer esta aplicación productiva y libre de errores!
Además de varios parches pequeños, un notable número de correcciones fueron hechas por las siguientes personas (en orden alfabético):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>nueva lista unificada de claves</li>
<li>huella digital de la clave coloreada</li>
<li>compatibilidad con puertos del servidor de claves</li>
<li>desactivar la posibilidad de generar claves débiles</li>
<li>mucho más trabajo en el interior de la API</li>
<li>certificar las IDs de usuario</li>
<li>consulta al servidor de claves basadas en lecturas mecánicas</li>
<li>cerrar navigation drawer en tabletas</li>
<li>sugerencias para emails en la creación de claves</li>
<li>buscar en las listas de claves públicas</li>
<li>y muchas más mejoras y correcciones...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>corrección del fallo cuando se actualiza desde versiones anteriores</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
<p>Merci à tous les participants de « Google Summer of Code 2014 » qui ont rendu cette version riche en fonctions et sans bogue !
À part plusieurs petits correctifs, un nombre notable de correctifs ont été apportés par les personnes suivantes (par ordre alphabétique) :
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>Nouvelle liste de clefs unifiée</li>
<li>empreinte de clef colorée</li>
<li>prise en charge des ports du serveur de clefs</li>
<li>désactiver la possibilité de générer des clefs faibles</li>
<li>bien plus de travail interne sur l'API</li>
<li>certifier les ID des utilisateurs</li>
<li>requête du serveur de clef basée sur une sortie lisible par la machine</li>
<li>verrouiller le tiroir de navigation sur les tablettes</li>
<li>suggestions de courriels à la création des clefs</li>
<li>recherche dans les listes de clefs publiques</li>
<li>et bien plus d'améliorations et de correctifs...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>correctif de plantage lors de la mise à niveau des anciennes versions</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -22,7 +22,7 @@
</ul>
<h2>Sviluppatori APG 1.x</h2>
<ul>
<li>Thialfihar (Lead developer)</li>
<li>Thialfihar (Capo Sviluppatore)</li>
<li>'Senecaso' (QRCode, firma chiavi, caricamento chiavi)</li>
<li>Markus Doits</li>
</ul>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<p>Grazie a tutti i partecipanti di Google Summer of Code 2014 che hanno reso questo rilascio ricco di caratteristiche e privo di bug!
Oltre a numerose piccole correzioni, un notevole numero di patch sono fatte dalle seguenti persone (in ordine alfabetico):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paolo Sarbinowski, Sreeram Boyapati, Vincent Breitmoser. </p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>nuova lista chiave unificata</li>
<li>impronta chiave colorata</li>
<li>supporto per porte</li>
<li>disattiva la possibilità di generare chiavi deboli</li>
<li>molto più lavoro interno sulle API</li>
<li>certificazione ID utente</li>
<li>interrogazione keyserver basate su output leggibile a livello macchina</li>
<li>blocco del menu di navigazione sui tablet</li>
<li>suggerimenti per e-mail sulla creazione di chiavi</li>
<li>ricerca nelle liste di chiavi pubbliche</li>
<li>e molti altri miglioramenti e correzioni ...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>correzione del crash quando si aggiorna da versioni precedenti</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Per iniziare</h2>
<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>In primo luogo è necessario una coppia di chiavi personale. Creane una tramite l'opzione nel menu "Contatti" o importando coppie di chiavi esistenti tramite "Importa Chiavi". Successivamente, è possibile scaricare le chiavi dei vostri amici o scambiarle con i codici QR o NFC.</p>
<p>Si raccomanda di installare <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> per una migliore selezione dei file e <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> per scansionare i codici QR. I collegamenti verranno aperti in Google Play Store o F-Droid per l'installazione.</p>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
<p>このリリースにおいて適用したリッチでバグのない機能を作ってくれたGoogle Summer of Code 2014の参加者たちに感謝を!
また、以下の人達(アルファベット順)の作ってくれたいくつもののさなパッチや相当数のパッチにも:
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>新しい統合キーリスト</li>
<li>鍵指紋のカラー化</li>
<li>鍵サーバのポート設定のサポート</li>
<li>弱い鍵の生成が可能だったのを無効化</li>
<li>さらなるAPIでの内部動作</li>
<li>ユーザーIDの検証</li>
<li>鍵サーバへの要求をマシンリーダブル出力を基盤にした</li>
<li>タブレットでのナビゲーションドロワーのロック</li>
<li>鍵の生成についてメールでのサジェスト</li>
<li>公開鍵リスト内での検索</li>
<li>そしてさらなる改善と修正...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>古いバージョンからのアップデートでクラッシュすることに対するホットフィックス</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -2,7 +2,7 @@
<head></head>
<body>
<h2>入門</h2>
<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>最初にあなたの個人用鍵ペアが必要になります。オプションメニューの"連絡先"で生成するか、"鍵のインポート"から既存の鍵ペアをインポートします。その後、あなたの友人の鍵をダウンロード、もしくはQRコードやNFCで交換します。</p>
<p>ファイルの選択を拡張するには<a href="market://details?id=org.openintents.filemanager">OI File Manager</a><a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a>を生成したQRコードのスキャンのため、それぞれのインストールを必要とします。 リンクをクリックして、Google Play Store上かF-Droidからインストールしてください。</p>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
<p>Podziękowania dla wszystkich kandydatów do Google Summer of Code 2014 którzy uczynili to wydanie bogatym w nowe funkcje i pozbawione błedów!
Poza kilkoma małymi poprawkami, znaczna ilość aktualizacji została wykonana przez poniższe osoby (w kolejności alfabetycznej):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>nowa ujednolicona lista kluczy</li>
<li>pokolowane odciski klucza</li>
<li>obsługa portów w serwerach kluczy</li>
<li>zablokowana możliwość generowania słabych kluczy</li>
<li>wiele wewnętrznych prac nad API</li>
<li>podpisywanie identyfikatorów użytkowników</li>
<li>zapytania do serwera kluczy wykorzystują wydajniejszą komunikację maszynową</li>
<li>zablokowany panel nawigacyjny na tabletach</li>
<li>podpowiedzi do adresu email przy tworzeniu kluczy</li>
<li>wyszukiwanie w liście publicznych kluczy</li>
<li>i wiele innych usprawnień i poprawek...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>szybka poprawka awarii aplikacji przy aktualizacji ze starszej wersji</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -22,7 +22,7 @@
</ul>
<h2>Разработчики APG 1.x</h2>
<ul>
<li>Thialfihar (Lead developer)</li>
<li>Thialfihar (главный разработчик)</li>
<li>'Senecaso' (QR коды, подписание и загрузка ключей)</li>
<li>Markus Doits</li>
</ul>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
<p>Спасибо всем участникам Google Summer of Code 2014, которые помогли сделать этот выпуск, добавив функции и исправив ошибки!
Из общего числа патчей, особенный вклад внесли следующие люди (в алфавитном порядке):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>новый объединенный список ключей</li>
<li>цветовая индикация отпечатков ключей</li>
<li>поддержка портов серверов ключей</li>
<li>отключена возможность создавать слабые ключи</li>
<li>ещё больше улучшений работы API</li>
<li>сертификация пользовательских данных</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes…</li>
<li>фиксация панели на планшетах</li>
<li>подсказки email при создании ключей</li>
<li>поиск в списках публичных ключей</li>
<li>и множество других исправлений и улучшений...</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>исправление ошибки при обновлении со старых версий</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -2,7 +2,7 @@
<head></head>
<body>
<h2>Приступая</h2>
<p>First you need a personal key pair. Create one via the option menus in "Contacts" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<p>Для начала вам понадобится своя пара ключей. Создайте её через меню раздела "Контакты" или импортируйте ранее созданный секретный ключ через меню "Импорт ключей". После этого вы сможете скачать ключи ваших друзей или обменяться ключами посредством QR кодов или NFC.</p>
<p>Рекомендуется установить <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> для удобного выбора файлов и <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> для распознавания QR кодов. Перейдите по ссылкам на соответствующие страницы Google Play или F-Droid для дальнейшей установки.</p>

View File

@ -15,9 +15,9 @@
<li>Даніель Габ</li>
<li>Ґреґ Вітчак</li>
<li>Міроджін Бакші</li>
<li>Nikhil Peter Raj</li>
<li>Ніхіл Петер Радж</li>
<li>Пауль Сарбіновський</li>
<li>Sreeram Boyapati</li>
<li>Срірам Вояпаті</li>
<li>Вінсент Брейтмозер</li>
</ul>
<h2>Розробники APG 1.x</h2>

View File

@ -2,25 +2,25 @@
<head></head>
<body>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
<p>Дякуємо усім заявникам Google Summer of Code 2014, які зробили цю версію багатшу на функції та вільну від помилок!
Крім окремих незначних латок, значне число латок зробили наступні люди (у алфавітному порядку):
Даніель Гаман, Даніель Габ, Ґреґ Вітчак, Міроджін Бакші, Ніхіл Петер Радж, Пауль Сарбіновський, Срірам Бояпаті, Вінсент Брейтмосер.</p>
<ul>
<li>new unified key list</li>
<li>colorized key fingerprint</li>
<li>support for keyserver ports</li>
<li>deactivate possibility to generate weak keys</li>
<li>much more internal work on the API</li>
<li>certify user ids</li>
<li>keyserver query based on machine-readable output</li>
<li>lock navigation drawer on tablets</li>
<li>suggestions for emails on creation of keys</li>
<li>search in public key lists</li>
<li>and much more improvements and fixes</li>
<li>новий єдиний перелік ключів</li>
<li>кольоровий відбиток ключа</li>
<li>підтримка для портів сервера ключів</li>
<li>деактивувати можливість генерувати слабкі ключі</li>
<li>набагато більше внутрішньої роботи на API</li>
<li>сертифікувати ідентифікатори користувача</li>
<li>запит сервера ключів на основі машиночитабельного виводу</li>
<li>блокувати панель навігації на планшетах</li>
<li>пропозиції для листів при створенні ключів</li>
<li>пошук у списках відкритих ключів</li>
<li>і багато інших покращень та виправлень</li>
</ul>
<h2>2.3.1</h2>
<ul>
<li>hotfix for crash when upgrading from old versions</li>
<li>свіже виправлення збою при оновленні із старих версій</li>
</ul>
<h2>2.3</h2>
<ul>

View File

@ -5,6 +5,14 @@ And don't add newlines before or after p tags because of transifex -->
<head>
</head>
<body>
<h2>2.5</h2>
<ul>
<li>fix decryption of symmetric pgp messages/files</li>
<li>refactored edit key screen (thanks to Ash Hughes)</li>
<li>OpenPGP API version 3 (multiple api accounts, internal fixes)</li>
<li>new modern design for encrypt/decrypt screens</li>
</ul>
<h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):

View File

@ -29,6 +29,7 @@
<!--label-->
<string name="unknown_status"></string>
<!--choice-->
<!--key flags-->
<!--sentences-->
<!--errors
no punctuation, all lowercase,

View File

@ -55,8 +55,6 @@
<string name="btn_delete">Löschen</string>
<string name="btn_no_date">Keine</string>
<string name="btn_okay">Okay</string>
<string name="btn_change_passphrase">Passwort ändern</string>
<string name="btn_set_passphrase">Passwort setzen</string>
<string name="btn_search">Suchen</string>
<string name="btn_export_to_server">Auf Schlüsselserver hochladen</string>
<string name="btn_next">Weiter</string>
@ -73,7 +71,6 @@
<string name="menu_import_from_qr_code">QR-Code</string>
<string name="menu_import">Importieren</string>
<string name="menu_import_from_nfc">NFC</string>
<string name="menu_export_keys">Alle Schlüssel exportieren</string>
<string name="menu_export_secret_keys">Alle geheimen Schlüssel exportieren</string>
<string name="menu_export_key">In Datei exportieren</string>
<string name="menu_delete_key">Schlüssel löschen</string>
@ -129,8 +126,6 @@
<string name="label_name">Name</string>
<string name="label_comment">Kommentar</string>
<string name="label_email">E-Mail</string>
<string name="label_sign_user_id">Benutzer ID unterschreiben</string>
<string name="label_sign_email">Email unterschreiben</string>
<string name="label_send_key">Schlüssel nach Beglaubigung auf ausgewählten Schlüsselserver hochladen</string>
<string name="label_fingerprint">Fingerabdruck</string>
<string name="select_keys_button_default">Auswählen</string>
@ -161,9 +156,6 @@
<string name="secret_key">Privater Schlüssel:</string>
<!--choice-->
<string name="choice_none">Keine</string>
<string name="choice_sign_only">Nur Signieren</string>
<string name="choice_encrypt_only">Nur Verschlüsseln</string>
<string name="choice_sign_and_encrypt">Signieren und Verschlüsseln</string>
<string name="choice_15secs">15 s</string>
<string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string>
@ -183,21 +175,18 @@
<string name="warning">Warnung</string>
<string name="error">Fehler</string>
<string name="error_message">Fehler: %s</string>
<!--key flags-->
<!--sentences-->
<string name="wrong_passphrase">Falsches Passwort.</string>
<string name="using_clipboard_content">Verwende Inhalt der Zwischenablage.</string>
<string name="set_a_passphrase">Zuerst ein Passwort setzen.</string>
<string name="no_filemanager_installed">Kein passender Dateimanager installiert.</string>
<string name="passphrases_do_not_match">Die Passwörter stimmten nicht überein.</string>
<string name="passphrase_must_not_be_empty">Leere Passwörter sind nicht erlaubt.</string>
<string name="passphrase_for_symmetric_encryption">Symmetrische Verschlüsselung.</string>
<string name="passphrase_for">Passwort für \'%s\' eingeben</string>
<string name="file_delete_confirmation">%s\nwirklich löschen?</string>
<string name="file_delete_successful">Erfolgreich gelöscht.</string>
<string name="no_file_selected">Zuerst eine Datei auswählen.</string>
<string name="decryption_successful">Erfolgreich entschlüsselt.</string>
<string name="encryption_successful">Erfolgreich verschlüsselt.</string>
<string name="encryption_to_clipboard_successful">Erfolgreich in die Zwischenablage verschlüsselt.</string>
<string name="enter_passphrase_twice">Passwort zweimal eingeben.</string>
<string name="select_encryption_key">Mindestens einen Schlüssel zum verschlüsseln auswählen.</string>
<string name="select_encryption_or_signature_key">Mindestens einen Schlüssel zum Verschlüsseln oder einen zum Signieren auswählen.</string>
@ -416,9 +405,6 @@
<string name="key_view_tab_main">Info</string>
<string name="key_view_tab_certs">Zertifikationen</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Kontakte</string>
<string name="nav_encrypt">Verschlüsseln</string>
<string name="nav_decrypt">Entschlüsseln</string>
<string name="nav_import">Schlüssel Importieren</string>
<string name="nav_secret_keys">Meine Schlüssel</string>
<string name="nav_apps">Registrierte Anwendungen</string>

View File

@ -15,8 +15,6 @@
<string name="btn_delete">Διαγραφή</string>
<string name="btn_no_date">Κανένα</string>
<string name="btn_okay">ΟΚ</string>
<string name="btn_change_passphrase">Αλλαγή κωδικού</string>
<string name="btn_set_passphrase">Επέλεξε Κωδικό</string>
<!--menu-->
<string name="menu_delete_key">Διαγραφής κλειδιού</string>
<string name="menu_create_key">Δημιουργίας κλειδιού</string>
@ -34,6 +32,7 @@
<string name="label_email">Ηλεκτρονικό ταχυδρομίο</string>
<string name="unknown_status"></string>
<!--choice-->
<!--key flags-->
<!--sentences-->
<!--errors
no punctuation, all lowercase,

View File

@ -36,8 +36,6 @@
<string name="btn_delete">Borrar</string>
<string name="btn_no_date">Ninguno</string>
<string name="btn_okay">Ok</string>
<string name="btn_change_passphrase">Cambiar contraseña</string>
<string name="btn_set_passphrase">Establecer contraseña</string>
<string name="btn_search">Buscar</string>
<string name="btn_next">Siguiente</string>
<string name="btn_back">Atrás</string>
@ -46,7 +44,6 @@
<string name="menu_import_from_file">Importar desde archivo</string>
<string name="menu_import_from_qr_code">Importar desde código QR</string>
<string name="menu_import_from_nfc">Importar desde NFC</string>
<string name="menu_export_keys">Exportar todas las claves</string>
<string name="menu_export_key">Exportar a archivo</string>
<string name="menu_delete_key">Borrar clave</string>
<string name="menu_create_key">Crear clave</string>
@ -81,6 +78,7 @@
<string name="label_email">Correo electrónico</string>
<string name="unknown_status"></string>
<!--choice-->
<!--key flags-->
<!--sentences-->
<!--errors
no punctuation, all lowercase,

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certificar</string>
<string name="btn_decrypt">Descifrar</string>
<string name="btn_decrypt_verify">Descifrar y verificar</string>
<string name="btn_decrypt_verify_clipboard">Desde el portapapeles</string>
<string name="btn_select_encrypt_keys">Seleccionar destinatarios</string>
<string name="btn_encrypt_file">Cifrar archivo</string>
<string name="btn_save">Guardar</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Eliminar</string>
<string name="btn_no_date">Ninguno</string>
<string name="btn_okay">De acuerdo</string>
<string name="btn_change_passphrase">Cambiar la frase de contraseña</string>
<string name="btn_set_passphrase">Establecer frase de contraseña</string>
<string name="btn_change_passphrase">Cambiar nueva frase de contraseña</string>
<string name="btn_set_passphrase">Establecer nueva frase de contraseña</string>
<string name="btn_search">Buscar</string>
<string name="btn_export_to_server">Cargar al servidor de claves</string>
<string name="btn_next">Siguiente</string>
@ -73,7 +74,6 @@
<string name="menu_import_from_qr_code">Importar desde código QR</string>
<string name="menu_import">Importar</string>
<string name="menu_import_from_nfc">Importar desde NFC</string>
<string name="menu_export_keys">Exportar todas las claves</string>
<string name="menu_export_secret_keys">Exportar todas las claves secretas</string>
<string name="menu_export_key">Exportar hacia archivo</string>
<string name="menu_delete_key">Borrar clave</string>
@ -129,8 +129,6 @@
<string name="label_name">Nombre</string>
<string name="label_comment">Comentario</string>
<string name="label_email">Email</string>
<string name="label_sign_user_id">Firmar Id de usuario</string>
<string name="label_sign_email">Firmar correo</string>
<string name="label_send_key">Cargar clave al servidor de claves seleccionado después de la certificación</string>
<string name="label_fingerprint">Huella digital</string>
<string name="select_keys_button_default">Seleccionar</string>
@ -161,9 +159,6 @@
<string name="secret_key">Clave secreta:</string>
<!--choice-->
<string name="choice_none">Ninguna</string>
<string name="choice_sign_only">Solo firmar</string>
<string name="choice_encrypt_only">Solo cifrar</string>
<string name="choice_sign_and_encrypt">Firmar y cifrar</string>
<string name="choice_15secs">15 segs</string>
<string name="choice_1min">1 min</string>
<string name="choice_3mins">3 mins</string>
@ -183,21 +178,22 @@
<string name="warning">Advertencia</string>
<string name="error">Error</string>
<string name="error_message">Error: %s</string>
<!--key flags-->
<string name="flag_certify">Certificar</string>
<string name="flag_sign">Firmar</string>
<string name="flag_encrypt">Cifrar</string>
<string name="flag_authenticate">Autentificar</string>
<!--sentences-->
<string name="wrong_passphrase">Frase de contraseña incorrecta.</string>
<string name="using_clipboard_content">Usando el contenido del portapapeles.</string>
<string name="set_a_passphrase">Establece una frase de contraseña antes.</string>
<string name="no_filemanager_installed">No hay un gestor de archivos compatible instalado.</string>
<string name="passphrases_do_not_match">Las frases de contraseña no coinciden.</string>
<string name="passphrase_must_not_be_empty">Las frases de contraseña no pueden estar vacías.</string>
<string name="passphrase_for_symmetric_encryption">Cifrado simétrico.</string>
<string name="passphrase_for">Introducir la frase de contraseña para \'%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="no_file_selected">Selecciona un archivo antes.</string>
<string name="decryption_successful">Descifrado satisfactoriamente.</string>
<string name="encryption_successful">Cifrado satisfactoriamente.</string>
<string name="encryption_to_clipboard_successful">Cifrado satisfactoriamente al portapapeles.</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_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string>
@ -208,6 +204,7 @@
<string name="key_deletion_confirmation">¿Quieres realmente borrar la clave \'%s\'?\n¡No podrás deshacerlo!</string>
<string name="key_deletion_confirmation_multi">¿Quieres realmente borrar todas las claves seleccionadas?\n¡No podrás deshacerlo!</string>
<string name="secret_key_deletion_confirmation">¿Quieres realmente borrar la clave SECRETA \'%s\'?\n¡No podrás deshacerlo!</string>
<string name="ask_save_changed_key">Has hecho cambios en el almacén de claves, ¿quieres guardarlos?</string>
<string name="public_key_deletetion_confirmation">¿Quieres realmente borrar la clave PÚBLICA \'%s\'?\n¡No podrás deshacerlo!</string>
<string name="secret_key_delete_text">¿Borrar claves secretas?</string>
<string name="also_export_secret_keys">¿Exportar también las claves secretas?</string>
@ -285,6 +282,7 @@
<string name="error_nfc_needed">¡NFC no está disponible en tu dispositivo!</string>
<string name="error_nothing_import">¡Nada que importar!</string>
<string name="error_expiry_must_come_after_creation">la fecha de caducidad debe ser posterior a la fecha de creación</string>
<string name="error_save_first">Por favor, guarda el almacén de claves antes</string>
<string name="error_can_not_delete_contact">no puedes eliminar este contacto porque eres tú mismo.</string>
<string name="error_can_not_delete_contacts">no puedes eliminar los siguientes contactos porque son tú mismo:\n%s</string>
<string name="error_keyserver_insufficient_query">Consulta al servidor insuficiente</string>
@ -384,13 +382,16 @@
<string name="api_settings_hide_advanced">Ocultar la configuración avanzada</string>
<string name="api_settings_no_key">No se ha seleccionado ninguna clave</string>
<string name="api_settings_select_key">Seleccionar clave</string>
<string name="api_settings_create_key">Crear una nueva clave para esta cuenta</string>
<string name="api_settings_save">Guardar</string>
<string name="api_settings_cancel">Cancelar</string>
<string name="api_settings_revoke">Revocar acceso</string>
<string name="api_settings_delete_account">Borrar cuenta</string>
<string name="api_settings_package_name">Nombre de paquete</string>
<string name="api_settings_package_signature">SHA-256 de firma de paquete</string>
<string name="api_settings_accounts">Cuentas</string>
<string name="api_settings_accounts_empty">No hay cuentas asociadas a esta aplicación.</string>
<string name="api_create_account_text">La aplicación solicita la creación de una nueva cuenta. Por favor, selecciona una clave privada que ya exista o crea una nueva.\n¡Las aplicaciones tienen restringido el uso de claves a las que tú selecciones aquí!</string>
<string name="api_register_text">La aplicación mostrada solicita acceso a OpenKeychain.\n¿Permitir el acceso?\n\nAVISO: Si no sabes por qué aparece esta pantalla, ¡deniega el acceso! Puedes revocarlo después usando la pantalla \'Aplicaciones registradas\'.</string>
<string name="api_register_allow">Permitir el acceso</string>
<string name="api_register_disallow">Denegar el acceso</string>
@ -422,9 +423,6 @@
<string name="key_view_tab_main">Información</string>
<string name="key_view_tab_certs">Certificaciones</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Contactos</string>
<string name="nav_encrypt">Cifrar</string>
<string name="nav_decrypt">Descifrar</string>
<string name="nav_import">Importar claves</string>
<string name="nav_secret_keys">Mis claves</string>
<string name="nav_apps">Aplicaciones registradas</string>
@ -438,5 +436,4 @@
<string name="section_uids_to_sign">IDs de usuario para firmar</string>
<string name="progress_re_adding_certs">Nueva aplicación de certificados</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Escribe aquí el mensaje que quieras cifrar...</string>
</resources>

View File

@ -35,7 +35,6 @@
<string name="btn_save">Salvesta</string>
<string name="btn_do_not_save">Katkesta</string>
<string name="btn_delete">Kustuta</string>
<string name="btn_set_passphrase">Määra salasõne</string>
<string name="btn_search">Otsi</string>
<string name="btn_export_to_server">Saada võtmeserverisse</string>
<string name="btn_next">Järgmine</string>
@ -77,9 +76,6 @@
<string name="fingerprint">Sõrmejälg:</string>
<string name="secret_key">Salajane võti:</string>
<!--choice-->
<string name="choice_sign_only">Ainult allkirjastamine</string>
<string name="choice_encrypt_only">Ainult krüpteerimine</string>
<string name="choice_sign_and_encrypt">Allkirjastamine ja krüpteerimine</string>
<string name="choice_15secs">15 sekundit</string>
<string name="choice_1min">1 minut</string>
<string name="choice_3mins">3 minutit</string>
@ -98,11 +94,11 @@
<string name="warning">Hoiatus</string>
<string name="error">Viga</string>
<string name="error_message">Viga: %s</string>
<!--key flags-->
<!--sentences-->
<string name="wrong_passphrase">Vale salasõne</string>
<string name="set_a_passphrase">Määra enne salasõne.</string>
<string name="passphrases_do_not_match">Salasõned ei ühti.</string>
<string name="passphrase_must_not_be_empty">Tühi salasõne pole lubatud.</string>
<string name="passphrase_for_symmetric_encryption">Sümmeetriline krüpteering</string>
<!--errors
no punctuation, all lowercase,

View File

@ -7,6 +7,7 @@
<!--label-->
<string name="unknown_status"></string>
<!--choice-->
<!--key flags-->
<!--sentences-->
<!--errors
no punctuation, all lowercase,

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certifier</string>
<string name="btn_decrypt">Déchiffrer</string>
<string name="btn_decrypt_verify">Déchiffrer et vérifier</string>
<string name="btn_decrypt_verify_clipboard">À partir du presse-papiers</string>
<string name="btn_select_encrypt_keys">Choisir les destinataires</string>
<string name="btn_encrypt_file">Chiffrer le fichier</string>
<string name="btn_save">Enregistrer</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Supprimer</string>
<string name="btn_no_date">Aucune</string>
<string name="btn_okay">OK</string>
<string name="btn_change_passphrase">Changer la phrase de passe</string>
<string name="btn_set_passphrase">Définir la phrase de passe</string>
<string name="btn_change_passphrase">Changer la nouvelle phrase de passe</string>
<string name="btn_set_passphrase">Définir la nouvelle phrase de passe</string>
<string name="btn_search">Rechercher</string>
<string name="btn_export_to_server">Téléverser vers le serveur de clefs</string>
<string name="btn_next">Suivant</string>
@ -73,7 +74,6 @@
<string name="menu_import_from_qr_code">Importer depuis un code QR</string>
<string name="menu_import">Importer</string>
<string name="menu_import_from_nfc">Importer avec NFC</string>
<string name="menu_export_keys">Exporter toutes les clefs</string>
<string name="menu_export_secret_keys">Exporter toutes les clefs secrètes</string>
<string name="menu_export_key">Exporter vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string>
@ -129,8 +129,6 @@
<string name="label_name">Nom</string>
<string name="label_comment">Commentaire</string>
<string name="label_email">Courriel</string>
<string name="label_sign_user_id">Signer l\'ID utilisateur</string>
<string name="label_sign_email">Signer le courriel</string>
<string name="label_send_key">Téléverser la clef vers le serveur de clefs choisi après certification</string>
<string name="label_fingerprint">Empreinte</string>
<string name="select_keys_button_default">Choisir</string>
@ -161,9 +159,6 @@
<string name="secret_key">Clef secrète :</string>
<!--choice-->
<string name="choice_none">Aucune</string>
<string name="choice_sign_only">Signer seulement</string>
<string name="choice_encrypt_only">Chiffrer seulement</string>
<string name="choice_sign_and_encrypt">Signer et chiffrer</string>
<string name="choice_15secs">15 s</string>
<string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string>
@ -183,21 +178,22 @@
<string name="warning">Avertissement</string>
<string name="error">Erreur</string>
<string name="error_message">Erreur : %s</string>
<!--key flags-->
<string name="flag_certify">Certifier</string>
<string name="flag_sign">Signer</string>
<string name="flag_encrypt">Chiffrer</string>
<string name="flag_authenticate">Authentifier</string>
<!--sentences-->
<string name="wrong_passphrase">Phrase de passe erronée</string>
<string name="using_clipboard_content">Utiliser le contenu du presse-papiers.</string>
<string name="set_a_passphrase">Définir d\'abord une phrase de passe.</string>
<string name="no_filemanager_installed">Aucun gestionnaire de fichiers compatible installé.</string>
<string name="passphrases_do_not_match">Les phrases de passe ne correspondent pas.</string>
<string name="passphrase_must_not_be_empty">Les phrases de passe vides ne sont pas autorisées.</string>
<string name="passphrase_for_symmetric_encryption">Chriffrement symétrique.</string>
<string name="passphrase_for">Saisir une phrase de passe pour « %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="no_file_selected">Choisir d\'abord un fichier.</string>
<string name="decryption_successful">Déchiffré avec succès.</string>
<string name="encryption_successful">Chiffré avec succès.</string>
<string name="encryption_to_clipboard_successful">Chiffré vers le presse-papiers avec succès.</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_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string>
@ -208,6 +204,7 @@
<string name="key_deletion_confirmation">Voulez-vous vraiment supprimer la clef %s ?\nVous ne pourrez pas la restituer !</string>
<string name="key_deletion_confirmation_multi">Voulez-vous vraiment supprimer toutes les clefs choisies ?\nCeci est irréversible !</string>
<string name="secret_key_deletion_confirmation">Voulez-vous vraiment supprimer la clef SECRÈTE %s ?\nVous ne pourrez pas la restituer !</string>
<string name="ask_save_changed_key">Vous avez apporté des changements au trousseau, voulez-vous l\'enregistrer ?</string>
<string name="public_key_deletetion_confirmation">Voulez-vous vraiment supprimer la clef PUBLIQUE « %s » ?\nVous ne pourrez pas la restituer !</string>
<string name="secret_key_delete_text">Supprimer les clefs privées ?</string>
<string name="also_export_secret_keys">Exporter aussi les clefs secrètes?</string>
@ -285,6 +282,7 @@
<string name="error_nfc_needed">NFC n\'est pas disponible sur votre appareil !</string>
<string name="error_nothing_import">Rien à importer !</string>
<string name="error_expiry_must_come_after_creation">la date d\'expiration doit venir après la date de création</string>
<string name="error_save_first">veuillez d\'abord enregistrer le trousseau</string>
<string name="error_can_not_delete_contact">vous ne pouvez pas supprimer ce contact car c\'est le vôtre.</string>
<string name="error_can_not_delete_contacts">vous ne pouvez pas supprimer les contacts suivants car c\'est les vôtres.\n%s</string>
<string name="error_keyserver_insufficient_query">Requête serveur insuffisante</string>
@ -300,6 +298,7 @@
<item quantity="one">une partie du fichier chargé est un objet OpenPGP valide mais pas une clef OpenPGP</item>
<item quantity="other">certaines parties du fichier chargé sont des objets OpenPGP valides mais pas des clefs OpenPGP</item>
</plurals>
<string name="error_change_something_first">Vous devez apporter des changements au trousseau avant de pouvoir l\'enregistrer</string>
<!--progress dialogs, usually ending in '…'-->
<string name="progress_done">Terminé.</string>
<string name="progress_cancel">Annuler</string>
@ -384,13 +383,16 @@
<string name="api_settings_hide_advanced">Masquer les paramètres avancés</string>
<string name="api_settings_no_key">Aucune clef choisie</string>
<string name="api_settings_select_key">Choisir une clef</string>
<string name="api_settings_create_key">Créer une nouvelle clef pour ce compte</string>
<string name="api_settings_save">Enregistrer</string>
<string name="api_settings_cancel">Annuler</string>
<string name="api_settings_revoke">Révoquer l\'accès</string>
<string name="api_settings_delete_account">Supprimer le compte</string>
<string name="api_settings_package_name">Nom du paquet</string>
<string name="api_settings_package_signature">SHA-256 de la signature du paquet</string>
<string name="api_settings_accounts">Comptes</string>
<string name="api_settings_accounts_empty">Aucun compte n\'est attaché à cette application.</string>
<string name="api_create_account_text">L\'application demande la création d\'un nouveau compte. Veuillez choisir un clef privée existante ou en créer une.\nLes applications sont restreintes à l\'utilisation de clefs choisies ici.</string>
<string name="api_register_text">L\'application affichée demande l\'accès à OpenKeychain.\nPermettre l\'accès ?\n\nAvertissement : si vous ne savez pas pourquoi cet écran est apparu, refusez l\'accès ! Vous pourrez révoquer l\'accès plus tard en utilisant l\'écran « Applications enregistrées ».</string>
<string name="api_register_allow">Permettre l\'accès</string>
<string name="api_register_disallow">Enlever l\'accès</string>
@ -422,9 +424,6 @@
<string name="key_view_tab_main">Infos</string>
<string name="key_view_tab_certs">Certifications</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Contacts</string>
<string name="nav_encrypt">Chiffrer</string>
<string name="nav_decrypt">Déchiffrer</string>
<string name="nav_import">Importer les clefs</string>
<string name="nav_secret_keys">Mes clefs</string>
<string name="nav_apps">Applis enregistrées</string>
@ -438,5 +437,4 @@
<string name="section_uids_to_sign">ID utilisateur pour signer</string>
<string name="progress_re_adding_certs">Nouvel application des certificats</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Écrire le message à chiffrer ici...</string>
</resources>

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certifica</string>
<string name="btn_decrypt">Decodifica</string>
<string name="btn_decrypt_verify">Decodifica e Verifica</string>
<string name="btn_decrypt_verify_clipboard">Dagli Appunti</string>
<string name="btn_select_encrypt_keys">Seleziona Destinatari</string>
<string name="btn_encrypt_file">Codifica File</string>
<string name="btn_save">Salva</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Elimina</string>
<string name="btn_no_date">Nessuno</string>
<string name="btn_okay">Okay</string>
<string name="btn_change_passphrase">Cambia Frase Di Accesso</string>
<string name="btn_set_passphrase">Imposta Frase di Accesso</string>
<string name="btn_change_passphrase">Cambia Nuova Frase di Accesso</string>
<string name="btn_set_passphrase">Imposta Nuova Frase di Accesso</string>
<string name="btn_search">Cerca</string>
<string name="btn_export_to_server">Carica sul Server delle Chiavi</string>
<string name="btn_next">Prossimo</string>
@ -73,12 +74,11 @@
<string name="menu_import_from_qr_code">Importa da Codice QR</string>
<string name="menu_import">Importa</string>
<string name="menu_import_from_nfc">Importa tramite NFC</string>
<string name="menu_export_keys">Esporta tutte le chiavi</string>
<string name="menu_export_secret_keys">Esporta tutte le chiavi segrete</string>
<string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
<string name="menu_create_key">Crea chiave</string>
<string name="menu_create_key_expert">Crea chiave (esperto)</string>
<string name="menu_create_key_expert">Crea chiave (avanzato)</string>
<string name="menu_search">Cerca</string>
<string name="menu_import_from_key_server">Server delle Chiavi</string>
<string name="menu_key_server">Server delle Chiavi...</string>
@ -104,7 +104,7 @@
<string name="label_file">File</string>
<string name="label_no_passphrase">Nessuna Frase di Accesso</string>
<string name="label_passphrase">Frase di Accesso</string>
<string name="label_passphrase_again">Ancora</string>
<string name="label_passphrase_again">Di nuovo</string>
<string name="label_algorithm">Algortimo</string>
<string name="label_ascii_armor">Armatura ASCII</string>
<string name="label_select_public_keys">Destinatari</string>
@ -129,8 +129,6 @@
<string name="label_name">Nome</string>
<string name="label_comment">Commento</string>
<string name="label_email">Email</string>
<string name="label_sign_user_id">Firma ID Utente</string>
<string name="label_sign_email">Firma email</string>
<string name="label_send_key">Carica chiave nel server delle chiavi selezionati dopo la certificazione</string>
<string name="label_fingerprint">Impronta</string>
<string name="select_keys_button_default">Seleziona</string>
@ -161,9 +159,6 @@
<string name="secret_key">Chiave Privata:</string>
<!--choice-->
<string name="choice_none">Nessuno</string>
<string name="choice_sign_only">Firma soltanto</string>
<string name="choice_encrypt_only">Codifica soltanto</string>
<string name="choice_sign_and_encrypt">Firma e Codifica</string>
<string name="choice_15secs">15 sec</string>
<string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string>
@ -183,21 +178,22 @@
<string name="warning">Attenzione</string>
<string name="error">Errore</string>
<string name="error_message">Errore: %s</string>
<!--key flags-->
<string name="flag_certify">Certifica</string>
<string name="flag_sign">Firma</string>
<string name="flag_encrypt">Codifica</string>
<string name="flag_authenticate">Convalida</string>
<!--sentences-->
<string name="wrong_passphrase">Frase di Accesso errata</string>
<string name="using_clipboard_content">Utilizzo il contenuto degli appunti.</string>
<string name="set_a_passphrase">Imposta prima una frase di accesso.</string>
<string name="no_filemanager_installed">Nessun gestore file compatibile installato.</string>
<string name="passphrases_do_not_match">Le frasi di accesso non corrispondono.</string>
<string name="passphrase_must_not_be_empty">Frasi di accesso vuote non consentite.</string>
<string name="passphrase_for_symmetric_encryption">Codifica Simmetrica.</string>
<string name="passphrase_for">Inserisci la frase di accesso per \'%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="no_file_selected">Seleziona un file prima.</string>
<string name="decryption_successful">Decodificato correttamente.</string>
<string name="encryption_successful">Codificato correttamente.</string>
<string name="encryption_to_clipboard_successful">Codificato correttamente negli appunti.</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_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string>
@ -208,6 +204,7 @@
<string name="key_deletion_confirmation">Vuoi veramente eliminare la chiave \'%s\'?\nNon potrai annullare!</string>
<string name="key_deletion_confirmation_multi">Vuoi veramente eliminare le chiavi selezionate?\nNon potrai annullare!</string>
<string name="secret_key_deletion_confirmation">Vuoi veramente eliminare la chiave PRIVATA \'%s\'?\nNon potrai annullare!</string>
<string name="ask_save_changed_key">Hai apportato modifiche al tuo portachiavi, vuoi salvarlo?</string>
<string name="public_key_deletetion_confirmation">Vuoi veramente eliminare la chiave PUBBLICA \'%s\'?\nNon potrai annullare!</string>
<string name="secret_key_delete_text">Eliminare le Chiavi Segrete?</string>
<string name="also_export_secret_keys">Esportare anche le chiavi segrete?</string>
@ -285,6 +282,7 @@
<string name="error_nfc_needed">NFC non disponibile nel tuo dispositivo!</string>
<string name="error_nothing_import">Niente da importare!</string>
<string name="error_expiry_must_come_after_creation">La data di scadenza deve essere postuma quella di creazione</string>
<string name="error_save_first">si prega di salvare il portachiavi primo</string>
<string name="error_can_not_delete_contact">Non è possibile eliminare questo contatto, perché è il proprio.</string>
<string name="error_can_not_delete_contacts">Non è possibile eliminare i seguenti contatti perché sono i propri:\n%s</string>
<string name="error_keyserver_insufficient_query">Query di server insufficiente</string>
@ -377,16 +375,23 @@
<string name="intent_send_encrypt">Codifica con OpenKeychain</string>
<string name="intent_send_decrypt">Decodifica con OpenKeychain</string>
<!--Remote API-->
<string name="api_no_apps">Nessuna app registrata!\n\nApp di terza parti possono richiedere accesso a OpenKeychain. Dopo aver concesso l\'accesso, saranno elencate qui.</string>
<string name="api_no_apps">Nessuna app registrata!\n\nApp di terze parti possono richiedere l\'accesso a OpenKeychain. Dopo aver concesso l\'accesso, le app saranno elencate qui.</string>
<string name="api_settings_show_info">Mostra informazioni dettagliate</string>
<string name="api_settings_hide_info">Nascondi informazioni dettagliate</string>
<string name="api_settings_show_advanced">Mostra impostazioni avanzate</string>
<string name="api_settings_hide_advanced">Nascondi impostazioni avanzate</string>
<string name="api_settings_no_key">Nessuna chiave selezionata</string>
<string name="api_settings_select_key">Seleziona chiave</string>
<string name="api_settings_create_key">Crea una nuova chiave per questo account</string>
<string name="api_settings_save">Salva</string>
<string name="api_settings_cancel">Annulla</string>
<string name="api_settings_revoke">Revoca accesso</string>
<string name="api_settings_delete_account">Cancella account</string>
<string name="api_settings_package_name">Nome Pacchetto</string>
<string name="api_settings_package_signature">SHA-256 della Firma del Pacchetto</string>
<string name="api_settings_accounts">Account</string>
<string name="api_settings_accounts_empty">Nessun account collegato a questa applicazione</string>
<string name="api_create_account_text">L\'applicazione richiede la creazione di un nuovo account. Si prega di selezionare una chiave privata esistente o crearne una nuova.\nLe applicazioni sono limitate all\'utilizzo delle chiavi selezionate qui!</string>
<string name="api_register_text">Le app visualizzate hanno richiesto l\'accesso a OpenKeychain.\nPermetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' apparsa, nega l\'accesso! Puoi revocare l\'accesso dopo, usando la schermata \'App Registrate\'.</string>
<string name="api_register_allow">Permetti accesso</string>
<string name="api_register_disallow">Nega accesso</string>
@ -418,10 +423,7 @@
<string name="key_view_tab_main">Info</string>
<string name="key_view_tab_certs">Certificazioni</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Contatti</string>
<string name="nav_encrypt">Codifica</string>
<string name="nav_decrypt">Decodifica</string>
<string name="nav_import">Importare Chiavi</string>
<string name="nav_import">Importa Chiavi</string>
<string name="nav_secret_keys">Le Mie Chiavi</string>
<string name="nav_apps">App Registrate</string>
<string name="drawer_open">Apri drawer di navigazione</string>
@ -434,5 +436,4 @@
<string name="section_uids_to_sign">ID Utente da firmare</string>
<string name="progress_re_adding_certs">Riapplicazione certificati</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Scrivi qui il messaggio da codificare...</string>
</resources>

View File

@ -48,6 +48,7 @@
<string name="btn_certify">検証</string>
<string name="btn_decrypt">復号化</string>
<string name="btn_decrypt_verify">復号化と検証</string>
<string name="btn_decrypt_verify_clipboard">クリップボードから</string>
<string name="btn_select_encrypt_keys">受信者の選択</string>
<string name="btn_encrypt_file">ファイル暗号化</string>
<string name="btn_save">保存</string>
@ -55,8 +56,8 @@
<string name="btn_delete">削除</string>
<string name="btn_no_date">無し</string>
<string name="btn_okay">OK</string>
<string name="btn_change_passphrase">パスフレーズの変更</string>
<string name="btn_set_passphrase">パスフレーズの設定</string>
<string name="btn_change_passphrase">新しいパスフレーズに変更</string>
<string name="btn_set_passphrase">新しいパスフレーズを設定</string>
<string name="btn_search">検索</string>
<string name="btn_export_to_server">鍵サーバへアップロード</string>
<string name="btn_next"></string>
@ -73,7 +74,6 @@
<string name="menu_import_from_qr_code">QRコードからインポート</string>
<string name="menu_import">インポート</string>
<string name="menu_import_from_nfc">NFCからインポート</string>
<string name="menu_export_keys">すべての鍵のエクスポート</string>
<string name="menu_export_secret_keys">すべての秘密鍵のエクスポート</string>
<string name="menu_export_key">ファイルへのエクスポート</string>
<string name="menu_delete_key">鍵の削除</string>
@ -129,8 +129,6 @@
<string name="label_name">名前</string>
<string name="label_comment">コメント</string>
<string name="label_email">Eメールアドレス</string>
<string name="label_sign_user_id">署名ユーザーID</string>
<string name="label_sign_email">メールを署名</string>
<string name="label_send_key">証明後選択した鍵サーバに鍵をアップロード</string>
<string name="label_fingerprint">指紋</string>
<string name="select_keys_button_default">選択</string>
@ -158,9 +156,6 @@
<string name="secret_key">秘密鍵:</string>
<!--choice-->
<string name="choice_none">無し</string>
<string name="choice_sign_only">署名のみ</string>
<string name="choice_encrypt_only">暗号化のみ</string>
<string name="choice_sign_and_encrypt">署名と暗号化</string>
<string name="choice_15secs">15秒</string>
<string name="choice_1min">1分</string>
<string name="choice_3mins">3分</string>
@ -180,21 +175,22 @@
<string name="warning">注意</string>
<string name="error">エラー</string>
<string name="error_message">エラー: %s</string>
<!--key flags-->
<string name="flag_certify">検証</string>
<string name="flag_sign">署名</string>
<string name="flag_encrypt">暗号化</string>
<string name="flag_authenticate">証明</string>
<!--sentences-->
<string name="wrong_passphrase">良くないパスフレーズ</string>
<string name="using_clipboard_content">クリップボードの内容を使う。</string>
<string name="set_a_passphrase">最初にパスフレーズを設定してください。</string>
<string name="no_filemanager_installed">互換性のないファイルマネージャがインストールされています。</string>
<string name="passphrases_do_not_match">パスフレーズが一致しません。</string>
<string name="passphrase_must_not_be_empty">空のパスフレーズは受け付けません。</string>
<string name="passphrase_for_symmetric_encryption">対称暗号。</string>
<string name="passphrase_for">\'%s\' にパスフレーズを入れてください。</string>
<string name="file_delete_confirmation">%s を削除してもかまいませんか?</string>
<string name="file_delete_successful">削除に成功しました。</string>
<string name="no_file_selected">最初にファイルを選択してください。</string>
<string name="decryption_successful">復号化に成功しました。</string>
<string name="encryption_successful">暗号化に成功しました。</string>
<string name="encryption_to_clipboard_successful">クリップボードの中身の暗号化に成功しました。</string>
<string name="enter_passphrase_twice">もう一度パスフレーズを入れてください。</string>
<string name="select_encryption_key">少なくとも1つの暗号化鍵を選択して下さい。</string>
<string name="select_encryption_or_signature_key">少なくとも1つの暗号化鍵か署名鍵を選択して下さい。</string>
@ -205,6 +201,7 @@
<string name="key_deletion_confirmation">鍵\'%s\'を本当に削除してもよいですか?\nこれは元に戻せません!</string>
<string name="key_deletion_confirmation_multi">選択したすべての鍵を本当に削除してよいですか?\nこれは元に戻せません。</string>
<string name="secret_key_deletion_confirmation">秘密鍵\'%s\'を本当に削除してもよいですか?\nこれは元に戻せません!</string>
<string name="ask_save_changed_key">あなたは鍵輪に変更を加えました、これを保存しますか?</string>
<string name="public_key_deletetion_confirmation">公開鍵\'%s\'を本当に削除してもよいですか?\nこれは元に戻せません!</string>
<string name="secret_key_delete_text">秘密鍵を削除しますか?</string>
<string name="also_export_secret_keys">秘密鍵もエクスポートしますか?</string>
@ -276,6 +273,7 @@
<string name="error_nfc_needed">あなたのデバイスにはNFCが存在しません!</string>
<string name="error_nothing_import">インポートするものがありません!</string>
<string name="error_expiry_must_come_after_creation">期限日時は生成日時より後である必要があります</string>
<string name="error_save_first">まず鍵輪を保存してください</string>
<string name="error_can_not_delete_contact">この連絡先はあなたなので削除できません。</string>
<string name="error_can_not_delete_contacts">この連絡先はあなたなので削除できません。:\n%s</string>
<string name="error_keyserver_insufficient_query">サーバへのクエリーが不足しています</string>
@ -289,6 +287,7 @@
<plurals name="error_import_non_pgp_part">
<item quantity="other">読み込んだファイルのOpenPGPオブジェクト部分は正しいですが、OpenPGPの鍵ではありません</item>
</plurals>
<string name="error_change_something_first">あなたは鍵輪を保存する前に変更を加えなくてはなりません</string>
<!--progress dialogs, usually ending in '…'-->
<string name="progress_done">完了。</string>
<string name="progress_cancel">キャンセル</string>
@ -364,15 +363,22 @@
<string name="intent_send_decrypt">OpenKeychainで復号化</string>
<!--Remote API-->
<string name="api_no_apps">登録されていないアプリケーション!\n\nサードパーティアプリケーションはOpenKeychainにアクセスを要求できます。アクセスを与えた後、それらはここにリストされます。</string>
<string name="api_settings_show_info">詳細情報を表示</string>
<string name="api_settings_hide_info">詳細情報を非表示</string>
<string name="api_settings_show_advanced">拡張設定を表示</string>
<string name="api_settings_hide_advanced">拡張設定を隠す</string>
<string name="api_settings_no_key">鍵が選択されていない</string>
<string name="api_settings_select_key">鍵の選択</string>
<string name="api_settings_create_key">このアカウントで新しい鍵を生成</string>
<string name="api_settings_save">保存</string>
<string name="api_settings_cancel">キャンセル</string>
<string name="api_settings_revoke">破棄されたアクセス</string>
<string name="api_settings_delete_account">アカウントを削除</string>
<string name="api_settings_package_name">パッケージ名</string>
<string name="api_settings_package_signature">パッケージの署名 SHA-256</string>
<string name="api_settings_accounts">アカウント</string>
<string name="api_settings_accounts_empty">このアプリケーションに接続されてるアカウントはありません。</string>
<string name="api_create_account_text">このアプリケーションは新しいアカウントの生成を要求しています。すでにある秘密鍵を選択するか、新しく生成してください。\nここであなたが選択する鍵の使い道についてアプリケーションには制約があります!</string>
<string name="api_register_text">表示されているアプリケーションはOpenKeychainへのアクセスを要求しています。\nアクセスを許可しますか?\n\n注意: もしなぜスクリーンに表れたかわからないなら、アクセスを許可しないでください! あなたは\'登録済みアプリケーション\'スクリーンを使って、以降のアクセスを破棄するこもできます。</string>
<string name="api_register_allow">許可されたアクセス</string>
<string name="api_register_disallow">許可されないアクセス</string>
@ -403,9 +409,6 @@
<string name="key_view_tab_main">情報</string>
<string name="key_view_tab_certs">証明</string>
<!--Navigation Drawer-->
<string name="nav_contacts">連絡先</string>
<string name="nav_encrypt">暗号化</string>
<string name="nav_decrypt">復号化</string>
<string name="nav_import">鍵のインポート</string>
<string name="nav_secret_keys">自分の鍵</string>
<string name="nav_apps">登録済みのアプリ</string>
@ -419,5 +422,4 @@
<string name="section_uids_to_sign">署名に使うユーザーID</string>
<string name="progress_re_adding_certs">検証を再適用する</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">ここに書いたメッセージを暗号化..</string>
</resources>

View File

@ -36,8 +36,6 @@
<string name="btn_delete">Verwijderen</string>
<string name="btn_no_date">Geen</string>
<string name="btn_okay">OK</string>
<string name="btn_change_passphrase">Wachtwoord wijzigen</string>
<string name="btn_set_passphrase">Wachtwoord instellen</string>
<string name="btn_search">Zoeken</string>
<string name="btn_next">Volgende</string>
<string name="btn_back">Terug</string>
@ -46,7 +44,6 @@
<string name="menu_import_from_file">Importeren uit bestand</string>
<string name="menu_import_from_qr_code">Importeren met QR-code</string>
<string name="menu_import_from_nfc">Importeren met NFC</string>
<string name="menu_export_keys">Alle sleutels exporteren</string>
<string name="menu_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string>
<string name="menu_create_key">Sleutel aanmaken</string>
@ -91,9 +88,6 @@
<string name="secret_key">Privésleutel:</string>
<!--choice-->
<string name="choice_none">Geen</string>
<string name="choice_sign_only">Alleen ondertekenen</string>
<string name="choice_encrypt_only">Alleen versleutelen</string>
<string name="choice_sign_and_encrypt">Ondertekenen en versleutelen</string>
<string name="choice_15secs">15 sec.</string>
<string name="choice_1min">1 min.</string>
<string name="choice_3mins">3 min.</string>
@ -112,21 +106,18 @@
<string name="warning">Waarschuwing</string>
<string name="error">Fout</string>
<string name="error_message">Fout: %s</string>
<!--key flags-->
<!--sentences-->
<string name="wrong_passphrase">Wachtwoord verkeerd.</string>
<string name="using_clipboard_content">Gebruikmaken van klembordinhoud.</string>
<string name="set_a_passphrase">Stel eerst een wachtwoord in.</string>
<string name="no_filemanager_installed">Geen compatibele bestandsbeheerder geïnstalleerd.</string>
<string name="passphrases_do_not_match">De wachtwoorden komen niet overeen.</string>
<string name="passphrase_must_not_be_empty">Lege wachtwoorden zijn niet toegestaand.</string>
<string name="passphrase_for_symmetric_encryption">Symmetrische versleuteling.</string>
<string name="passphrase_for">Voer het wachtwoord in voor \'%s\'</string>
<string name="file_delete_confirmation">Weer u zeker dat u het volgende wilt verwijderen:\n%s?</string>
<string name="file_delete_successful">Succesvol verwijderd.</string>
<string name="no_file_selected">Selecteer eerst een bestand.</string>
<string name="decryption_successful">Succesvol ontsleuteld.</string>
<string name="encryption_successful">Succesvol versleuteld.</string>
<string name="encryption_to_clipboard_successful">Succesvol versleuteld naar klembord.</string>
<string name="enter_passphrase_twice">Voer het wachtwoord tweemaal in.</string>
<string name="select_encryption_key">Selecteer ten minste één versleutelingssleutel.</string>
<string name="select_encryption_or_signature_key">Selecter ten minste één versleutelings-/ondertekeningssleutel.</string>

View File

@ -55,8 +55,6 @@
<string name="btn_delete">Usuń</string>
<string name="btn_no_date">Żaden</string>
<string name="btn_okay">Ok</string>
<string name="btn_change_passphrase">Zmień hasło</string>
<string name="btn_set_passphrase">Ustaw hasło</string>
<string name="btn_search">Wyszukaj</string>
<string name="btn_export_to_server">Wyślij do serwera kluczy</string>
<string name="btn_next">Dalej</string>
@ -73,8 +71,7 @@
<string name="menu_import_from_qr_code">Zaimportuj z kodu QR</string>
<string name="menu_import">Import</string>
<string name="menu_import_from_nfc">Zaimportuj przy użyciu NFC</string>
<string name="menu_export_keys">Eksportuj wszystkie klucze</string>
<string name="menu_export_secret_keys">Eksportuj wszystkie klucze prywatne</string>
<string name="menu_export_secret_keys">Eksportuj wszystkie prywatne klucze</string>
<string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string>
<string name="menu_create_key">Stwórz klucz</string>
@ -129,8 +126,6 @@
<string name="label_name">Imię</string>
<string name="label_comment">Komentarz</string>
<string name="label_email">Adres email</string>
<string name="label_sign_user_id">Identyfikator użytkownika podpisu (sign user id)</string>
<string name="label_sign_email">Podpisz e-mail</string>
<string name="label_send_key">Wyślij klucz do serwera kluczy po certyfikacji</string>
<string name="label_fingerprint">Odcisk</string>
<string name="select_keys_button_default">Wybierz</string>
@ -163,10 +158,7 @@
<string name="fingerprint">Odcisk:</string>
<string name="secret_key">Klucz prywatny:</string>
<!--choice-->
<string name="choice_none">Żaden</string>
<string name="choice_sign_only">Tylko podpisz</string>
<string name="choice_encrypt_only">Tylko zaszyfruj</string>
<string name="choice_sign_and_encrypt">Podpisz i zaszyfruj</string>
<string name="choice_none">Brak</string>
<string name="choice_15secs">15 sekund</string>
<string name="choice_1min">1 minuta</string>
<string name="choice_3mins">3 minuty</string>
@ -186,21 +178,18 @@
<string name="warning">Ostrzeżenie</string>
<string name="error">Błąd</string>
<string name="error_message">Błąd: %s</string>
<!--key flags-->
<!--sentences-->
<string name="wrong_passphrase">Nieprawidłowe hasło.</string>
<string name="using_clipboard_content">Użycie zawartości schowka.</string>
<string name="set_a_passphrase">Najpierw ustaw hasło.</string>
<string name="no_filemanager_installed">Nie zainstalowano żadnego kompatybilnego menadżera plików.</string>
<string name="passphrases_do_not_match">Hasła nie pasują do siebie</string>
<string name="passphrase_must_not_be_empty">Puste hasła nie są dozwolone.</string>
<string name="passphrase_for_symmetric_encryption">Szyfrowanie symetryczne.</string>
<string name="passphrase_for">Podaj hasło dla \'%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="no_file_selected">Najpierw wskaż plik.</string>
<string name="decryption_successful">Odszyfrowano pomyślnie.</string>
<string name="encryption_successful">Zaszyfrowano pomyślnie.</string>
<string name="encryption_to_clipboard_successful">Pomyślnie zaszyfrowano do schowka.</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_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string>
@ -398,13 +387,16 @@
<string name="api_settings_hide_advanced">Ukryj zaawansowane ustawienia</string>
<string name="api_settings_no_key">Nie wybrano klucza</string>
<string name="api_settings_select_key">Wybierz klucz</string>
<string name="api_settings_create_key">Utwórz nowy klucz dla tego konta</string>
<string name="api_settings_save">Zapisz</string>
<string name="api_settings_cancel">Anuluj</string>
<string name="api_settings_revoke">Odwołaj dostęp</string>
<string name="api_settings_delete_account">Usuń konto</string>
<string name="api_settings_package_name">Nazwa paczki</string>
<string name="api_settings_package_signature">Skrót SHA-256 podpisu paczki</string>
<string name="api_settings_accounts">Konta</string>
<string name="api_settings_accounts_empty">Nie przypisano żadnych kont do tej aplikacji</string>
<string name="api_create_account_text">Aplikacja prosi o zgodę na utworzenie nowego konta. Wskaż istniejący klucz prywatny lub wygeneruj nowy.\nAplikacje mogą używać wyłącznie klucze które tutaj wskażesz!</string>
<string name="api_register_text">Wyświetlona aplikacja prosi o dostęp do OpenKeychain.\nZezwolić?\n\nOSTRZEZENIE: Jeżeli nie wiesz, czemu wyświetlił się ten komunikat, nie zezwalaj na dostęp! Możesz to również zrobić później, korzystając z ekranu \'Zarejestrowane aplikacje\'.</string>
<string name="api_register_allow">Zezwól na dostęp</string>
<string name="api_register_disallow">Odmów dostępu</string>
@ -437,10 +429,7 @@
<string name="key_view_tab_main">Informacje</string>
<string name="key_view_tab_certs">Certyfikaty</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Kontakty</string>
<string name="nav_encrypt">Zaszyfruj</string>
<string name="nav_decrypt">Deszyfruj</string>
<string name="nav_import">importuj klucze</string>
<string name="nav_import">Importuj klucze</string>
<string name="nav_secret_keys">Moje klucze</string>
<string name="nav_apps">Zarejestrowane aplikacje</string>
<string name="drawer_open">Otwórz panel nawigacji</string>
@ -453,5 +442,4 @@
<string name="section_uids_to_sign">Identyfikator użytkownika do podpisu</string>
<string name="progress_re_adding_certs">Ponowne stosowanie certyfikatów</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Wpisz tutaj wiadomość do zaszyfrowania...</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More