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; public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(icicle); super.onCreate(savedInstanceState);
setContentView(R.layout.openpgp_provider); setContentView(R.layout.openpgp_provider);
mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message); mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message);
@ -171,7 +171,7 @@ public class OpenPgpProviderActivity extends Activity {
@Override @Override
public void onReturn(Intent result) { 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: { case OpenPgpApi.RESULT_CODE_SUCCESS: {
try { try {
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length 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()); data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false); InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN)); 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()); data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false); InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT)); 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()); data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(false); InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT)); 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()); data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString());
InputStream is = getInputstream(true); InputStream is = getInputstream(true);
final ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.executeApiAsync(data, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY)); 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 class Path {
public static final String APP_DIR = Environment.getExternalStorageDirectory() 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_SEC = APP_DIR + "/secexport.asc";
public static final String APP_DIR_FILE_PUB = APP_DIR + "/pubexport.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 class Pref {
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm"; public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm";
public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm"; 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_MESSAGE_COMPRESSION = "defaultMessageCompression";
public static final String DEFAULT_FILE_COMPRESSION = "defaultFileCompression"; 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 LANGUAGE = "language";
public static final String FORCE_V3_SIGNATURES = "forceV3Signatures"; public static final String FORCE_V3_SIGNATURES = "forceV3Signatures";
public static final String KEY_SERVERS = "keyServers"; 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 DECRYPT = DecryptActivity.class;
public static final Class IMPORT_KEYS = ImportKeysActivity.class; public static final Class IMPORT_KEYS = ImportKeysActivity.class;
public static final Class REGISTERED_APPS_LIST = AppsListActivity.class; public static final Class REGISTERED_APPS_LIST = AppsListActivity.class;
public static final Class[] ARRAY = new Class[]{KEY_LIST, ENCRYPT, DECRYPT, public static final Class[] ARRAY = new Class[]{
IMPORT_KEYS, REGISTERED_APPS_LIST}; KEY_LIST,
ENCRYPT,
DECRYPT,
IMPORT_KEYS,
REGISTERED_APPS_LIST
};
} }
} }

View File

@ -17,16 +17,17 @@
package org.sufficientlysecure.keychain; package org.sufficientlysecure.keychain;
import java.io.File; import android.app.Application;
import java.security.Provider; import android.os.Environment;
import java.security.Security;
import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.PRNGFixes; import org.sufficientlysecure.keychain.util.PRNGFixes;
import android.app.Application; import java.io.File;
import android.os.Environment; import java.security.Provider;
import java.security.Security;
public class KeychainApplication extends Application { public class KeychainApplication extends Application {
@ -40,14 +41,14 @@ public class KeychainApplication extends Application {
/* /*
* Sets Bouncy (Spongy) Castle as preferred security provider * Sets Bouncy (Spongy) Castle as preferred security provider
* *
* insertProviderAt() position starts from 1 * insertProviderAt() position starts from 1
*/ */
Security.insertProviderAt(new BouncyCastleProvider(), 1); Security.insertProviderAt(new BouncyCastleProvider(), 1);
/* /*
* apply RNG fixes * apply RNG fixes
* *
* among other things, executes Security.insertProviderAt(new * among other things, executes Security.insertProviderAt(new
* LinuxPRNGSecureRandomProvider(), 1) for Android <= SDK 17 * LinuxPRNGSecureRandomProvider(), 1) for Android <= SDK 17
*/ */

View File

@ -17,20 +17,20 @@
package org.sufficientlysecure.keychain.compatibility; package org.sufficientlysecure.keychain.compatibility;
import java.lang.reflect.Method;
import android.content.Context; import android.content.Context;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.lang.reflect.Method;
public class ClipboardReflection { public class ClipboardReflection {
private static final String clipboardLabel = "Keychain"; private static final String clipboardLabel = "Keychain";
/** /**
* Wrapper around ClipboardManager based on Android version using Reflection API * Wrapper around ClipboardManager based on Android version using Reflection API
* *
* @param context * @param context
* @param text * @param text
*/ */
@ -57,7 +57,7 @@ public class ClipboardReflection {
/** /**
* Wrapper around ClipboardManager based on Android version using Reflection API * Wrapper around ClipboardManager based on Android version using Reflection API
* *
* @param context * @param context
*/ */
public static CharSequence getClipboardText(Context context) { public static CharSequence getClipboardText(Context context) {

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org> * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -30,7 +30,7 @@ import java.util.Vector;
* Singleton Implementation of a Preference Helper * Singleton Implementation of a Preference Helper
*/ */
public class Preferences { public class Preferences {
private static Preferences mPreferences; private static Preferences sPreferences;
private SharedPreferences mSharedPreferences; private SharedPreferences mSharedPreferences;
public static synchronized Preferences getPreferences(Context context) { public static synchronized Preferences getPreferences(Context context) {
@ -38,10 +38,10 @@ public class Preferences {
} }
public static synchronized Preferences getPreferences(Context context, boolean forceNew) { public static synchronized Preferences getPreferences(Context context, boolean forceNew) {
if (mPreferences == null || forceNew) { if (sPreferences == null || forceNew) {
mPreferences = new Preferences(context); sPreferences = new Preferences(context);
} }
return mPreferences; return sPreferences;
} }
private Preferences(Context context) { private Preferences(Context context) {
@ -58,8 +58,8 @@ public class Preferences {
editor.commit(); editor.commit();
} }
public long getPassPhraseCacheTtl() { public long getPassphraseCacheTtl() {
int ttl = mSharedPreferences.getInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, 180); 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 // fix the value if it was set to "never" in previous versions, which currently is not
// supported // supported
if (ttl == 0) { if (ttl == 0) {
@ -68,9 +68,9 @@ public class Preferences {
return (long) ttl; return (long) ttl;
} }
public void setPassPhraseCacheTtl(int value) { public void setPassphraseCacheTtl(int value) {
SharedPreferences.Editor editor = mSharedPreferences.edit(); SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, value); editor.putInt(Constants.Pref.PASSPHRASE_CACHE_TTL, value);
editor.commit(); editor.commit();
} }
@ -118,13 +118,13 @@ public class Preferences {
editor.commit(); editor.commit();
} }
public boolean getDefaultAsciiArmour() { public boolean getDefaultAsciiArmor() {
return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, false); return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, false);
} }
public void setDefaultAsciiArmour(boolean value) { public void setDefaultAsciiArmor(boolean value) {
SharedPreferences.Editor editor = mSharedPreferences.edit(); SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, value); editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, value);
editor.commit(); editor.commit();
} }

View File

@ -65,14 +65,16 @@ public class PgpConversionHelper {
try { try {
while ((obj = factory.nextObject()) != null) { while ((obj = factory.nextObject()) != null) {
PGPSecretKey secKey = null; PGPSecretKey secKey = null;
if(obj instanceof PGPSecretKey) { if (obj instanceof PGPSecretKey) {
if ((secKey = (PGPSecretKey)obj ) == null) { secKey = (PGPSecretKey) obj;
if (secKey == null) {
Log.e(Constants.TAG, "No keys given!"); Log.e(Constants.TAG, "No keys given!");
} }
keys.add(secKey); 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; PGPSecretKeyRing keyRing = null;
if ((keyRing = (PGPSecretKeyRing)obj) == null) { keyRing = (PGPSecretKeyRing) obj;
if (keyRing == null) {
Log.e(Constants.TAG, "No keys given!"); Log.e(Constants.TAG, "No keys given!");
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

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

View File

@ -21,7 +21,13 @@ import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException; 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.Constants;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@ -45,9 +51,9 @@ public class PgpHelper {
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
public static final Pattern PGP_CLEARTEXT_SIGNATURE = Pattern public static final Pattern PGP_CLEARTEXT_SIGNATURE = Pattern
.compile( .compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----" +
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", "BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
Pattern.DOTALL); Pattern.DOTALL);
public static final Pattern PGP_PUBLIC_KEY = Pattern.compile( public static final Pattern PGP_PUBLIC_KEY = Pattern.compile(
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*", ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",

View File

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

View File

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

View File

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

View File

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

View File

@ -22,14 +22,14 @@ import android.content.Context;
public class PgpGeneralMsgIdException extends Exception { public class PgpGeneralMsgIdException extends Exception {
static final long serialVersionUID = 0xf812773343L; static final long serialVersionUID = 0xf812773343L;
private final int msgId; private final int mMessageId;
public PgpGeneralMsgIdException(int msgId) { public PgpGeneralMsgIdException(int messageId) {
super("msg[" + msgId + "]"); super("msg[" + messageId + "]");
this.msgId = msgId; mMessageId = messageId;
} }
public PgpGeneralException getContextualized(Context context) { 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.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; 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.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;

View File

@ -17,7 +17,11 @@
package org.sufficientlysecure.keychain.provider; 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.Cursor;
import android.database.DatabaseUtils; import android.database.DatabaseUtils;
import android.net.Uri; import android.net.Uri;
@ -48,6 +52,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class ProviderHelper { public class ProviderHelper {
@ -628,10 +634,10 @@ public class ProviderHelper {
return settings; return settings;
} }
public static AccountSettings getApiAccountSettings(Context context, Uri uri) { public static AccountSettings getApiAccountSettings(Context context, Uri accountUri) {
AccountSettings settings = null; 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()) { if (cur != null && cur.moveToFirst()) {
settings = new AccountSettings(); settings = new AccountSettings();
@ -650,6 +656,20 @@ public class ProviderHelper {
return settings; 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) { public static byte[] getApiAppSignature(Context context, String packageName) {
Uri queryUri = ApiApps.buildByPackageNameUri(packageName); Uri queryUri = ApiApps.buildByPackageNameUri(packageName);

View File

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

View File

@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.util.Log;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set;
public class OpenPgpService extends RemoteService { public class OpenPgpService extends RemoteService {
@ -187,7 +188,8 @@ public class OpenPgpService extends RemoteService {
} }
private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input, private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AccountSettings accSettings, boolean sign) { ParcelFileDescriptor output, AccountSettings accSettings,
boolean sign) {
try { try {
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); 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, private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AccountSettings accSettings) { ParcelFileDescriptor output, Set<Long> allowedKeyIds) {
try { try {
// Get Input- and OutputStream from ParcelFileDescriptor // Get Input- and OutputStream from ParcelFileDescriptor
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
@ -291,7 +293,8 @@ public class OpenPgpService extends RemoteService {
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os); PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
builder.allowSymmetricDecryption(false) // no support for symmetric encryption 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); .passphrase(passphrase);
// TODO: currently does not support binary signed-only content // 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()) { if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
// get PendingIntent for passphrase input, add it to given params and return to client // 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; 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!"); 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)) { } else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
return encryptAndSignImpl(data, input, output, accSettings, true); return encryptAndSignImpl(data, input, output, accSettings, true);
} else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) { } 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)) { } else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
return getKeyImpl(data); return getKeyImpl(data);
} else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) { } else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {

View File

@ -127,7 +127,7 @@ public abstract class RemoteService extends Service {
* *
* @return package name * @return package name
*/ */
private String getCurrentCallingPackage() { protected String getCurrentCallingPackage() {
// TODO: // TODO:
// callingPackages contains more than one entry when sharedUserId has been used... // callingPackages contains more than one entry when sharedUserId has been used...
String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
@ -243,7 +243,8 @@ public abstract class RemoteService extends Service {
return true; return true;
} else { } else {
throw new WrongPackageSignatureException( 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; package org.sufficientlysecure.keychain.remote.ui;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -31,6 +33,7 @@ import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton; import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.ui.EditKeyActivity; import org.sufficientlysecure.keychain.ui.EditKeyActivity;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment; import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
@ -40,6 +43,8 @@ import org.sufficientlysecure.keychain.util.AlgorithmNames;
public class AccountSettingsFragment extends Fragment implements public class AccountSettingsFragment extends Fragment implements
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback { SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
private static final int REQUEST_CODE_CREATE_KEY = 0x00008884;
// model // model
private AccountSettings mAccSettings; private AccountSettings mAccSettings;
@ -162,7 +167,27 @@ public class AccountSettingsFragment extends Fragment implements
intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
// set default user id to account name TODO: not working currently in EditKey // set default user id to account name TODO: not working currently in EditKey
intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, mAccSettings.getAccountName()); 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.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.widget.FixedListView; 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.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.util.Log;
public class AppsListFragment extends ListFragment implements public class AppsListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> { LoaderManager.LoaderCallbacks<Cursor> {

View File

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

View File

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

View File

@ -24,15 +24,24 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.*; import android.os.Binder;
import android.util.Log; 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.support.v4.util.LongSparseArray;
import android.util.Log;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.Preferences;
@ -86,7 +95,7 @@ public class PassphraseCacheService extends Service {
Intent intent = new Intent(context, PassphraseCacheService.class); Intent intent = new Intent(context, PassphraseCacheService.class);
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD); 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_PASSPHRASE, passphrase);
intent.putExtra(EXTRA_KEY_ID, keyId); intent.putExtra(EXTRA_KEY_ID, keyId);

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2011 Senecaso * Copyright (C) 2011 Senecaso
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -32,13 +32,18 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarActivity;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; 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.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton; import com.beardedhen.androidbootstrap.BootstrapButton;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@ -200,7 +205,8 @@ public class CertifyKeyActivity extends ActionBarActivity implements
byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT); byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
((TextView) findViewById(R.id.fingerprint)).setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); ((TextView) findViewById(R.id.fingerprint))
.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
} }
break; break;
case LOADER_ID_USER_IDS: 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 // Bail out if there is not at least one user id selected
ArrayList<String> userIds = mUserIdsAdapter.getSelectedUserIds(); ArrayList<String> userIds = mUserIdsAdapter.getSelectedUserIds();
if(userIds.isEmpty()) { if (userIds.isEmpty()) {
Toast.makeText(CertifyKeyActivity.this, "No User IDs to sign selected!", Toast.makeText(CertifyKeyActivity.this, "No User IDs to sign selected!",
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
return; return;

View File

@ -77,8 +77,10 @@ public class DecryptActivity extends DrawerActivity {
// Handle intent actions, maybe changes the bundles // Handle intent actions, maybe changes the bundles
handleActions(getIntent()); handleActions(getIntent());
mTabsAdapter.addTab(DecryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message)); mTabsAdapter.addTab(DecryptMessageFragment.class,
mTabsAdapter.addTab(DecryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file)); mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapter.addTab(DecryptFileFragment.class,
mFileFragmentBundle, getString(R.string.label_file));
mViewPager.setCurrentItem(mSwitchToTab); mViewPager.setCurrentItem(mSwitchToTab);
} }
@ -164,7 +166,8 @@ public class DecryptActivity extends DrawerActivity {
mSwitchToTab = PAGER_TAB_FILE; mSwitchToTab = PAGER_TAB_FILE;
} else { } else {
Log.e(Constants.TAG, 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) Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
.show(); .show();
// end activity // end activity

View File

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

View File

@ -47,10 +47,14 @@ import java.util.regex.Matcher;
public class DecryptMessageFragment extends DecryptFragment { public class DecryptMessageFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext"; public static final String ARG_CIPHERTEXT = "ciphertext";
// view
private EditText mMessage; private EditText mMessage;
private BootstrapButton mDecryptButton; private BootstrapButton mDecryptButton;
private BootstrapButton mDecryptFromCLipboardButton; private BootstrapButton mDecryptFromCLipboardButton;
// model
private String mCiphertext;
/** /**
* Inflate the layout for this fragment * Inflate the layout for this fragment
*/ */
@ -64,13 +68,13 @@ public class DecryptMessageFragment extends DecryptFragment {
mDecryptButton.setOnClickListener(new OnClickListener() { mDecryptButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
decryptStart(null); decryptClicked();
} }
}); });
mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() { mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { 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()); CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
// only decrypt if clipboard content is available and a pgp message or cleartext signature // 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); matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText);
} }
if (matcher.matches()) { if (matcher.matches()) {
String data = matcher.group(1); mCiphertext = matcher.group(1);
mMessage.setText(data);
decryptStart(null); decryptStart(null);
} else { } else {
AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_INFO) AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_INFO)
@ -125,8 +133,7 @@ public class DecryptMessageFragment extends DecryptFragment {
// data // data
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES); data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
String message = mMessage.getText().toString(); data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes());
data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -147,7 +154,8 @@ public class DecryptMessageFragment extends DecryptFragment {
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded());
} else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED ==
decryptVerifyResult.getStatus()) {
showPassphraseDialog(Id.key.symmetric); showPassphraseDialog(Id.key.symmetric);
} else { } else {
AppMsg.makeText(getActivity(), R.string.decryption_successful, 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.view.GravityCompat;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarActivity;
import android.view.*; import android.view.LayoutInflater;
import android.widget.*; 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 com.beardedhen.androidbootstrap.FontAwesomeText;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; 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 // if the left margin of the loaded layout is close to the
// one used in tablets then set drawer as open and locked // 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.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, mDrawerList);
mDrawerLayout.setScrimColor(Color.TRANSPARENT); mDrawerLayout.setScrimColor(Color.TRANSPARENT);
mIsDrawerLocked = true; mIsDrawerLocked = true;
@ -82,7 +91,7 @@ public class DrawerActivity extends ActionBarActivity {
// enable ActionBar app icon to behave as action to toggle nav drawer // enable ActionBar app icon to behave as action to toggle nav drawer
// if the drawer is not locked // if the drawer is not locked
if ( !mIsDrawerLocked ) { if (!mIsDrawerLocked) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setHomeButtonEnabled(true);
} }
@ -109,20 +118,18 @@ public class DrawerActivity extends ActionBarActivity {
} }
}; };
if ( !mIsDrawerLocked ) { if (!mIsDrawerLocked) {
mDrawerLayout.setDrawerListener(mDrawerToggle); mDrawerLayout.setDrawerListener(mDrawerToggle);
} else { } else {
// If the drawer is locked open make it un-focusable // If the drawer is locked open make it un-focusable
// so that it doesn't consume all the Back button presses // so that it doesn't consume all the Back button presses
mDrawerLayout.setFocusableInTouchMode(false); mDrawerLayout.setFocusableInTouchMode(false);
} }
// if (savedInstanceState == null) {
// selectItem(0);
// }
} }
/** /**
* Uses startActivity to call the Intent of the given class * 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.* * @param drawerItem the class of the drawer item you want to load. Based on Constants.DrawerItems.*
*/ */
public void callIntentForDrawerItem(Class drawerItem) { public void callIntentForDrawerItem(Class drawerItem) {
@ -150,16 +157,6 @@ public class DrawerActivity extends ActionBarActivity {
return super.onCreateOptionsMenu(menu); 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 @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer. // The action bar home/up action should open or close the drawer.
@ -182,26 +179,11 @@ public class DrawerActivity extends ActionBarActivity {
default: default:
return super.onOptionsItemSelected(item); 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 { private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@ -218,9 +200,9 @@ public class DrawerActivity extends ActionBarActivity {
// setTitle(mDrawerTitles[position]); // setTitle(mDrawerTitles[position]);
// If drawer isn't locked just close the drawer and // If drawer isn't locked just close the drawer and
// it will move to the selected item by itself (via drawer toggle listener) // it will move to the selected item by itself (via drawer toggle listener)
if ( !mIsDrawerLocked ) { if (!mIsDrawerLocked) {
mDrawerLayout.closeDrawer(mDrawerList); mDrawerLayout.closeDrawer(mDrawerList);
// else move to the selected item yourself // else move to the selected item yourself
} else { } else {
callIntentForDrawerItem(mSelectedItem); callIntentForDrawerItem(mSelectedItem);
} }

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

View File

@ -155,12 +155,16 @@ public class EncryptActivity extends DrawerActivity implements
// Handle intent actions // Handle intent actions
handleActions(getIntent()); handleActions(getIntent());
mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class, mAsymmetricFragmentBundle, getString(R.string.label_asymmetric)); mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class,
mTabsAdapterMode.addTab(EncryptSymmetricFragment.class, mSymmetricFragmentBundle, getString(R.string.label_symmetric)); mAsymmetricFragmentBundle, getString(R.string.label_asymmetric));
mTabsAdapterMode.addTab(EncryptSymmetricFragment.class,
mSymmetricFragmentBundle, getString(R.string.label_symmetric));
mViewPagerMode.setCurrentItem(mSwitchToMode); mViewPagerMode.setCurrentItem(mSwitchToMode);
mTabsAdapterContent.addTab(EncryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message)); mTabsAdapterContent.addTab(EncryptMessageFragment.class,
mTabsAdapterContent.addTab(EncryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file)); mMessageFragmentBundle, getString(R.string.label_message));
mTabsAdapterContent.addTab(EncryptFileFragment.class,
mFileFragmentBundle, getString(R.string.label_file));
mViewPagerContent.setCurrentItem(mSwitchToContent); mViewPagerContent.setCurrentItem(mSwitchToContent);
} }
@ -212,8 +216,10 @@ public class EncryptActivity extends DrawerActivity implements
long[] encryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); long[] encryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
// preselect keys given by intent // preselect keys given by intent
mAsymmetricFragmentBundle.putLongArray(EncryptAsymmetricFragment.ARG_ENCRYPTION_KEY_IDS, encryptionKeyIds); mAsymmetricFragmentBundle.putLongArray(EncryptAsymmetricFragment.ARG_ENCRYPTION_KEY_IDS,
mAsymmetricFragmentBundle.putLong(EncryptAsymmetricFragment.ARG_SIGNATURE_KEY_ID, signatureKeyId); encryptionKeyIds);
mAsymmetricFragmentBundle.putLong(EncryptAsymmetricFragment.ARG_SIGNATURE_KEY_ID,
signatureKeyId);
mSwitchToMode = PAGER_MODE_ASYMMETRIC; mSwitchToMode = PAGER_MODE_ASYMMETRIC;
/** /**
@ -234,7 +240,8 @@ public class EncryptActivity extends DrawerActivity implements
mSwitchToContent = PAGER_CONTENT_FILE; mSwitchToContent = PAGER_CONTENT_FILE;
} else { } else {
Log.e(Constants.TAG, 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) Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
.show(); .show();
// end activity // end activity

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2011 Senecaso * Copyright (C) 2011 Senecaso
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -168,7 +168,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
} }
} else { } else {
Log.e(Constants.TAG, 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; return;
} }
@ -233,7 +234,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
* onNavigationItemSelected() should check whether the Fragment is already in existence * onNavigationItemSelected() should check whether the Fragment is already in existence
* inside your Activity." * inside your Activity."
* <p/> * <p/>
* from http://stackoverflow.com/questions/10983396/fragment-oncreateview-and-onactivitycreated-called-twice/14295474#14295474 * from http://bit.ly/1dBYThO
* <p/> * <p/>
* In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint, * 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. * 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 { // } else {
// status.putString( // status.putString(
// EXTRA_ERROR, // 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) { // } catch (QueryException e) {

View File

@ -65,7 +65,7 @@ public class ImportKeysClipboardFragment extends Fragment {
String sendText = ""; String sendText = "";
if (clipboardText != null) { if (clipboardText != null) {
sendText = clipboardText.toString(); 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)); mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
return; return;
} }

View File

@ -29,7 +29,11 @@ import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences; 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.InputData;
import org.sufficientlysecure.keychain.util.KeyServer; import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;

View File

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

View File

@ -21,6 +21,7 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@ -55,10 +56,6 @@ public class KeyListActivity extends DrawerActivity {
case R.id.menu_key_list_import: case R.id.menu_key_list_import:
callIntentForDrawerItem(Constants.DrawerItems.IMPORT_KEYS); 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; return true;
case R.id.menu_key_list_create: case R.id.menu_key_list_create:
createKey(); createKey();
@ -67,9 +64,15 @@ public class KeyListActivity extends DrawerActivity {
case R.id.menu_key_list_create_expert: case R.id.menu_key_list_create_expert:
createKeyExpert(); 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; return true;
case R.id.menu_key_list_secret_export: 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; return true;
default: default:

View File

@ -24,7 +24,11 @@ import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; 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.Fragment;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader; 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.app.ActionBarActivity;
import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView;
import android.text.TextUtils; 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.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils; import android.view.animation.AnimationUtils;
import android.widget.*;
import android.widget.AbsListView.MultiChoiceModeListener; 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 com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
@ -191,9 +205,11 @@ public class KeyListFragment extends Fragment
ProviderHelper.getPublicKeyRingsRowIds(getActivity()); ProviderHelper.getPublicKeyRingsRowIds(getActivity());
for (int i = 0; i < ids.length; i++) { for (int i = 0; i < ids.length; i++) {
if (allPubRowIds.contains(ids[i])) { if (allPubRowIds.contains(ids[i])) {
masterKeyIds[i] = ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]); masterKeyIds[i] =
ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]);
} else { } else {
masterKeyIds[i] = ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]); masterKeyIds[i] =
ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]);
} }
}*/ }*/
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity()); ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());

View File

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

View File

@ -32,7 +32,13 @@ import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; 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.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround; import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;

View File

@ -187,20 +187,17 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan
return; 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 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode & 0xFFFF) { switch (requestCode) {
case REQUEST_CODE_SELECT_KEY: { case REQUEST_CODE_SELECT_KEY: {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
mReceivedUri = data.getData(); mReceivedUri = data.getData();
//Must be restartLoader() or the data will not be updated on selecting a new key //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); mKeyUserId.setError(null);
} }
break; break;
} }

View File

@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter; 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.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import org.sufficientlysecure.keychain.util.Log; 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.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;

View File

@ -32,7 +32,6 @@ import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView; import android.widget.TextView;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,12 +44,12 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
protected List<ImportKeysListEntry> mData; protected List<ImportKeysListEntry> mData;
static class ViewHolder { static class ViewHolder {
private TextView mainUserId; public TextView mainUserId;
private TextView mainUserIdRest; public TextView mainUserIdRest;
private TextView keyId; public TextView keyId;
private TextView fingerprint; public TextView fingerprint;
private TextView algorithm; public TextView algorithm;
private TextView status; public TextView status;
} }
public ImportKeysAdapter(Activity activity) { 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> * 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(-1, "unknown"); // TODO: with resources
put(0, "unencrypted"); put(0, "unencrypted");
put(PGPPublicKey.RSA_GENERAL, "RSA"); 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> * Based on <a href="http://tools.ietf.org/html/rfc2440#section-9.1">OpenPGP Message Format</a>
*/ */
public static String getAlgorithmFromId(int algorithmId) { 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.content.Context;
import android.widget.ArrayAdapter; 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> { public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
private final HashMap<Integer, String> mData; private final HashMap<Integer, String> mData;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -111,7 +111,7 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
content = keyringArmored.get(0); content = keyringArmored.get(0);
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs // 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.setPositiveButton(R.string.btn_next, null);
alert.setNegativeButton(android.R.string.cancel, null); alert.setNegativeButton(android.R.string.cancel, null);

View File

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

View File

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

View File

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

View File

@ -16,11 +16,6 @@
package org.sufficientlysecure.keychain.ui.widget; 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.content.Context;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -29,10 +24,18 @@ import android.util.Patterns;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; 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 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 { public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null; private EditorListener mEditorListener = null;
@ -49,8 +52,8 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
private boolean mOriginallyMainUserID; private boolean mOriginallyMainUserID;
private boolean mIsNewId; private boolean mIsNewId;
public void setCanEdit(boolean bCanEdit) { public void setCanBeEdited(boolean canBeEdited) {
if (!bCanEdit) { if (!canBeEdited) {
mDeleteButton.setVisibility(View.INVISIBLE); mDeleteButton.setVisibility(View.INVISIBLE);
mName.setEnabled(false); mName.setEnabled(false);
mIsMainUserId.setEnabled(false); mIsMainUserId.setEnabled(false);
@ -85,8 +88,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
} }
@Override @Override
public void afterTextChanged(Editable s) public void afterTextChanged(Editable s) {
{
if (mEditorListener != null) { if (mEditorListener != null) {
mEditorListener.onEdited(); mEditorListener.onEdited();
} }
@ -240,25 +242,24 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
@Override @Override
public boolean needsSaving() { public boolean needsSaving() {
boolean retval = false; //(mOriginallyMainUserID != isMainUserId()); boolean retval = false; //(mOriginallyMainUserID != isMainUserId());
retval |= !(mOriginalName.equals( ("" + mName.getText()).trim() ) ); retval |= !(mOriginalName.equals(("" + mName.getText()).trim()));
retval |= !(mOriginalEmail.equals( ("" + mEmail.getText()).trim() ) ); retval |= !(mOriginalEmail.equals(("" + mEmail.getText()).trim()));
retval |= !(mOriginalComment.equals( ("" + mComment.getText()).trim() ) ); retval |= !(mOriginalComment.equals(("" + mComment.getText()).trim()));
retval |= mIsNewId; retval |= mIsNewId;
return retval; return retval;
} }
public boolean getIsOriginallyMainUserID() public boolean getIsOriginallyMainUserID() {
{
return mOriginallyMainUserID; return mOriginallyMainUserID;
} }
public boolean primarySwapped() public boolean primarySwapped() {
{
return (mOriginallyMainUserID != isMainUserId()); return (mOriginallyMainUserID != isMainUserId());
} }
public String getOriginalID() public String getOriginalID() {
{
return mOriginalID; 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.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.*; import java.net.HttpURLConnection;
import java.util.*; 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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry.getAlgorithmFromId;
public class HkpKeyServer extends KeyServer { public class HkpKeyServer extends KeyServer {
private static class HttpError extends Exception { private static class HttpError extends Exception {
private static final long serialVersionUID = 1718783705229428893L; private static final long serialVersionUID = 1718783705229428893L;
@ -72,20 +80,22 @@ public class HkpKeyServer extends KeyServer {
/** /**
* pub:%keyid%:%algo%:%keylen%:%creationdate%:%expirationdate%:%flags% * pub:%keyid%:%algo%:%keylen%:%creationdate%:%expirationdate%:%flags%
* <ul> * <ul>
* <li>%<b>keyid</b>% = this is either the fingerprint or the key ID of the key. Either the 16-digit or 8-digit * <li>%<b>keyid</b>% = this is either the fingerprint or the key ID of the key.
* key IDs are acceptable, but obviously the fingerprint is best.</li> * 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). * <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> * 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>keylen</b>% = the key length (i.e. 1024, 2048, 4096, etc.)</li>
* <li>%<b>creationdate</b>% = creation date of the key in standard * <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 * <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* 1/1/1970 UTC time)</li> * seconds since 1/1/1970 UTC time)</li>
* <li>%<b>expirationdate</b>% = expiration date of the key in standard * <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 * <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* 1/1/1970 UTC time)</li> * 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 * <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any
* meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so * order. The meaning of "disabled" is implementation-specific. Note that individual flags may
* the absence of a given flag does not necessarily mean the absence of the detail. * be unimplemented, so the absence of a given flag does not necessarily mean the absence of the
* detail.
* <ul> * <ul>
* <li>r == revoked</li> * <li>r == revoked</li>
* <li>d == disabled</li> * <li>d == disabled</li>
@ -94,7 +104,8 @@ public class HkpKeyServer extends KeyServer {
* </li> * </li>
* </ul> * </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 * in Internet-Draft OpenPGP HTTP Keyserver Protocol Document
*/ */
public static final Pattern PUB_KEY_LINE = Pattern public static final Pattern PUB_KEY_LINE = Pattern
@ -105,17 +116,19 @@ public class HkpKeyServer extends KeyServer {
/** /**
* uid:%escaped uid string%:%creationdate%:%expirationdate%:%flags% * uid:%escaped uid string%:%creationdate%:%expirationdate%:%flags%
* <ul> * <ul>
* <li>%<b>escaped uid string</b>% = the user ID string, with HTTP %-escaping for anything that isn't 7-bit * <li>%<b>escaped uid string</b>% = the user ID string, with HTTP %-escaping for anything that
* safe as well as for the ":" character. Any other characters may be escaped, as desired.</li> * 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 * <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 * <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* 1/1/1970 UTC time)</li> * seconds since 1/1/1970 UTC time)</li>
* <li>%<b>expirationdate</b>% = expiration date of the key in standard * <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 * <a href="http://tools.ietf.org/html/rfc2440#section-9.1">RFC-2440</a> form (i.e. number of
* 1/1/1970 UTC time)</li> * 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 * <li>%<b>flags</b>% = letter codes to indicate details of the key, if any. Flags may be in any
* meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so * order. The meaning of "disabled" is implementation-specific. Note that individual flags may
* the absence of a given flag does not necessarily mean the absence of the detail. * be unimplemented, so the absence of a given flag does not necessarily mean the absence of
* the detail.
* <ul> * <ul>
* <li>r == revoked</li> * <li>r == revoked</li>
* <li>d == disabled</li> * <li>d == disabled</li>
@ -244,11 +257,10 @@ public class HkpKeyServer extends KeyServer {
entry.setBitStrength(Integer.parseInt(matcher.group(3))); entry.setBitStrength(Integer.parseInt(matcher.group(3)));
final int algorithmId = Integer.decode(matcher.group(2)); 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 // 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 // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr
// and https://github.com/openpgp-keychain/openpgp-keychain/issues/259#issuecomment-38168176
String fingerprintOrKeyId = matcher.group(1); String fingerprintOrKeyId = matcher.group(1);
if (fingerprintOrKeyId.length() > 16) { if (fingerprintOrKeyId.length() > 16) {
entry.setFingerPrintHex(fingerprintOrKeyId.toLowerCase(Locale.US)); 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at

View File

@ -16,9 +16,10 @@
package org.sufficientlysecure.keychain.util; package org.sufficientlysecure.keychain.util;
import com.google.zxing.integration.android.IntentIntegrator;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import com.google.zxing.integration.android.IntentIntegrator;
/** /**
* IntentIntegrator for the V4 Android compatibility package. * 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) { public IterableIterator(Iterator<T> iter, boolean failsafe) {
mIter = iter; mIter = iter;
if(failsafe && mIter == null) { if (failsafe && mIter == null) {
// is there a better way? // is there a better way?
mIter = new ArrayList<T>().iterator(); mIter = new ArrayList<T>().iterator();
} }

View File

@ -1,16 +1,20 @@
/* /*
* Licensed under the Apache License, Version 2.0 (the "License"); * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * 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 * This program is distributed in the hope that it will be useful,
* distributed under the License is distributed on an "AS IS" BASIS, * but WITHOUT ANY WARRANTY; without even the implied warranty of
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* See the License for the specific language governing permissions and * GNU General Public License for more details.
* limitations under the License. *
* 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; package org.sufficientlysecure.keychain.util;
public interface KeychainServiceListener { public interface KeychainServiceListener {

View File

@ -17,7 +17,11 @@
package org.sufficientlysecure.keychain.util; 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.Condition;
import java.util.concurrent.locks.ReentrantLock; 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * 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 * Set progressDialogUpdater of ProgressDialog by sending message to handler on UI thread
*/ */
public void setProgress(String message, int progress, int max) { 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) { public void setProgress(int resourceId, int progress, int max) {

View File

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

View File

@ -54,10 +54,10 @@
android:orientation="horizontal"> android:orientation="horizontal">
<CheckBox <CheckBox
android:id="@+id/asciiArmour" android:id="@+id/asciiArmor"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:text="@string/label_ascii_armor"/> android:text="@string/label_ascii_armor"/>
</LinearLayout> </LinearLayout>
</merge> </merge>

View File

@ -2,11 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> 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 <item
android:id="@+id/menu_key_list_search" android:id="@+id/menu_key_list_search"
@ -16,23 +11,44 @@
app:showAsAction="collapseActionView|ifRoom" /> app:showAsAction="collapseActionView|ifRoom" />
<item <item
android:id="@+id/menu_key_list_create" android:id="@+id/menu_key_list_add"
app:showAsAction="never" app:showAsAction="ifRoom|withText"
android:title="@string/menu_create_key" /> 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 <item
android:id="@+id/menu_key_list_create_expert" android:id="@+id/menu_key_list_create"
app:showAsAction="never" app:showAsAction="never"
android:title="@string/menu_create_key_expert" /> android:title="@string/menu_create_key" />
<item
android:id="@+id/menu_key_list_create_expert"
app:showAsAction="never"
android:title="@string/menu_create_key_expert" />
</menu>
</item>
<item <item
android:id="@+id/menu_key_list_export" android:id="@+id/menu_key_list_export"
app:showAsAction="never" app:showAsAction="ifRoom|withText"
android:title="@string/menu_export_keys" /> 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_public_keys" />
<item <item
android:id="@+id/menu_key_list_secret_export" android:id="@+id/menu_key_list_secret_export"
app:showAsAction="never" app:showAsAction="never"
android:title="@string/menu_export_secret_keys" /> android:title="@string/menu_export_secret_keys" />
</menu>
</item>
</menu> </menu>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,25 +2,25 @@
<head></head> <head></head>
<body> <body>
<h2>2.4</h2> <h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! <p>Дякуємо усім заявникам Google Summer of Code 2014, які зробили цю версію багатшу на функції та вільну від помилок!
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>
<ul> <ul>
<li>new unified key list</li> <li>новий єдиний перелік ключів</li>
<li>colorized key fingerprint</li> <li>кольоровий відбиток ключа</li>
<li>support for keyserver ports</li> <li>підтримка для портів сервера ключів</li>
<li>deactivate possibility to generate weak keys</li> <li>деактивувати можливість генерувати слабкі ключі</li>
<li>much more internal work on the API</li> <li>набагато більше внутрішньої роботи на API</li>
<li>certify user ids</li> <li>сертифікувати ідентифікатори користувача</li>
<li>keyserver query based on machine-readable output</li> <li>запит сервера ключів на основі машиночитабельного виводу</li>
<li>lock navigation drawer on tablets</li> <li>блокувати панель навігації на планшетах</li>
<li>suggestions for emails on creation of keys</li> <li>пропозиції для листів при створенні ключів</li>
<li>search in public key lists</li> <li>пошук у списках відкритих ключів</li>
<li>and much more improvements and fixes</li> <li>і багато інших покращень та виправлень</li>
</ul> </ul>
<h2>2.3.1</h2> <h2>2.3.1</h2>
<ul> <ul>
<li>hotfix for crash when upgrading from old versions</li> <li>свіже виправлення збою при оновленні із старих версій</li>
</ul> </ul>
<h2>2.3</h2> <h2>2.3</h2>
<ul> <ul>

View File

@ -5,6 +5,14 @@ And don't add newlines before or after p tags because of transifex -->
<head> <head>
</head> </head>
<body> <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> <h2>2.4</h2>
<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! <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): 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--> <!--label-->
<string name="unknown_status"></string> <string name="unknown_status"></string>
<!--choice--> <!--choice-->
<!--key flags-->
<!--sentences--> <!--sentences-->
<!--errors <!--errors
no punctuation, all lowercase, no punctuation, all lowercase,

View File

@ -55,8 +55,6 @@
<string name="btn_delete">Löschen</string> <string name="btn_delete">Löschen</string>
<string name="btn_no_date">Keine</string> <string name="btn_no_date">Keine</string>
<string name="btn_okay">Okay</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_search">Suchen</string>
<string name="btn_export_to_server">Auf Schlüsselserver hochladen</string> <string name="btn_export_to_server">Auf Schlüsselserver hochladen</string>
<string name="btn_next">Weiter</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_from_qr_code">QR-Code</string>
<string name="menu_import">Importieren</string> <string name="menu_import">Importieren</string>
<string name="menu_import_from_nfc">NFC</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_secret_keys">Alle geheimen Schlüssel exportieren</string>
<string name="menu_export_key">In Datei exportieren</string> <string name="menu_export_key">In Datei exportieren</string>
<string name="menu_delete_key">Schlüssel löschen</string> <string name="menu_delete_key">Schlüssel löschen</string>
@ -129,8 +126,6 @@
<string name="label_name">Name</string> <string name="label_name">Name</string>
<string name="label_comment">Kommentar</string> <string name="label_comment">Kommentar</string>
<string name="label_email">E-Mail</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_send_key">Schlüssel nach Beglaubigung auf ausgewählten Schlüsselserver hochladen</string>
<string name="label_fingerprint">Fingerabdruck</string> <string name="label_fingerprint">Fingerabdruck</string>
<string name="select_keys_button_default">Auswählen</string> <string name="select_keys_button_default">Auswählen</string>
@ -161,9 +156,6 @@
<string name="secret_key">Privater Schlüssel:</string> <string name="secret_key">Privater Schlüssel:</string>
<!--choice--> <!--choice-->
<string name="choice_none">Keine</string> <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_15secs">15 s</string>
<string name="choice_1min">1 min</string> <string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string> <string name="choice_3mins">3 min</string>
@ -183,21 +175,18 @@
<string name="warning">Warnung</string> <string name="warning">Warnung</string>
<string name="error">Fehler</string> <string name="error">Fehler</string>
<string name="error_message">Fehler: %s</string> <string name="error_message">Fehler: %s</string>
<!--key flags-->
<!--sentences--> <!--sentences-->
<string name="wrong_passphrase">Falsches Passwort.</string> <string name="wrong_passphrase">Falsches Passwort.</string>
<string name="using_clipboard_content">Verwende Inhalt der Zwischenablage.</string> <string name="using_clipboard_content">Verwende Inhalt der Zwischenablage.</string>
<string name="set_a_passphrase">Zuerst ein Passwort setzen.</string> <string name="set_a_passphrase">Zuerst ein Passwort setzen.</string>
<string name="no_filemanager_installed">Kein passender Dateimanager installiert.</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="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_symmetric_encryption">Symmetrische Verschlüsselung.</string>
<string name="passphrase_for">Passwort für \'%s\' eingeben</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_confirmation">%s\nwirklich löschen?</string>
<string name="file_delete_successful">Erfolgreich gelöscht.</string> <string name="file_delete_successful">Erfolgreich gelöscht.</string>
<string name="no_file_selected">Zuerst eine Datei auswählen.</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="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_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> <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_main">Info</string>
<string name="key_view_tab_certs">Zertifikationen</string> <string name="key_view_tab_certs">Zertifikationen</string>
<!--Navigation Drawer--> <!--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_import">Schlüssel Importieren</string>
<string name="nav_secret_keys">Meine Schlüssel</string> <string name="nav_secret_keys">Meine Schlüssel</string>
<string name="nav_apps">Registrierte Anwendungen</string> <string name="nav_apps">Registrierte Anwendungen</string>

View File

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

View File

@ -36,8 +36,6 @@
<string name="btn_delete">Borrar</string> <string name="btn_delete">Borrar</string>
<string name="btn_no_date">Ninguno</string> <string name="btn_no_date">Ninguno</string>
<string name="btn_okay">Ok</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_search">Buscar</string>
<string name="btn_next">Siguiente</string> <string name="btn_next">Siguiente</string>
<string name="btn_back">Atrás</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_file">Importar desde archivo</string>
<string name="menu_import_from_qr_code">Importar desde código QR</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_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_export_key">Exportar a archivo</string>
<string name="menu_delete_key">Borrar clave</string> <string name="menu_delete_key">Borrar clave</string>
<string name="menu_create_key">Crear clave</string> <string name="menu_create_key">Crear clave</string>
@ -81,6 +78,7 @@
<string name="label_email">Correo electrónico</string> <string name="label_email">Correo electrónico</string>
<string name="unknown_status"></string> <string name="unknown_status"></string>
<!--choice--> <!--choice-->
<!--key flags-->
<!--sentences--> <!--sentences-->
<!--errors <!--errors
no punctuation, all lowercase, no punctuation, all lowercase,

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certificar</string> <string name="btn_certify">Certificar</string>
<string name="btn_decrypt">Descifrar</string> <string name="btn_decrypt">Descifrar</string>
<string name="btn_decrypt_verify">Descifrar y verificar</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_select_encrypt_keys">Seleccionar destinatarios</string>
<string name="btn_encrypt_file">Cifrar archivo</string> <string name="btn_encrypt_file">Cifrar archivo</string>
<string name="btn_save">Guardar</string> <string name="btn_save">Guardar</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Eliminar</string> <string name="btn_delete">Eliminar</string>
<string name="btn_no_date">Ninguno</string> <string name="btn_no_date">Ninguno</string>
<string name="btn_okay">De acuerdo</string> <string name="btn_okay">De acuerdo</string>
<string name="btn_change_passphrase">Cambiar la frase de contraseña</string> <string name="btn_change_passphrase">Cambiar nueva frase de contraseña</string>
<string name="btn_set_passphrase">Establecer 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_search">Buscar</string>
<string name="btn_export_to_server">Cargar al servidor de claves</string> <string name="btn_export_to_server">Cargar al servidor de claves</string>
<string name="btn_next">Siguiente</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_from_qr_code">Importar desde código QR</string>
<string name="menu_import">Importar</string> <string name="menu_import">Importar</string>
<string name="menu_import_from_nfc">Importar desde NFC</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_secret_keys">Exportar todas las claves secretas</string>
<string name="menu_export_key">Exportar hacia archivo</string> <string name="menu_export_key">Exportar hacia archivo</string>
<string name="menu_delete_key">Borrar clave</string> <string name="menu_delete_key">Borrar clave</string>
@ -129,8 +129,6 @@
<string name="label_name">Nombre</string> <string name="label_name">Nombre</string>
<string name="label_comment">Comentario</string> <string name="label_comment">Comentario</string>
<string name="label_email">Email</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_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="label_fingerprint">Huella digital</string>
<string name="select_keys_button_default">Seleccionar</string> <string name="select_keys_button_default">Seleccionar</string>
@ -161,9 +159,6 @@
<string name="secret_key">Clave secreta:</string> <string name="secret_key">Clave secreta:</string>
<!--choice--> <!--choice-->
<string name="choice_none">Ninguna</string> <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_15secs">15 segs</string>
<string name="choice_1min">1 min</string> <string name="choice_1min">1 min</string>
<string name="choice_3mins">3 mins</string> <string name="choice_3mins">3 mins</string>
@ -183,21 +178,22 @@
<string name="warning">Advertencia</string> <string name="warning">Advertencia</string>
<string name="error">Error</string> <string name="error">Error</string>
<string name="error_message">Error: %s</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--> <!--sentences-->
<string name="wrong_passphrase">Frase de contraseña incorrecta.</string> <string name="wrong_passphrase">Frase de contraseña incorrecta.</string>
<string name="using_clipboard_content">Usando el contenido del portapapeles.</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="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="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="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_symmetric_encryption">Cifrado simétrico.</string>
<string name="passphrase_for">Introducir la frase de contraseña para \'%s\'</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_confirmation">¿Estás seguro de que quieres borrar\n%s?</string>
<string name="file_delete_successful">Borrado satisfactoriamente.</string> <string name="file_delete_successful">Borrado satisfactoriamente.</string>
<string name="no_file_selected">Selecciona un archivo antes.</string> <string name="no_file_selected">Selecciona un archivo antes.</string>
<string name="decryption_successful">Descifrado 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="enter_passphrase_twice">Introduce la frase de contraseña dos veces.</string>
<string name="select_encryption_key">Selecciona al menos una clave de cifrado.</string> <string name="select_encryption_key">Selecciona al menos una clave de cifrado.</string>
<string name="select_encryption_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string> <string name="select_encryption_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string>
@ -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">¿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="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="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="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="secret_key_delete_text">¿Borrar claves secretas?</string>
<string name="also_export_secret_keys">¿Exportar también las 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_nfc_needed">¡NFC no está disponible en tu dispositivo!</string>
<string name="error_nothing_import">¡Nada que importar!</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_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_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_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> <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_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_no_key">No se ha seleccionado ninguna clave</string>
<string name="api_settings_select_key">Seleccionar 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_save">Guardar</string>
<string name="api_settings_cancel">Cancelar</string> <string name="api_settings_cancel">Cancelar</string>
<string name="api_settings_revoke">Revocar acceso</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_name">Nombre de paquete</string>
<string name="api_settings_package_signature">SHA-256 de firma 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">Cuentas</string>
<string name="api_settings_accounts_empty">No hay cuentas asociadas a esta aplicación.</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_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_allow">Permitir el acceso</string>
<string name="api_register_disallow">Denegar 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_main">Información</string>
<string name="key_view_tab_certs">Certificaciones</string> <string name="key_view_tab_certs">Certificaciones</string>
<!--Navigation Drawer--> <!--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_import">Importar claves</string>
<string name="nav_secret_keys">Mis claves</string> <string name="nav_secret_keys">Mis claves</string>
<string name="nav_apps">Aplicaciones registradas</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="section_uids_to_sign">IDs de usuario para firmar</string>
<string name="progress_re_adding_certs">Nueva aplicación de certificados</string> <string name="progress_re_adding_certs">Nueva aplicación de certificados</string>
<!--hints--> <!--hints-->
<string name="encrypt_content_edit_text_hint">Escribe aquí el mensaje que quieras cifrar...</string>
</resources> </resources>

View File

@ -35,7 +35,6 @@
<string name="btn_save">Salvesta</string> <string name="btn_save">Salvesta</string>
<string name="btn_do_not_save">Katkesta</string> <string name="btn_do_not_save">Katkesta</string>
<string name="btn_delete">Kustuta</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_search">Otsi</string>
<string name="btn_export_to_server">Saada võtmeserverisse</string> <string name="btn_export_to_server">Saada võtmeserverisse</string>
<string name="btn_next">Järgmine</string> <string name="btn_next">Järgmine</string>
@ -77,9 +76,6 @@
<string name="fingerprint">Sõrmejälg:</string> <string name="fingerprint">Sõrmejälg:</string>
<string name="secret_key">Salajane võti:</string> <string name="secret_key">Salajane võti:</string>
<!--choice--> <!--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_15secs">15 sekundit</string>
<string name="choice_1min">1 minut</string> <string name="choice_1min">1 minut</string>
<string name="choice_3mins">3 minutit</string> <string name="choice_3mins">3 minutit</string>
@ -98,11 +94,11 @@
<string name="warning">Hoiatus</string> <string name="warning">Hoiatus</string>
<string name="error">Viga</string> <string name="error">Viga</string>
<string name="error_message">Viga: %s</string> <string name="error_message">Viga: %s</string>
<!--key flags-->
<!--sentences--> <!--sentences-->
<string name="wrong_passphrase">Vale salasõne</string> <string name="wrong_passphrase">Vale salasõne</string>
<string name="set_a_passphrase">Määra enne 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="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> <string name="passphrase_for_symmetric_encryption">Sümmeetriline krüpteering</string>
<!--errors <!--errors
no punctuation, all lowercase, no punctuation, all lowercase,

View File

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

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certifier</string> <string name="btn_certify">Certifier</string>
<string name="btn_decrypt">Déchiffrer</string> <string name="btn_decrypt">Déchiffrer</string>
<string name="btn_decrypt_verify">Déchiffrer et vérifier</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_select_encrypt_keys">Choisir les destinataires</string>
<string name="btn_encrypt_file">Chiffrer le fichier</string> <string name="btn_encrypt_file">Chiffrer le fichier</string>
<string name="btn_save">Enregistrer</string> <string name="btn_save">Enregistrer</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Supprimer</string> <string name="btn_delete">Supprimer</string>
<string name="btn_no_date">Aucune</string> <string name="btn_no_date">Aucune</string>
<string name="btn_okay">OK</string> <string name="btn_okay">OK</string>
<string name="btn_change_passphrase">Changer 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 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_search">Rechercher</string>
<string name="btn_export_to_server">Téléverser vers le serveur de clefs</string> <string name="btn_export_to_server">Téléverser vers le serveur de clefs</string>
<string name="btn_next">Suivant</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_from_qr_code">Importer depuis un code QR</string>
<string name="menu_import">Importer</string> <string name="menu_import">Importer</string>
<string name="menu_import_from_nfc">Importer avec NFC</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_secret_keys">Exporter toutes les clefs secrètes</string>
<string name="menu_export_key">Exporter vers un fichier</string> <string name="menu_export_key">Exporter vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string> <string name="menu_delete_key">Supprimer la clef</string>
@ -129,8 +129,6 @@
<string name="label_name">Nom</string> <string name="label_name">Nom</string>
<string name="label_comment">Commentaire</string> <string name="label_comment">Commentaire</string>
<string name="label_email">Courriel</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_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="label_fingerprint">Empreinte</string>
<string name="select_keys_button_default">Choisir</string> <string name="select_keys_button_default">Choisir</string>
@ -161,9 +159,6 @@
<string name="secret_key">Clef secrète :</string> <string name="secret_key">Clef secrète :</string>
<!--choice--> <!--choice-->
<string name="choice_none">Aucune</string> <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_15secs">15 s</string>
<string name="choice_1min">1 min</string> <string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string> <string name="choice_3mins">3 min</string>
@ -183,21 +178,22 @@
<string name="warning">Avertissement</string> <string name="warning">Avertissement</string>
<string name="error">Erreur</string> <string name="error">Erreur</string>
<string name="error_message">Erreur : %s</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--> <!--sentences-->
<string name="wrong_passphrase">Phrase de passe erronée</string> <string name="wrong_passphrase">Phrase de passe erronée</string>
<string name="using_clipboard_content">Utiliser le contenu du presse-papiers.</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="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="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="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_symmetric_encryption">Chriffrement symétrique.</string>
<string name="passphrase_for">Saisir une phrase de passe pour « %s »</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_confirmation">Êtes-vous sûr de vouloir supprimer\n%s ?</string>
<string name="file_delete_successful">Supprimé avec succès.</string> <string name="file_delete_successful">Supprimé avec succès.</string>
<string name="no_file_selected">Choisir d\'abord un fichier.</string> <string name="no_file_selected">Choisir d\'abord un fichier.</string>
<string name="decryption_successful">Déchiffré 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="enter_passphrase_twice">Saisir la phrase de passe deux fois.</string>
<string name="select_encryption_key">Choisir au moins une clef de chiffrement.</string> <string name="select_encryption_key">Choisir au moins une clef de chiffrement.</string>
<string name="select_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string> <string name="select_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string>
@ -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">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="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="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="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="secret_key_delete_text">Supprimer les clefs privées ?</string>
<string name="also_export_secret_keys">Exporter aussi les clefs secrètes?</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_nfc_needed">NFC n\'est pas disponible sur votre appareil !</string>
<string name="error_nothing_import">Rien à importer !</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_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_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_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> <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="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> <item quantity="other">certaines parties du fichier chargé sont des objets OpenPGP valides mais pas des clefs OpenPGP</item>
</plurals> </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 '…'--> <!--progress dialogs, usually ending in '…'-->
<string name="progress_done">Terminé.</string> <string name="progress_done">Terminé.</string>
<string name="progress_cancel">Annuler</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_hide_advanced">Masquer les paramètres avancés</string>
<string name="api_settings_no_key">Aucune clef choisie</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_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_save">Enregistrer</string>
<string name="api_settings_cancel">Annuler</string> <string name="api_settings_cancel">Annuler</string>
<string name="api_settings_revoke">Révoquer l\'accès</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_name">Nom du paquet</string>
<string name="api_settings_package_signature">SHA-256 de la signature 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">Comptes</string>
<string name="api_settings_accounts_empty">Aucun compte n\'est attaché à cette application.</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_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_allow">Permettre l\'accès</string>
<string name="api_register_disallow">Enlever 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_main">Infos</string>
<string name="key_view_tab_certs">Certifications</string> <string name="key_view_tab_certs">Certifications</string>
<!--Navigation Drawer--> <!--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_import">Importer les clefs</string>
<string name="nav_secret_keys">Mes clefs</string> <string name="nav_secret_keys">Mes clefs</string>
<string name="nav_apps">Applis enregistrées</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="section_uids_to_sign">ID utilisateur pour signer</string>
<string name="progress_re_adding_certs">Nouvel application des certificats</string> <string name="progress_re_adding_certs">Nouvel application des certificats</string>
<!--hints--> <!--hints-->
<string name="encrypt_content_edit_text_hint">Écrire le message à chiffrer ici...</string>
</resources> </resources>

View File

@ -48,6 +48,7 @@
<string name="btn_certify">Certifica</string> <string name="btn_certify">Certifica</string>
<string name="btn_decrypt">Decodifica</string> <string name="btn_decrypt">Decodifica</string>
<string name="btn_decrypt_verify">Decodifica e Verifica</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_select_encrypt_keys">Seleziona Destinatari</string>
<string name="btn_encrypt_file">Codifica File</string> <string name="btn_encrypt_file">Codifica File</string>
<string name="btn_save">Salva</string> <string name="btn_save">Salva</string>
@ -55,8 +56,8 @@
<string name="btn_delete">Elimina</string> <string name="btn_delete">Elimina</string>
<string name="btn_no_date">Nessuno</string> <string name="btn_no_date">Nessuno</string>
<string name="btn_okay">Okay</string> <string name="btn_okay">Okay</string>
<string name="btn_change_passphrase">Cambia Frase Di Accesso</string> <string name="btn_change_passphrase">Cambia Nuova Frase di Accesso</string>
<string name="btn_set_passphrase">Imposta Frase di Accesso</string> <string name="btn_set_passphrase">Imposta Nuova Frase di Accesso</string>
<string name="btn_search">Cerca</string> <string name="btn_search">Cerca</string>
<string name="btn_export_to_server">Carica sul Server delle Chiavi</string> <string name="btn_export_to_server">Carica sul Server delle Chiavi</string>
<string name="btn_next">Prossimo</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_from_qr_code">Importa da Codice QR</string>
<string name="menu_import">Importa</string> <string name="menu_import">Importa</string>
<string name="menu_import_from_nfc">Importa tramite NFC</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_secret_keys">Esporta tutte le chiavi segrete</string>
<string name="menu_export_key">Esporta su un file</string> <string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string> <string name="menu_delete_key">Cancella chiave</string>
<string name="menu_create_key">Crea 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_search">Cerca</string>
<string name="menu_import_from_key_server">Server delle Chiavi</string> <string name="menu_import_from_key_server">Server delle Chiavi</string>
<string name="menu_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_file">File</string>
<string name="label_no_passphrase">Nessuna Frase di Accesso</string> <string name="label_no_passphrase">Nessuna Frase di Accesso</string>
<string name="label_passphrase">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_algorithm">Algortimo</string>
<string name="label_ascii_armor">Armatura ASCII</string> <string name="label_ascii_armor">Armatura ASCII</string>
<string name="label_select_public_keys">Destinatari</string> <string name="label_select_public_keys">Destinatari</string>
@ -129,8 +129,6 @@
<string name="label_name">Nome</string> <string name="label_name">Nome</string>
<string name="label_comment">Commento</string> <string name="label_comment">Commento</string>
<string name="label_email">Email</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_send_key">Carica chiave nel server delle chiavi selezionati dopo la certificazione</string>
<string name="label_fingerprint">Impronta</string> <string name="label_fingerprint">Impronta</string>
<string name="select_keys_button_default">Seleziona</string> <string name="select_keys_button_default">Seleziona</string>
@ -161,9 +159,6 @@
<string name="secret_key">Chiave Privata:</string> <string name="secret_key">Chiave Privata:</string>
<!--choice--> <!--choice-->
<string name="choice_none">Nessuno</string> <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_15secs">15 sec</string>
<string name="choice_1min">1 min</string> <string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string> <string name="choice_3mins">3 min</string>
@ -183,21 +178,22 @@
<string name="warning">Attenzione</string> <string name="warning">Attenzione</string>
<string name="error">Errore</string> <string name="error">Errore</string>
<string name="error_message">Errore: %s</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--> <!--sentences-->
<string name="wrong_passphrase">Frase di Accesso errata</string> <string name="wrong_passphrase">Frase di Accesso errata</string>
<string name="using_clipboard_content">Utilizzo il contenuto degli appunti.</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="set_a_passphrase">Imposta prima una frase di accesso.</string>
<string name="no_filemanager_installed">Nessun gestore file compatibile installato.</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="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_symmetric_encryption">Codifica Simmetrica.</string>
<string name="passphrase_for">Inserisci la frase di accesso per \'%s\'</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_confirmation">Sei sicuro di voler cancellare\n%s?</string>
<string name="file_delete_successful">Eliminato correttamente.</string> <string name="file_delete_successful">Eliminato correttamente.</string>
<string name="no_file_selected">Seleziona un file prima.</string> <string name="no_file_selected">Seleziona un file prima.</string>
<string name="decryption_successful">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="enter_passphrase_twice">Inserisci la frase di accesso due volte.</string>
<string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string> <string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string>
<string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string> <string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string>
@ -208,6 +204,7 @@
<string name="key_deletion_confirmation">Vuoi veramente eliminare la chiave \'%s\'?\nNon potrai annullare!</string> <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="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="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="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="secret_key_delete_text">Eliminare le Chiavi Segrete?</string>
<string name="also_export_secret_keys">Esportare anche 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_nfc_needed">NFC non disponibile nel tuo dispositivo!</string>
<string name="error_nothing_import">Niente da importare!</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_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_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_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> <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_encrypt">Codifica con OpenKeychain</string>
<string name="intent_send_decrypt">Decodifica con OpenKeychain</string> <string name="intent_send_decrypt">Decodifica con OpenKeychain</string>
<!--Remote API--> <!--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_show_advanced">Mostra impostazioni avanzate</string>
<string name="api_settings_hide_advanced">Nascondi 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_no_key">Nessuna chiave selezionata</string>
<string name="api_settings_select_key">Seleziona chiave</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_save">Salva</string>
<string name="api_settings_cancel">Annulla</string> <string name="api_settings_cancel">Annulla</string>
<string name="api_settings_revoke">Revoca accesso</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_name">Nome Pacchetto</string>
<string name="api_settings_package_signature">SHA-256 della Firma del 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_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_allow">Permetti accesso</string>
<string name="api_register_disallow">Nega 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_main">Info</string>
<string name="key_view_tab_certs">Certificazioni</string> <string name="key_view_tab_certs">Certificazioni</string>
<!--Navigation Drawer--> <!--Navigation Drawer-->
<string name="nav_contacts">Contatti</string> <string name="nav_import">Importa Chiavi</string>
<string name="nav_encrypt">Codifica</string>
<string name="nav_decrypt">Decodifica</string>
<string name="nav_import">Importare Chiavi</string>
<string name="nav_secret_keys">Le Mie Chiavi</string> <string name="nav_secret_keys">Le Mie Chiavi</string>
<string name="nav_apps">App Registrate</string> <string name="nav_apps">App Registrate</string>
<string name="drawer_open">Apri drawer di navigazione</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="section_uids_to_sign">ID Utente da firmare</string>
<string name="progress_re_adding_certs">Riapplicazione certificati</string> <string name="progress_re_adding_certs">Riapplicazione certificati</string>
<!--hints--> <!--hints-->
<string name="encrypt_content_edit_text_hint">Scrivi qui il messaggio da codificare...</string>
</resources> </resources>

View File

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

View File

@ -36,8 +36,6 @@
<string name="btn_delete">Verwijderen</string> <string name="btn_delete">Verwijderen</string>
<string name="btn_no_date">Geen</string> <string name="btn_no_date">Geen</string>
<string name="btn_okay">OK</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_search">Zoeken</string>
<string name="btn_next">Volgende</string> <string name="btn_next">Volgende</string>
<string name="btn_back">Terug</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_file">Importeren uit bestand</string>
<string name="menu_import_from_qr_code">Importeren met QR-code</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_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_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string> <string name="menu_delete_key">Sleutel verwijderen</string>
<string name="menu_create_key">Sleutel aanmaken</string> <string name="menu_create_key">Sleutel aanmaken</string>
@ -91,9 +88,6 @@
<string name="secret_key">Privésleutel:</string> <string name="secret_key">Privésleutel:</string>
<!--choice--> <!--choice-->
<string name="choice_none">Geen</string> <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_15secs">15 sec.</string>
<string name="choice_1min">1 min.</string> <string name="choice_1min">1 min.</string>
<string name="choice_3mins">3 min.</string> <string name="choice_3mins">3 min.</string>
@ -112,21 +106,18 @@
<string name="warning">Waarschuwing</string> <string name="warning">Waarschuwing</string>
<string name="error">Fout</string> <string name="error">Fout</string>
<string name="error_message">Fout: %s</string> <string name="error_message">Fout: %s</string>
<!--key flags-->
<!--sentences--> <!--sentences-->
<string name="wrong_passphrase">Wachtwoord verkeerd.</string> <string name="wrong_passphrase">Wachtwoord verkeerd.</string>
<string name="using_clipboard_content">Gebruikmaken van klembordinhoud.</string> <string name="using_clipboard_content">Gebruikmaken van klembordinhoud.</string>
<string name="set_a_passphrase">Stel eerst een wachtwoord in.</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="no_filemanager_installed">Geen compatibele bestandsbeheerder geïnstalleerd.</string>
<string name="passphrases_do_not_match">De wachtwoorden komen niet overeen.</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_symmetric_encryption">Symmetrische versleuteling.</string>
<string name="passphrase_for">Voer het wachtwoord in voor \'%s\'</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_confirmation">Weer u zeker dat u het volgende wilt verwijderen:\n%s?</string>
<string name="file_delete_successful">Succesvol verwijderd.</string> <string name="file_delete_successful">Succesvol verwijderd.</string>
<string name="no_file_selected">Selecteer eerst een bestand.</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="enter_passphrase_twice">Voer het wachtwoord tweemaal in.</string>
<string name="select_encryption_key">Selecteer ten minste één versleutelingssleutel.</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> <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_delete">Usuń</string>
<string name="btn_no_date">Żaden</string> <string name="btn_no_date">Żaden</string>
<string name="btn_okay">Ok</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_search">Wyszukaj</string>
<string name="btn_export_to_server">Wyślij do serwera kluczy</string> <string name="btn_export_to_server">Wyślij do serwera kluczy</string>
<string name="btn_next">Dalej</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_from_qr_code">Zaimportuj z kodu QR</string>
<string name="menu_import">Import</string> <string name="menu_import">Import</string>
<string name="menu_import_from_nfc">Zaimportuj przy użyciu NFC</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 prywatne klucze</string>
<string name="menu_export_secret_keys">Eksportuj wszystkie klucze prywatne</string>
<string name="menu_export_key">Eksportuj do pliku</string> <string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string> <string name="menu_delete_key">Usuń klucz</string>
<string name="menu_create_key">Stwórz klucz</string> <string name="menu_create_key">Stwórz klucz</string>
@ -129,8 +126,6 @@
<string name="label_name">Imię</string> <string name="label_name">Imię</string>
<string name="label_comment">Komentarz</string> <string name="label_comment">Komentarz</string>
<string name="label_email">Adres email</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_send_key">Wyślij klucz do serwera kluczy po certyfikacji</string>
<string name="label_fingerprint">Odcisk</string> <string name="label_fingerprint">Odcisk</string>
<string name="select_keys_button_default">Wybierz</string> <string name="select_keys_button_default">Wybierz</string>
@ -163,10 +158,7 @@
<string name="fingerprint">Odcisk:</string> <string name="fingerprint">Odcisk:</string>
<string name="secret_key">Klucz prywatny:</string> <string name="secret_key">Klucz prywatny:</string>
<!--choice--> <!--choice-->
<string name="choice_none">Żaden</string> <string name="choice_none">Brak</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_15secs">15 sekund</string> <string name="choice_15secs">15 sekund</string>
<string name="choice_1min">1 minuta</string> <string name="choice_1min">1 minuta</string>
<string name="choice_3mins">3 minuty</string> <string name="choice_3mins">3 minuty</string>
@ -186,21 +178,18 @@
<string name="warning">Ostrzeżenie</string> <string name="warning">Ostrzeżenie</string>
<string name="error">Błąd</string> <string name="error">Błąd</string>
<string name="error_message">Błąd: %s</string> <string name="error_message">Błąd: %s</string>
<!--key flags-->
<!--sentences--> <!--sentences-->
<string name="wrong_passphrase">Nieprawidłowe hasło.</string> <string name="wrong_passphrase">Nieprawidłowe hasło.</string>
<string name="using_clipboard_content">Użycie zawartości schowka.</string> <string name="using_clipboard_content">Użycie zawartości schowka.</string>
<string name="set_a_passphrase">Najpierw ustaw hasło.</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="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="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_symmetric_encryption">Szyfrowanie symetryczne.</string>
<string name="passphrase_for">Podaj hasło dla \'%s\'</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_confirmation">Czy jesteś pewien że chcesz usunąć\n%s?</string>
<string name="file_delete_successful">Usunięto pomyślnie.</string> <string name="file_delete_successful">Usunięto pomyślnie.</string>
<string name="no_file_selected">Najpierw wskaż plik.</string> <string name="no_file_selected">Najpierw wskaż plik.</string>
<string name="decryption_successful">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="enter_passphrase_twice">Podaj hasło dwukrotnie.</string>
<string name="select_encryption_key">Wybierz co najmniej jeden klucz szyfrujący.</string> <string name="select_encryption_key">Wybierz co najmniej jeden klucz szyfrujący.</string>
<string name="select_encryption_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string> <string name="select_encryption_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string>
@ -398,13 +387,16 @@
<string name="api_settings_hide_advanced">Ukryj zaawansowane ustawienia</string> <string name="api_settings_hide_advanced">Ukryj zaawansowane ustawienia</string>
<string name="api_settings_no_key">Nie wybrano klucza</string> <string name="api_settings_no_key">Nie wybrano klucza</string>
<string name="api_settings_select_key">Wybierz klucz</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_save">Zapisz</string>
<string name="api_settings_cancel">Anuluj</string> <string name="api_settings_cancel">Anuluj</string>
<string name="api_settings_revoke">Odwołaj dostęp</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_name">Nazwa paczki</string>
<string name="api_settings_package_signature">Skrót SHA-256 podpisu 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">Konta</string>
<string name="api_settings_accounts_empty">Nie przypisano żadnych kont do tej aplikacji</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_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_allow">Zezwól na dostęp</string>
<string name="api_register_disallow">Odmów dostępu</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_main">Informacje</string>
<string name="key_view_tab_certs">Certyfikaty</string> <string name="key_view_tab_certs">Certyfikaty</string>
<!--Navigation Drawer--> <!--Navigation Drawer-->
<string name="nav_contacts">Kontakty</string> <string name="nav_import">Importuj klucze</string>
<string name="nav_encrypt">Zaszyfruj</string>
<string name="nav_decrypt">Deszyfruj</string>
<string name="nav_import">importuj klucze</string>
<string name="nav_secret_keys">Moje klucze</string> <string name="nav_secret_keys">Moje klucze</string>
<string name="nav_apps">Zarejestrowane aplikacje</string> <string name="nav_apps">Zarejestrowane aplikacje</string>
<string name="drawer_open">Otwórz panel nawigacji</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="section_uids_to_sign">Identyfikator użytkownika do podpisu</string>
<string name="progress_re_adding_certs">Ponowne stosowanie certyfikatów</string> <string name="progress_re_adding_certs">Ponowne stosowanie certyfikatów</string>
<!--hints--> <!--hints-->
<string name="encrypt_content_edit_text_hint">Wpisz tutaj wiadomość do zaszyfrowania...</string>
</resources> </resources>

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