mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-06 17:25:05 -05:00
Merge branch 'master' into certs
Conflicts: OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
This commit is contained in:
commit
a73e91c49c
5
.gitignore
vendored
5
.gitignore
vendored
@ -31,3 +31,8 @@ pom.xml.*
|
||||
|
||||
#OS Specific
|
||||
[Tt]humbs.db
|
||||
|
||||
|
||||
#Lint output
|
||||
OpenPGP-Keychain/lint-report.html
|
||||
OpenPGP-Keychain/lint-report_files/*
|
@ -3,7 +3,7 @@ jdk: oraclejdk7
|
||||
before_install:
|
||||
# Install base Android SDK
|
||||
- sudo apt-get update -qq
|
||||
- if [ `uname -m` = x86_64 ]; then sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs; fi
|
||||
- if [ `uname -m` = x86_64 ]; then sudo apt-get install -qq --force-yes libgd2-xpm lib32z1 lib32stdc++6; fi
|
||||
- wget http://dl.google.com/android/android-sdk_r22.3-linux.tgz
|
||||
- tar xzf android-sdk_r22.3-linux.tgz
|
||||
- export ANDROID_HOME=$PWD/android-sdk-linux
|
||||
|
@ -57,5 +57,7 @@ android {
|
||||
// Do not abort build if lint finds errors
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
htmlReport true
|
||||
htmlOutput file("lint-report.html")
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
public final class Constants {
|
||||
|
||||
public static final boolean DEBUG = BuildConfig.DEBUG;
|
||||
@ -40,14 +40,14 @@ public final class Constants {
|
||||
|
||||
public static final String INTENT_PREFIX = PACKAGE_NAME + ".action.";
|
||||
|
||||
public static final class path {
|
||||
public static final class Path {
|
||||
public static final String APP_DIR = Environment.getExternalStorageDirectory()
|
||||
+ "/OpenPGP-Keychain";
|
||||
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 class pref {
|
||||
public static final class Pref {
|
||||
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm";
|
||||
public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm";
|
||||
public static final String DEFAULT_ASCII_ARMOUR = "defaultAsciiArmour";
|
||||
@ -59,7 +59,7 @@ public final class Constants {
|
||||
public static final String KEY_SERVERS = "keyServers";
|
||||
}
|
||||
|
||||
public static final class defaults {
|
||||
public static final class Defaults {
|
||||
public static final String KEY_SERVERS = "pool.sks-keyservers.net, subkeys.pgp.net, pgp.mit.edu";
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class KeychainApplication extends Application {
|
||||
|
||||
// Create APG directory on sdcard if not existing
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
File dir = new File(Constants.path.APP_DIR);
|
||||
File dir = new File(Constants.Path.APP_DIR);
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
// ignore this for now, it's not crucial
|
||||
// that the directory doesn't exist at this point
|
||||
|
@ -37,7 +37,8 @@ import android.os.Handler;
|
||||
* </code>
|
||||
*/
|
||||
public class DialogFragmentWorkaround {
|
||||
public static final SDKLevel17Interface INTERFACE = ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) ? new SDKLevel17Impl()
|
||||
public static final SDKLevel17Interface INTERFACE =
|
||||
((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) ? new SDKLevel17Impl()
|
||||
: new SDKLevelPriorLevel17Impl());
|
||||
|
||||
private static final int RUNNABLE_DELAY = 300;
|
||||
|
@ -17,18 +17,17 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.helper;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class ActionBarHelper {
|
||||
|
||||
@ -63,9 +62,9 @@ public class ActionBarHelper {
|
||||
* @param secondDrawableId
|
||||
* @param secondOnClickListener
|
||||
*/
|
||||
public static void setTwoButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
|
||||
OnClickListener firstOnClickListener, int secondText, int secondDrawableId,
|
||||
OnClickListener secondOnClickListener) {
|
||||
public static void setTwoButtonView(ActionBar actionBar,
|
||||
int firstText, int firstDrawableId, OnClickListener firstOnClickListener,
|
||||
int secondText, int secondDrawableId, OnClickListener secondOnClickListener) {
|
||||
|
||||
// Inflate the custom action bar view
|
||||
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
|
||||
|
@ -16,6 +16,16 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.helper;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -26,25 +36,15 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ExportHelper {
|
||||
protected FileDialogFragment mFileDialog;
|
||||
protected String mExportFilename;
|
||||
|
||||
ActionBarActivity activity;
|
||||
ActionBarActivity mActivity;
|
||||
|
||||
public ExportHelper(ActionBarActivity activity) {
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.mActivity = activity;
|
||||
}
|
||||
|
||||
public void deleteKey(Uri dataUri, final int keyType, Handler deleteHandler) {
|
||||
@ -56,7 +56,7 @@ public class ExportHelper {
|
||||
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
|
||||
new long[]{keyRingRowId}, keyType);
|
||||
|
||||
deleteKeyDialog.show(activity.getSupportFragmentManager(), "deleteKeyDialog");
|
||||
deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,23 +87,23 @@ public class ExportHelper {
|
||||
String title = null;
|
||||
if (rowIds == null) {
|
||||
// export all keys
|
||||
title = activity.getString(R.string.title_export_keys);
|
||||
title = mActivity.getString(R.string.title_export_keys);
|
||||
} else {
|
||||
// export only key specified at data uri
|
||||
title = activity.getString(R.string.title_export_key);
|
||||
title = mActivity.getString(R.string.title_export_key);
|
||||
}
|
||||
|
||||
String message = null;
|
||||
if (keyType == Id.type.public_key) {
|
||||
message = activity.getString(R.string.specify_file_to_export_to);
|
||||
message = mActivity.getString(R.string.specify_file_to_export_to);
|
||||
} else {
|
||||
message = activity.getString(R.string.specify_file_to_export_secret_keys_to);
|
||||
message = mActivity.getString(R.string.specify_file_to_export_secret_keys_to);
|
||||
}
|
||||
|
||||
mFileDialog = FileDialogFragment.newInstance(messenger, title, message,
|
||||
exportFilename, null);
|
||||
|
||||
mFileDialog.show(activity.getSupportFragmentManager(), "fileDialog");
|
||||
mFileDialog.show(mActivity.getSupportFragmentManager(), "fileDialog");
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -115,7 +115,7 @@ public class ExportHelper {
|
||||
Log.d(Constants.TAG, "exportKeys started");
|
||||
|
||||
// Send all information needed to service to export key in other thread
|
||||
Intent intent = new Intent(activity, KeychainIntentService.class);
|
||||
final Intent intent = new Intent(mActivity, KeychainIntentService.class);
|
||||
|
||||
intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING);
|
||||
|
||||
@ -134,8 +134,16 @@ public class ExportHelper {
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
|
||||
// Message is received after exporting is done in ApgService
|
||||
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(activity,
|
||||
activity.getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) {
|
||||
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(mActivity,
|
||||
mActivity.getString(R.string.progress_exporting),
|
||||
ProgressDialog.STYLE_HORIZONTAL,
|
||||
true,
|
||||
new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialogInterface) {
|
||||
mActivity.stopService(intent);
|
||||
}
|
||||
}) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard ApgHandler first
|
||||
super.handleMessage(message);
|
||||
@ -147,13 +155,13 @@ public class ExportHelper {
|
||||
int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT);
|
||||
String toastMessage;
|
||||
if (exported == 1) {
|
||||
toastMessage = activity.getString(R.string.key_exported);
|
||||
toastMessage = mActivity.getString(R.string.key_exported);
|
||||
} else if (exported > 0) {
|
||||
toastMessage = activity.getString(R.string.keys_exported, exported);
|
||||
toastMessage = mActivity.getString(R.string.keys_exported, exported);
|
||||
} else {
|
||||
toastMessage = activity.getString(R.string.no_keys_exported);
|
||||
toastMessage = mActivity.getString(R.string.no_keys_exported);
|
||||
}
|
||||
Toast.makeText(activity, toastMessage, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(mActivity, toastMessage, Toast.LENGTH_SHORT).show();
|
||||
|
||||
}
|
||||
}
|
||||
@ -164,10 +172,10 @@ public class ExportHelper {
|
||||
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
||||
|
||||
// show progress dialog
|
||||
exportHandler.showProgressDialog(activity);
|
||||
exportHandler.showProgressDialog(mActivity);
|
||||
|
||||
// start service with intent
|
||||
activity.startService(intent);
|
||||
mActivity.startService(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.helper;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
@ -30,6 +26,9 @@ import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class FileHelper {
|
||||
|
||||
@ -54,12 +53,9 @@ public class FileHelper {
|
||||
* installed.
|
||||
*
|
||||
* @param activity
|
||||
* @param filename
|
||||
* default selected file, not supported by all file managers
|
||||
* @param mimeType
|
||||
* can be text/plain for example
|
||||
* @param requestCode
|
||||
* requestCode used to identify the result coming back from file manager to
|
||||
* @param filename default selected file, not supported by all file managers
|
||||
* @param mimeType can be text/plain for example
|
||||
* @param requestCode requestCode used to identify the result coming back from file manager to
|
||||
* onActivityResult() in your activity
|
||||
*/
|
||||
public static void openFile(Activity activity, String filename, String mimeType, int requestCode) {
|
||||
@ -97,14 +93,13 @@ public class FileHelper {
|
||||
|
||||
/**
|
||||
* Get a file path from a Uri.
|
||||
*
|
||||
* <p/>
|
||||
* from https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/
|
||||
* afilechooser/utils/FileUtils.java
|
||||
*
|
||||
* @param context
|
||||
* @param uri
|
||||
* @return
|
||||
*
|
||||
* @author paulburke
|
||||
*/
|
||||
public static String getPath(Context context, Uri uri) {
|
||||
@ -120,16 +115,14 @@ public class FileHelper {
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
int column_index = cursor.getColumnIndexOrThrow("_data");
|
||||
int columnIndex = cursor.getColumnIndexOrThrow("_data");
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getString(column_index);
|
||||
return cursor.getString(columnIndex);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Eat it
|
||||
}
|
||||
}
|
||||
|
||||
else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
return uri.getPath();
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,15 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.helper;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.os.Bundle;
|
||||
import java.security.DigestException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class OtherHelper {
|
||||
|
||||
@ -58,4 +60,24 @@ public class OtherHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given bytes to a unique RGB color using SHA1 algorithm
|
||||
*
|
||||
* @param bytes
|
||||
* @return an integer array containing 3 numeric color representations (Red, Green, Black)
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws DigestException
|
||||
*/
|
||||
public static int[] getRgbForData(byte[] bytes) throws NoSuchAlgorithmException, DigestException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
|
||||
md.update(bytes);
|
||||
byte[] digest = md.digest();
|
||||
|
||||
int[] result = {((int) digest[0] + 256) % 256,
|
||||
((int) digest[1] + 256) % 256,
|
||||
((int) digest[2] + 256) % 256};
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,14 +17,13 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
@ -38,8 +37,8 @@ public class Preferences {
|
||||
return getPreferences(context, false);
|
||||
}
|
||||
|
||||
public static synchronized Preferences getPreferences(Context context, boolean force_new) {
|
||||
if (mPreferences == null || force_new) {
|
||||
public static synchronized Preferences getPreferences(Context context, boolean forceNew) {
|
||||
if (mPreferences == null || forceNew) {
|
||||
mPreferences = new Preferences(context);
|
||||
}
|
||||
return mPreferences;
|
||||
@ -50,17 +49,17 @@ public class Preferences {
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return mSharedPreferences.getString(Constants.pref.LANGUAGE, "");
|
||||
return mSharedPreferences.getString(Constants.Pref.LANGUAGE, "");
|
||||
}
|
||||
|
||||
public void setLanguage(String value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putString(Constants.pref.LANGUAGE, value);
|
||||
editor.putString(Constants.Pref.LANGUAGE, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public long getPassPhraseCacheTtl() {
|
||||
int ttl = mSharedPreferences.getInt(Constants.pref.PASS_PHRASE_CACHE_TTL, 180);
|
||||
int ttl = mSharedPreferences.getInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, 180);
|
||||
// fix the value if it was set to "never" in previous versions, which currently is not
|
||||
// supported
|
||||
if (ttl == 0) {
|
||||
@ -71,77 +70,77 @@ public class Preferences {
|
||||
|
||||
public void setPassPhraseCacheTtl(int value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putInt(Constants.pref.PASS_PHRASE_CACHE_TTL, value);
|
||||
editor.putInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public int getDefaultEncryptionAlgorithm() {
|
||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM,
|
||||
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM,
|
||||
PGPEncryptedData.AES_256);
|
||||
}
|
||||
|
||||
public void setDefaultEncryptionAlgorithm(int value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putInt(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM, value);
|
||||
editor.putInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public int getDefaultHashAlgorithm() {
|
||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_HASH_ALGORITHM,
|
||||
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM,
|
||||
HashAlgorithmTags.SHA512);
|
||||
}
|
||||
|
||||
public void setDefaultHashAlgorithm(int value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putInt(Constants.pref.DEFAULT_HASH_ALGORITHM, value);
|
||||
editor.putInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public int getDefaultMessageCompression() {
|
||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_MESSAGE_COMPRESSION,
|
||||
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION,
|
||||
Id.choice.compression.zlib);
|
||||
}
|
||||
|
||||
public void setDefaultMessageCompression(int value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putInt(Constants.pref.DEFAULT_MESSAGE_COMPRESSION, value);
|
||||
editor.putInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public int getDefaultFileCompression() {
|
||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_FILE_COMPRESSION,
|
||||
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION,
|
||||
Id.choice.compression.none);
|
||||
}
|
||||
|
||||
public void setDefaultFileCompression(int value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putInt(Constants.pref.DEFAULT_FILE_COMPRESSION, value);
|
||||
editor.putInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public boolean getDefaultAsciiArmour() {
|
||||
return mSharedPreferences.getBoolean(Constants.pref.DEFAULT_ASCII_ARMOUR, false);
|
||||
return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, false);
|
||||
}
|
||||
|
||||
public void setDefaultAsciiArmour(boolean value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putBoolean(Constants.pref.DEFAULT_ASCII_ARMOUR, value);
|
||||
editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public boolean getForceV3Signatures() {
|
||||
return mSharedPreferences.getBoolean(Constants.pref.FORCE_V3_SIGNATURES, false);
|
||||
return mSharedPreferences.getBoolean(Constants.Pref.FORCE_V3_SIGNATURES, false);
|
||||
}
|
||||
|
||||
public void setForceV3Signatures(boolean value) {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putBoolean(Constants.pref.FORCE_V3_SIGNATURES, value);
|
||||
editor.putBoolean(Constants.Pref.FORCE_V3_SIGNATURES, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public String[] getKeyServers() {
|
||||
String rawData = mSharedPreferences.getString(Constants.pref.KEY_SERVERS,
|
||||
Constants.defaults.KEY_SERVERS);
|
||||
String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS,
|
||||
Constants.Defaults.KEY_SERVERS);
|
||||
Vector<String> servers = new Vector<String>();
|
||||
String chunks[] = rawData.split(",");
|
||||
for (String c : chunks) {
|
||||
@ -166,7 +165,7 @@ public class Preferences {
|
||||
}
|
||||
rawData += tmp;
|
||||
}
|
||||
editor.putString(Constants.pref.KEY_SERVERS, rawData);
|
||||
editor.putString(Constants.Pref.KEY_SERVERS, rawData);
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
@ -31,6 +26,11 @@ import org.spongycastle.openpgp.PGPSignatureList;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
public class PgpConversionHelper {
|
||||
|
||||
@ -75,7 +75,7 @@ public class PgpConversionHelper {
|
||||
|
||||
/**
|
||||
* Convert from byte[] to PGPSecretKey
|
||||
*
|
||||
* <p/>
|
||||
* Singles keys are encoded as keyRings with one single key in it by Bouncy Castle
|
||||
*
|
||||
* @param keyBytes
|
||||
|
@ -18,38 +18,16 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
import org.spongycastle.bcpg.ArmoredInputStream;
|
||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||
import org.spongycastle.openpgp.PGPCompressedData;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.spongycastle.openpgp.PGPEncryptedDataList;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPLiteralData;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPOnePassSignature;
|
||||
import org.spongycastle.openpgp.PGPOnePassSignatureList;
|
||||
import org.spongycastle.openpgp.PGPPBEEncryptedData;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSignature;
|
||||
import org.spongycastle.openpgp.PGPSignatureList;
|
||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.spongycastle.openpgp.*;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
||||
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.*;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
@ -59,12 +37,7 @@ import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Iterator;
|
||||
|
||||
@ -72,57 +45,57 @@ import java.util.Iterator;
|
||||
* This class uses a Builder pattern!
|
||||
*/
|
||||
public class PgpDecryptVerify {
|
||||
private Context context;
|
||||
private InputData data;
|
||||
private OutputStream outStream;
|
||||
private Context mContext;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
private ProgressDialogUpdater progressDialogUpdater;
|
||||
private boolean assumeSymmetric;
|
||||
private String passphrase;
|
||||
private long enforcedKeyId;
|
||||
private ProgressDialogUpdater mProgressDialogUpdater;
|
||||
private boolean mAssumeSymmetric;
|
||||
private String mPassphrase;
|
||||
private long mEnforcedKeyId;
|
||||
|
||||
private PgpDecryptVerify(Builder builder) {
|
||||
// private Constructor can only be called from Builder
|
||||
this.context = builder.context;
|
||||
this.data = builder.data;
|
||||
this.outStream = builder.outStream;
|
||||
this.mContext = builder.mContext;
|
||||
this.mData = builder.mData;
|
||||
this.mOutStream = builder.mOutStream;
|
||||
|
||||
this.progressDialogUpdater = builder.progressDialogUpdater;
|
||||
this.assumeSymmetric = builder.assumeSymmetric;
|
||||
this.passphrase = builder.passphrase;
|
||||
this.enforcedKeyId = builder.enforcedKeyId;
|
||||
this.mProgressDialogUpdater = builder.mProgressDialogUpdater;
|
||||
this.mAssumeSymmetric = builder.mAssumeSymmetric;
|
||||
this.mPassphrase = builder.mPassphrase;
|
||||
this.mEnforcedKeyId = builder.mEnforcedKeyId;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
// mandatory parameter
|
||||
private Context context;
|
||||
private InputData data;
|
||||
private OutputStream outStream;
|
||||
private Context mContext;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
// optional
|
||||
private ProgressDialogUpdater progressDialogUpdater = null;
|
||||
private boolean assumeSymmetric = false;
|
||||
private String passphrase = "";
|
||||
private long enforcedKeyId = 0;
|
||||
private ProgressDialogUpdater mProgressDialogUpdater = null;
|
||||
private boolean mAssumeSymmetric = false;
|
||||
private String mPassphrase = "";
|
||||
private long mEnforcedKeyId = 0;
|
||||
|
||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
||||
this.context = context;
|
||||
this.data = data;
|
||||
this.outStream = outStream;
|
||||
this.mContext = context;
|
||||
this.mData = data;
|
||||
this.mOutStream = outStream;
|
||||
}
|
||||
|
||||
public Builder progressDialogUpdater(ProgressDialogUpdater progressDialogUpdater) {
|
||||
this.progressDialogUpdater = progressDialogUpdater;
|
||||
this.mProgressDialogUpdater = progressDialogUpdater;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder assumeSymmetric(boolean assumeSymmetric) {
|
||||
this.assumeSymmetric = assumeSymmetric;
|
||||
this.mAssumeSymmetric = assumeSymmetric;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder passphrase(String passphrase) {
|
||||
this.passphrase = passphrase;
|
||||
this.mPassphrase = passphrase;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -134,7 +107,7 @@ public class PgpDecryptVerify {
|
||||
* @return
|
||||
*/
|
||||
public Builder enforcedKeyId(long enforcedKeyId) {
|
||||
this.enforcedKeyId = enforcedKeyId;
|
||||
this.mEnforcedKeyId = enforcedKeyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -144,14 +117,14 @@ public class PgpDecryptVerify {
|
||||
}
|
||||
|
||||
public void updateProgress(int message, int current, int total) {
|
||||
if (progressDialogUpdater != null) {
|
||||
progressDialogUpdater.setProgress(message, current, total);
|
||||
if (mProgressDialogUpdater != null) {
|
||||
mProgressDialogUpdater.setProgress(message, current, total);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProgress(int current, int total) {
|
||||
if (progressDialogUpdater != null) {
|
||||
progressDialogUpdater.setProgress(current, total);
|
||||
if (mProgressDialogUpdater != null) {
|
||||
mProgressDialogUpdater.setProgress(current, total);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +169,7 @@ public class PgpDecryptVerify {
|
||||
public PgpDecryptVerifyResult execute()
|
||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
||||
// automatically works with ascii armor input and binary
|
||||
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
|
||||
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
|
||||
if (in instanceof ArmoredInputStream) {
|
||||
ArmoredInputStream aIn = (ArmoredInputStream) in;
|
||||
// it is ascii armored
|
||||
@ -240,7 +213,7 @@ public class PgpDecryptVerify {
|
||||
}
|
||||
|
||||
if (enc == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_invalid_data));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_invalid_data));
|
||||
}
|
||||
|
||||
InputStream clear;
|
||||
@ -250,7 +223,7 @@ public class PgpDecryptVerify {
|
||||
|
||||
// TODO: currently we always only look at the first known key or symmetric encryption,
|
||||
// there might be more...
|
||||
if (assumeSymmetric) {
|
||||
if (mAssumeSymmetric) {
|
||||
PGPPBEEncryptedData pbe = null;
|
||||
Iterator<?> it = enc.getEncryptedDataObjects();
|
||||
// find secret key
|
||||
@ -264,7 +237,7 @@ public class PgpDecryptVerify {
|
||||
|
||||
if (pbe == null) {
|
||||
throw new PgpGeneralException(
|
||||
context.getString(R.string.error_no_symmetric_encryption_packet));
|
||||
mContext.getString(R.string.error_no_symmetric_encryption_packet));
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
||||
@ -273,7 +246,7 @@ public class PgpDecryptVerify {
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
|
||||
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
|
||||
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
passphrase.toCharArray());
|
||||
mPassphrase.toCharArray());
|
||||
|
||||
clear = pbe.getDataStream(decryptorFactory);
|
||||
|
||||
@ -290,33 +263,37 @@ public class PgpDecryptVerify {
|
||||
Object obj = it.next();
|
||||
if (obj instanceof PGPPublicKeyEncryptedData) {
|
||||
PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
|
||||
secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, encData.getKeyID());
|
||||
secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID());
|
||||
if (secretKey != null) {
|
||||
// secret key exists in database
|
||||
|
||||
// allow only a specific key for decryption?
|
||||
if (enforcedKeyId != 0) {
|
||||
if (mEnforcedKeyId != 0) {
|
||||
// TODO: improve this code! get master key directly!
|
||||
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, encData.getKeyID());
|
||||
PGPSecretKeyRing secretKeyRing =
|
||||
ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, encData.getKeyID());
|
||||
long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID();
|
||||
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
|
||||
Log.d(Constants.TAG, "enforcedKeyId: " + enforcedKeyId);
|
||||
Log.d(Constants.TAG, "enforcedKeyId: " + mEnforcedKeyId);
|
||||
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
|
||||
|
||||
if (enforcedKeyId != masterKeyId) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found));
|
||||
if (mEnforcedKeyId != masterKeyId) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_no_secret_key_found));
|
||||
}
|
||||
}
|
||||
|
||||
pbe = encData;
|
||||
|
||||
// if no passphrase was explicitly set try to get it from the cache service
|
||||
if (passphrase == null) {
|
||||
if (mPassphrase == null) {
|
||||
// returns "" if key has no passphrase
|
||||
passphrase = PassphraseCacheService.getCachedPassphrase(context, encData.getKeyID());
|
||||
mPassphrase =
|
||||
PassphraseCacheService.getCachedPassphrase(mContext, encData.getKeyID());
|
||||
|
||||
// if passphrase was not cached, return here indicating that a passphrase is missing!
|
||||
if (passphrase == null) {
|
||||
// if passphrase was not cached, return here
|
||||
// indicating that a passphrase is missing!
|
||||
if (mPassphrase == null) {
|
||||
returnData.setKeyPassphraseNeeded(true);
|
||||
return returnData;
|
||||
}
|
||||
@ -330,7 +307,7 @@ public class PgpDecryptVerify {
|
||||
}
|
||||
|
||||
if (secretKey == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
||||
}
|
||||
|
||||
currentProgress += 5;
|
||||
@ -339,14 +316,14 @@ public class PgpDecryptVerify {
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
passphrase.toCharArray());
|
||||
mPassphrase.toCharArray());
|
||||
privateKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||
} catch (PGPException e) {
|
||||
throw new PGPException(context.getString(R.string.error_wrong_passphrase));
|
||||
throw new PGPException(mContext.getString(R.string.error_wrong_passphrase));
|
||||
}
|
||||
if (privateKey == null) {
|
||||
throw new PgpGeneralException(
|
||||
context.getString(R.string.error_could_not_extract_private_key));
|
||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
||||
}
|
||||
currentProgress += 5;
|
||||
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
||||
@ -386,7 +363,7 @@ public class PgpDecryptVerify {
|
||||
for (int i = 0; i < sigList.size(); ++i) {
|
||||
signature = sigList.get(i);
|
||||
signatureKey = ProviderHelper
|
||||
.getPGPPublicKeyByKeyId(context, signature.getKeyID());
|
||||
.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
|
||||
if (signatureKeyId == 0) {
|
||||
signatureKeyId = signature.getKeyID();
|
||||
}
|
||||
@ -397,7 +374,7 @@ public class PgpDecryptVerify {
|
||||
signatureKeyId = signature.getKeyID();
|
||||
String userId = null;
|
||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
|
||||
context, signatureKeyId);
|
||||
mContext, signatureKeyId);
|
||||
if (signKeyRing != null) {
|
||||
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
||||
}
|
||||
@ -409,7 +386,8 @@ public class PgpDecryptVerify {
|
||||
signatureResult.setKeyId(signatureKeyId);
|
||||
|
||||
if (signature != null) {
|
||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
|
||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||
new JcaPGPContentVerifierBuilderProvider()
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
|
||||
signature.init(contentVerifierBuilderProvider, signatureKey);
|
||||
@ -444,9 +422,9 @@ public class PgpDecryptVerify {
|
||||
int n;
|
||||
// TODO: progress calculation is broken here! Try to rework it based on commented code!
|
||||
// int progress = 0;
|
||||
long startPos = data.getStreamPosition();
|
||||
long startPos = mData.getStreamPosition();
|
||||
while ((n = dataIn.read(buffer)) > 0) {
|
||||
outStream.write(buffer, 0, n);
|
||||
mOutStream.write(buffer, 0, n);
|
||||
// progress += n;
|
||||
if (signature != null) {
|
||||
try {
|
||||
@ -460,11 +438,11 @@ public class PgpDecryptVerify {
|
||||
// unknown size, but try to at least have a moving, slowing down progress bar
|
||||
// currentProgress = startProgress + (endProgress - startProgress) * progress
|
||||
// / (progress + 100000);
|
||||
if (data.getSize() - startPos == 0) {
|
||||
if (mData.getSize() - startPos == 0) {
|
||||
currentProgress = endProgress;
|
||||
} else {
|
||||
currentProgress = (int) (startProgress + (endProgress - startProgress)
|
||||
* (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
|
||||
* (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos));
|
||||
}
|
||||
updateProgress(currentProgress, 100);
|
||||
}
|
||||
@ -480,7 +458,7 @@ public class PgpDecryptVerify {
|
||||
signatureResult.setSignatureOnly(false);
|
||||
|
||||
//Now check binding signatures
|
||||
boolean validKeyBinding = verifyKeyBinding(context, messageSignature, signatureKey);
|
||||
boolean validKeyBinding = verifyKeyBinding(mContext, messageSignature, signatureKey);
|
||||
boolean validSignature = signature.verify(messageSignature);
|
||||
|
||||
// TODO: implement CERTIFIED!
|
||||
@ -499,7 +477,7 @@ public class PgpDecryptVerify {
|
||||
} else {
|
||||
// failed
|
||||
Log.d(Constants.TAG, "Integrity verification: failed!");
|
||||
throw new PgpGeneralException(context.getString(R.string.error_integrity_check_failed));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_integrity_check_failed));
|
||||
}
|
||||
} else {
|
||||
// no integrity check
|
||||
@ -555,21 +533,21 @@ public class PgpDecryptVerify {
|
||||
out.close();
|
||||
|
||||
byte[] clearText = out.toByteArray();
|
||||
outStream.write(clearText);
|
||||
mOutStream.write(clearText);
|
||||
|
||||
updateProgress(R.string.progress_processing_signature, 60, 100);
|
||||
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
|
||||
|
||||
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
||||
if (sigList == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_corrupt_data));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_corrupt_data));
|
||||
}
|
||||
PGPSignature signature = null;
|
||||
long signatureKeyId = 0;
|
||||
PGPPublicKey signatureKey = null;
|
||||
for (int i = 0; i < sigList.size(); ++i) {
|
||||
signature = sigList.get(i);
|
||||
signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(context, signature.getKeyID());
|
||||
signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
|
||||
if (signatureKeyId == 0) {
|
||||
signatureKeyId = signature.getKeyID();
|
||||
}
|
||||
@ -579,7 +557,7 @@ public class PgpDecryptVerify {
|
||||
} else {
|
||||
signatureKeyId = signature.getKeyID();
|
||||
String userId = null;
|
||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
|
||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext,
|
||||
signatureKeyId);
|
||||
if (signKeyRing != null) {
|
||||
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
||||
@ -623,7 +601,7 @@ public class PgpDecryptVerify {
|
||||
}
|
||||
|
||||
//Now check binding signatures
|
||||
boolean validKeyBinding = verifyKeyBinding(context, signature, signatureKey);
|
||||
boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey);
|
||||
boolean validSignature = signature.verify();
|
||||
|
||||
if (validSignature & validKeyBinding) {
|
||||
@ -638,7 +616,8 @@ public class PgpDecryptVerify {
|
||||
return returnData;
|
||||
}
|
||||
|
||||
private static boolean verifyKeyBinding(Context context, PGPSignature signature, PGPPublicKey signatureKey) {
|
||||
private static boolean verifyKeyBinding(Context context,
|
||||
PGPSignature signature, PGPPublicKey signatureKey) {
|
||||
long signatureKeyId = signature.getKeyID();
|
||||
boolean validKeyBinding = false;
|
||||
|
||||
@ -673,7 +652,8 @@ public class PgpDecryptVerify {
|
||||
//about keys without subkey signing. Can't get it to import a slightly broken one
|
||||
//either, so we will err on bad subkey binding here.
|
||||
PGPSignature sig = itr.next();
|
||||
if (sig.getKeyID() == masterPublicKey.getKeyID() && sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) {
|
||||
if (sig.getKeyID() == masterPublicKey.getKeyID() &&
|
||||
sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) {
|
||||
//check and if ok, check primary key binding.
|
||||
try {
|
||||
sig.init(contentVerifierBuilderProvider, masterPublicKey);
|
||||
@ -684,24 +664,27 @@ public class PgpDecryptVerify {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (validTempSubkeyBinding)
|
||||
if (validTempSubkeyBinding) {
|
||||
validSubkeyBinding = true;
|
||||
}
|
||||
if (validTempSubkeyBinding) {
|
||||
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(),
|
||||
masterPublicKey, signingPublicKey);
|
||||
if (validPrimaryKeyBinding)
|
||||
if (validPrimaryKeyBinding) {
|
||||
break;
|
||||
}
|
||||
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(),
|
||||
masterPublicKey, signingPublicKey);
|
||||
if (validPrimaryKeyBinding)
|
||||
if (validPrimaryKeyBinding) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (validSubkeyBinding & validPrimaryKeyBinding);
|
||||
}
|
||||
|
||||
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector Pkts,
|
||||
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
|
||||
PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
|
||||
boolean validPrimaryKeyBinding = false;
|
||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||
@ -709,9 +692,9 @@ public class PgpDecryptVerify {
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureList eSigList;
|
||||
|
||||
if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
|
||||
if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
|
||||
try {
|
||||
eSigList = Pkts.getEmbeddedSignatures();
|
||||
eSigList = pkts.getEmbeddedSignatures();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} catch (PGPException e) {
|
||||
@ -723,8 +706,9 @@ public class PgpDecryptVerify {
|
||||
try {
|
||||
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
|
||||
validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey);
|
||||
if (validPrimaryKeyBinding)
|
||||
if (validPrimaryKeyBinding) {
|
||||
break;
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
continue;
|
||||
} catch (SignatureException e) {
|
||||
|
@ -19,36 +19,35 @@ package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
public class PgpDecryptVerifyResult implements Parcelable {
|
||||
boolean symmetricPassphraseNeeded;
|
||||
boolean keyPassphraseNeeded;
|
||||
OpenPgpSignatureResult signatureResult;
|
||||
boolean mSymmetricPassphraseNeeded;
|
||||
boolean mKeyPassphraseNeeded;
|
||||
OpenPgpSignatureResult mSignatureResult;
|
||||
|
||||
public boolean isSymmetricPassphraseNeeded() {
|
||||
return symmetricPassphraseNeeded;
|
||||
return mSymmetricPassphraseNeeded;
|
||||
}
|
||||
|
||||
public void setSymmetricPassphraseNeeded(boolean symmetricPassphraseNeeded) {
|
||||
this.symmetricPassphraseNeeded = symmetricPassphraseNeeded;
|
||||
this.mSymmetricPassphraseNeeded = symmetricPassphraseNeeded;
|
||||
}
|
||||
|
||||
public boolean isKeyPassphraseNeeded() {
|
||||
return keyPassphraseNeeded;
|
||||
return mKeyPassphraseNeeded;
|
||||
}
|
||||
|
||||
public void setKeyPassphraseNeeded(boolean keyPassphraseNeeded) {
|
||||
this.keyPassphraseNeeded = keyPassphraseNeeded;
|
||||
this.mKeyPassphraseNeeded = keyPassphraseNeeded;
|
||||
}
|
||||
|
||||
public OpenPgpSignatureResult getSignatureResult() {
|
||||
return signatureResult;
|
||||
return mSignatureResult;
|
||||
}
|
||||
|
||||
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
|
||||
this.signatureResult = signatureResult;
|
||||
this.mSignatureResult = signatureResult;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyResult() {
|
||||
@ -56,9 +55,9 @@ public class PgpDecryptVerifyResult implements Parcelable {
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) {
|
||||
this.symmetricPassphraseNeeded = b.symmetricPassphraseNeeded;
|
||||
this.keyPassphraseNeeded = b.keyPassphraseNeeded;
|
||||
this.signatureResult = b.signatureResult;
|
||||
this.mSymmetricPassphraseNeeded = b.mSymmetricPassphraseNeeded;
|
||||
this.mKeyPassphraseNeeded = b.mKeyPassphraseNeeded;
|
||||
this.mSignatureResult = b.mSignatureResult;
|
||||
}
|
||||
|
||||
|
||||
@ -67,17 +66,17 @@ public class PgpDecryptVerifyResult implements Parcelable {
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeByte((byte) (symmetricPassphraseNeeded ? 1 : 0));
|
||||
dest.writeByte((byte) (keyPassphraseNeeded ? 1 : 0));
|
||||
dest.writeParcelable(signatureResult, 0);
|
||||
dest.writeByte((byte) (mSymmetricPassphraseNeeded ? 1 : 0));
|
||||
dest.writeByte((byte) (mKeyPassphraseNeeded ? 1 : 0));
|
||||
dest.writeParcelable(mSignatureResult, 0);
|
||||
}
|
||||
|
||||
public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {
|
||||
public PgpDecryptVerifyResult createFromParcel(final Parcel source) {
|
||||
PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult();
|
||||
vr.symmetricPassphraseNeeded = source.readByte() == 1;
|
||||
vr.keyPassphraseNeeded = source.readByte() == 1;
|
||||
vr.signatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
||||
vr.mSymmetricPassphraseNeeded = source.readByte() == 1;
|
||||
vr.mKeyPassphraseNeeded = source.readByte() == 1;
|
||||
vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
||||
return vr;
|
||||
}
|
||||
|
||||
|
@ -17,22 +17,10 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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 android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import org.spongycastle.openpgp.*;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -42,21 +30,25 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PgpHelper {
|
||||
|
||||
public static Pattern PGP_MESSAGE = Pattern.compile(
|
||||
public static final Pattern PGP_MESSAGE = Pattern.compile(
|
||||
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
|
||||
|
||||
public static Pattern PGP_SIGNED_MESSAGE = Pattern
|
||||
public static final Pattern PGP_SIGNED_MESSAGE = Pattern
|
||||
.compile(
|
||||
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
public static 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-----).*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
@ -187,7 +179,7 @@ public class PgpHelper {
|
||||
|
||||
/**
|
||||
* Deletes file securely by overwriting it with random data before deleting it.
|
||||
*
|
||||
* <p/>
|
||||
* TODO: Does this really help on flash storage?
|
||||
*
|
||||
* @param context
|
||||
@ -206,8 +198,9 @@ public class PgpHelper {
|
||||
int pos = 0;
|
||||
String msg = context.getString(R.string.progress_deleting_securely, file.getName());
|
||||
while (pos < length) {
|
||||
if (progress != null)
|
||||
if (progress != null) {
|
||||
progress.setProgress(msg, (int) (100 * pos / length), 100);
|
||||
}
|
||||
random.nextBytes(data);
|
||||
raf.write(data);
|
||||
pos += data.length;
|
||||
|
@ -17,20 +17,11 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
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.*;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
@ -39,26 +30,36 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.*;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PgpImportExport {
|
||||
|
||||
private Context mContext;
|
||||
private ProgressDialogUpdater mProgress;
|
||||
|
||||
private KeychainServiceListener mKeychainServiceListener;
|
||||
|
||||
public PgpImportExport(Context context, ProgressDialogUpdater progress) {
|
||||
super();
|
||||
this.mContext = context;
|
||||
this.mProgress = progress;
|
||||
}
|
||||
|
||||
public PgpImportExport(Context context,
|
||||
ProgressDialogUpdater progress, KeychainServiceListener keychainListener) {
|
||||
super();
|
||||
this.mContext = context;
|
||||
this.mProgress = progress;
|
||||
this.mKeychainServiceListener = keychainListener;
|
||||
}
|
||||
|
||||
public void updateProgress(int message, int current, int total) {
|
||||
if (mProgress != null) {
|
||||
mProgress.setProgress(message, current, total);
|
||||
@ -96,8 +97,8 @@ public class PgpImportExport {
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
if (aos != null) aos.close();
|
||||
if (bos != null) bos.close();
|
||||
if (aos != null) { aos.close(); }
|
||||
if (bos != null) { bos.close(); }
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
@ -188,8 +189,10 @@ public class PgpImportExport {
|
||||
if (secretKeyRing != null) {
|
||||
secretKeyRing.encode(arOutStream);
|
||||
}
|
||||
// Else if it's a public key get the PGPPublicKeyRing
|
||||
// and encode that to the output
|
||||
if (mKeychainServiceListener.hasServiceStopped()) {
|
||||
arOutStream.close();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
updateProgress(i * 100 / rowIdsSize, 100);
|
||||
PGPPublicKeyRing publicKeyRing =
|
||||
@ -198,6 +201,11 @@ public class PgpImportExport {
|
||||
if (publicKeyRing != null) {
|
||||
publicKeyRing.encode(arOutStream);
|
||||
}
|
||||
|
||||
if (mKeychainServiceListener.hasServiceStopped()) {
|
||||
arOutStream.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
arOutStream.close();
|
||||
@ -245,8 +253,9 @@ public class PgpImportExport {
|
||||
}
|
||||
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
|
||||
}
|
||||
if (newPubRing != null)
|
||||
if (newPubRing != null) {
|
||||
ProviderHelper.saveKeyRing(mContext, newPubRing);
|
||||
}
|
||||
// TODO: remove status returns, use exceptions!
|
||||
status = Id.return_value.ok;
|
||||
}
|
||||
|
@ -17,21 +17,9 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.Context;
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
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.openpgp.*;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -39,7 +27,9 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.Context;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PgpKeyHelper {
|
||||
|
||||
|
@ -17,48 +17,20 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.SignatureException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import android.content.Context;
|
||||
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
||||
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.*;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
||||
import org.spongycastle.openpgp.operator.jcajce.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.spongycastle.openpgp.operator.jcajce.*;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -68,7 +40,13 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Primes;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import android.content.Context;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class PgpKeyOperation {
|
||||
private Context mContext;
|
||||
@ -119,7 +97,8 @@ public class PgpKeyOperation {
|
||||
|
||||
// TODO: key flags?
|
||||
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
|
||||
boolean isMasterKey) throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||
boolean isMasterKey)
|
||||
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||
PgpGeneralException, InvalidAlgorithmParameterException {
|
||||
|
||||
if (keySize < 512) {
|
||||
@ -237,8 +216,10 @@ public class PgpKeyOperation {
|
||||
updateProgress(R.string.progress_preparing_master_key, 10, 100);
|
||||
|
||||
int usageId = keysUsages.get(0);
|
||||
boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
boolean canSign =
|
||||
(usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
boolean canEncrypt =
|
||||
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
|
||||
String mainUserId = userIds.get(0);
|
||||
|
||||
@ -303,12 +284,16 @@ public class PgpKeyOperation {
|
||||
GregorianCalendar expiryDate = keysExpiryDates.get(0);
|
||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0)
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
long numDays =
|
||||
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
}
|
||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||
} else {
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
|
||||
//do this explicitly, although since we're rebuilding,
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||
//this happens anyway
|
||||
}
|
||||
|
||||
@ -352,8 +337,10 @@ public class PgpKeyOperation {
|
||||
keyFlags = 0;
|
||||
|
||||
usageId = keysUsages.get(i);
|
||||
canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
canSign =
|
||||
(usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
canEncrypt =
|
||||
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
if (canSign) {
|
||||
Date todayDate = new Date(); //both sig times the same
|
||||
keyFlags |= KeyFlags.SIGN_DATA;
|
||||
@ -382,12 +369,16 @@ public class PgpKeyOperation {
|
||||
GregorianCalendar expiryDate = keysExpiryDates.get(i);
|
||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0)
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
long numDays =
|
||||
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0) {
|
||||
throw new PgpGeneralException
|
||||
(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
}
|
||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||
} else {
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
|
||||
//do this explicitly, although since we're rebuilding,
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||
//this happens anyway
|
||||
}
|
||||
|
||||
|
@ -18,28 +18,11 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.bcpg.BCPGOutputStream;
|
||||
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.*;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
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.spongycastle.openpgp.operator.jcajce.*;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -49,11 +32,7 @@ import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SignatureException;
|
||||
@ -63,110 +42,110 @@ import java.util.Date;
|
||||
* This class uses a Builder pattern!
|
||||
*/
|
||||
public class PgpSignEncrypt {
|
||||
private Context context;
|
||||
private InputData data;
|
||||
private OutputStream outStream;
|
||||
private Context mContext;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
private ProgressDialogUpdater progress;
|
||||
private boolean enableAsciiArmorOutput;
|
||||
private int compressionId;
|
||||
private long[] encryptionKeyIds;
|
||||
private String encryptionPassphrase;
|
||||
private int symmetricEncryptionAlgorithm;
|
||||
private long signatureKeyId;
|
||||
private int signatureHashAlgorithm;
|
||||
private boolean signatureForceV3;
|
||||
private String signaturePassphrase;
|
||||
private ProgressDialogUpdater mProgress;
|
||||
private boolean mEnableAsciiArmorOutput;
|
||||
private int mCompressionId;
|
||||
private long[] mEncryptionKeyIds;
|
||||
private String mEncryptionPassphrase;
|
||||
private int mSymmetricEncryptionAlgorithm;
|
||||
private long mSignatureKeyId;
|
||||
private int mSignatureHashAlgorithm;
|
||||
private boolean mSignatureForceV3;
|
||||
private String mSignaturePassphrase;
|
||||
|
||||
private PgpSignEncrypt(Builder builder) {
|
||||
// private Constructor can only be called from Builder
|
||||
this.context = builder.context;
|
||||
this.data = builder.data;
|
||||
this.outStream = builder.outStream;
|
||||
this.mContext = builder.mContext;
|
||||
this.mData = builder.mData;
|
||||
this.mOutStream = builder.mOutStream;
|
||||
|
||||
this.progress = builder.progress;
|
||||
this.enableAsciiArmorOutput = builder.enableAsciiArmorOutput;
|
||||
this.compressionId = builder.compressionId;
|
||||
this.encryptionKeyIds = builder.encryptionKeyIds;
|
||||
this.encryptionPassphrase = builder.encryptionPassphrase;
|
||||
this.symmetricEncryptionAlgorithm = builder.symmetricEncryptionAlgorithm;
|
||||
this.signatureKeyId = builder.signatureKeyId;
|
||||
this.signatureHashAlgorithm = builder.signatureHashAlgorithm;
|
||||
this.signatureForceV3 = builder.signatureForceV3;
|
||||
this.signaturePassphrase = builder.signaturePassphrase;
|
||||
this.mProgress = builder.mProgress;
|
||||
this.mEnableAsciiArmorOutput = builder.mEnableAsciiArmorOutput;
|
||||
this.mCompressionId = builder.mCompressionId;
|
||||
this.mEncryptionKeyIds = builder.mEncryptionKeyIds;
|
||||
this.mEncryptionPassphrase = builder.mEncryptionPassphrase;
|
||||
this.mSymmetricEncryptionAlgorithm = builder.mSymmetricEncryptionAlgorithm;
|
||||
this.mSignatureKeyId = builder.mSignatureKeyId;
|
||||
this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm;
|
||||
this.mSignatureForceV3 = builder.mSignatureForceV3;
|
||||
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
// mandatory parameter
|
||||
private Context context;
|
||||
private InputData data;
|
||||
private OutputStream outStream;
|
||||
private Context mContext;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
// optional
|
||||
private ProgressDialogUpdater progress = null;
|
||||
private boolean enableAsciiArmorOutput = false;
|
||||
private int compressionId = Id.choice.compression.none;
|
||||
private long[] encryptionKeyIds = new long[0];
|
||||
private String encryptionPassphrase = null;
|
||||
private int symmetricEncryptionAlgorithm = 0;
|
||||
private long signatureKeyId = Id.key.none;
|
||||
private int signatureHashAlgorithm = 0;
|
||||
private boolean signatureForceV3 = false;
|
||||
private String signaturePassphrase = null;
|
||||
private ProgressDialogUpdater mProgress = null;
|
||||
private boolean mEnableAsciiArmorOutput = false;
|
||||
private int mCompressionId = Id.choice.compression.none;
|
||||
private long[] mEncryptionKeyIds = new long[0];
|
||||
private String mEncryptionPassphrase = null;
|
||||
private int mSymmetricEncryptionAlgorithm = 0;
|
||||
private long mSignatureKeyId = Id.key.none;
|
||||
private int mSignatureHashAlgorithm = 0;
|
||||
private boolean mSignatureForceV3 = false;
|
||||
private String mSignaturePassphrase = null;
|
||||
|
||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
||||
this.context = context;
|
||||
this.data = data;
|
||||
this.outStream = outStream;
|
||||
this.mContext = context;
|
||||
this.mData = data;
|
||||
this.mOutStream = outStream;
|
||||
}
|
||||
|
||||
public Builder progress(ProgressDialogUpdater progress) {
|
||||
this.progress = progress;
|
||||
this.mProgress = progress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder enableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
|
||||
this.enableAsciiArmorOutput = enableAsciiArmorOutput;
|
||||
this.mEnableAsciiArmorOutput = enableAsciiArmorOutput;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder compressionId(int compressionId) {
|
||||
this.compressionId = compressionId;
|
||||
this.mCompressionId = compressionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder encryptionKeyIds(long[] encryptionKeyIds) {
|
||||
this.encryptionKeyIds = encryptionKeyIds;
|
||||
this.mEncryptionKeyIds = encryptionKeyIds;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder encryptionPassphrase(String encryptionPassphrase) {
|
||||
this.encryptionPassphrase = encryptionPassphrase;
|
||||
this.mEncryptionPassphrase = encryptionPassphrase;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder symmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
|
||||
this.symmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
|
||||
this.mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signatureKeyId(long signatureKeyId) {
|
||||
this.signatureKeyId = signatureKeyId;
|
||||
this.mSignatureKeyId = signatureKeyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signatureHashAlgorithm(int signatureHashAlgorithm) {
|
||||
this.signatureHashAlgorithm = signatureHashAlgorithm;
|
||||
this.mSignatureHashAlgorithm = signatureHashAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signatureForceV3(boolean signatureForceV3) {
|
||||
this.signatureForceV3 = signatureForceV3;
|
||||
this.mSignatureForceV3 = signatureForceV3;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signaturePassphrase(String signaturePassphrase) {
|
||||
this.signaturePassphrase = signaturePassphrase;
|
||||
this.mSignaturePassphrase = signaturePassphrase;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -176,14 +155,14 @@ public class PgpSignEncrypt {
|
||||
}
|
||||
|
||||
public void updateProgress(int message, int current, int total) {
|
||||
if (progress != null) {
|
||||
progress.setProgress(message, current, total);
|
||||
if (mProgress != null) {
|
||||
mProgress.setProgress(message, current, total);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProgress(int current, int total) {
|
||||
if (progress != null) {
|
||||
progress.setProgress(current, total);
|
||||
if (mProgress != null) {
|
||||
mProgress.setProgress(current, total);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,17 +180,17 @@ public class PgpSignEncrypt {
|
||||
throws IOException, PgpGeneralException, PGPException, NoSuchProviderException,
|
||||
NoSuchAlgorithmException, SignatureException {
|
||||
|
||||
boolean enableSignature = signatureKeyId != Id.key.none;
|
||||
boolean enableEncryption = (encryptionKeyIds.length != 0 || encryptionPassphrase != null);
|
||||
boolean enableCompression = (enableEncryption && compressionId != Id.choice.compression.none);
|
||||
boolean enableSignature = mSignatureKeyId != Id.key.none;
|
||||
boolean enableEncryption = (mEncryptionKeyIds.length != 0 || mEncryptionPassphrase != null);
|
||||
boolean enableCompression = (enableEncryption && mCompressionId != Id.choice.compression.none);
|
||||
|
||||
Log.d(Constants.TAG, "enableSignature:" + enableSignature
|
||||
+ "\nenableEncryption:" + enableEncryption
|
||||
+ "\nenableCompression:" + enableCompression
|
||||
+ "\nenableAsciiArmorOutput:" + enableAsciiArmorOutput);
|
||||
+ "\nenableAsciiArmorOutput:" + mEnableAsciiArmorOutput);
|
||||
|
||||
int signatureType;
|
||||
if (enableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||
if (mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||
// for sign-only ascii text
|
||||
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
|
||||
} else {
|
||||
@ -220,12 +199,12 @@ public class PgpSignEncrypt {
|
||||
|
||||
ArmoredOutputStream armorOut = null;
|
||||
OutputStream out;
|
||||
if (enableAsciiArmorOutput) {
|
||||
armorOut = new ArmoredOutputStream(outStream);
|
||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(context));
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
armorOut = new ArmoredOutputStream(mOutStream);
|
||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
|
||||
out = armorOut;
|
||||
} else {
|
||||
out = outStream;
|
||||
out = mOutStream;
|
||||
}
|
||||
|
||||
/* Get keys for signature generation for later usage */
|
||||
@ -233,25 +212,25 @@ public class PgpSignEncrypt {
|
||||
PGPSecretKeyRing signingKeyRing = null;
|
||||
PGPPrivateKey signaturePrivateKey = null;
|
||||
if (enableSignature) {
|
||||
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
|
||||
signingKey = PgpKeyHelper.getSigningKey(context, signatureKeyId);
|
||||
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId);
|
||||
signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId);
|
||||
if (signingKey == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_signature_failed));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
||||
}
|
||||
|
||||
if (signaturePassphrase == null) {
|
||||
if (mSignaturePassphrase == null) {
|
||||
throw new PgpGeneralException(
|
||||
context.getString(R.string.error_no_signature_passphrase));
|
||||
mContext.getString(R.string.error_no_signature_passphrase));
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mSignaturePassphrase.toCharArray());
|
||||
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||
if (signaturePrivateKey == null) {
|
||||
throw new PgpGeneralException(
|
||||
context.getString(R.string.error_could_not_extract_private_key));
|
||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
||||
}
|
||||
}
|
||||
updateProgress(R.string.progress_preparing_streams, 5, 100);
|
||||
@ -261,23 +240,23 @@ public class PgpSignEncrypt {
|
||||
if (enableEncryption) {
|
||||
// has Integrity packet enabled!
|
||||
JcePGPDataEncryptorBuilder encryptorBuilder =
|
||||
new JcePGPDataEncryptorBuilder(symmetricEncryptionAlgorithm)
|
||||
new JcePGPDataEncryptorBuilder(mSymmetricEncryptionAlgorithm)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
|
||||
.setWithIntegrityPacket(true);
|
||||
|
||||
cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
|
||||
|
||||
if (encryptionKeyIds.length == 0) {
|
||||
if (mEncryptionKeyIds.length == 0) {
|
||||
// Symmetric encryption
|
||||
Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
|
||||
|
||||
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
|
||||
new JcePBEKeyEncryptionMethodGenerator(encryptionPassphrase.toCharArray());
|
||||
new JcePBEKeyEncryptionMethodGenerator(mEncryptionPassphrase.toCharArray());
|
||||
cPk.addMethod(symmetricEncryptionGenerator);
|
||||
} else {
|
||||
// Asymmetric encryption
|
||||
for (long id : encryptionKeyIds) {
|
||||
PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(context, id);
|
||||
for (long id : mEncryptionKeyIds) {
|
||||
PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(mContext, id);
|
||||
if (key != null) {
|
||||
JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator =
|
||||
new JcePublicKeyKeyEncryptionMethodGenerator(key);
|
||||
@ -295,10 +274,10 @@ public class PgpSignEncrypt {
|
||||
|
||||
// content signer based on signing key algorithm and chosen hash algorithm
|
||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
|
||||
signingKey.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
||||
signatureV3Generator.init(signatureType, signaturePrivateKey);
|
||||
} else {
|
||||
@ -322,14 +301,14 @@ public class PgpSignEncrypt {
|
||||
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
||||
|
||||
if (enableCompression) {
|
||||
compressGen = new PGPCompressedDataGenerator(compressionId);
|
||||
compressGen = new PGPCompressedDataGenerator(mCompressionId);
|
||||
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
|
||||
} else {
|
||||
bcpgOut = new BCPGOutputStream(encryptionOut);
|
||||
}
|
||||
|
||||
if (enableSignature) {
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
|
||||
} else {
|
||||
signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
|
||||
@ -345,13 +324,13 @@ public class PgpSignEncrypt {
|
||||
long progress = 0;
|
||||
int n;
|
||||
byte[] buffer = new byte[1 << 16];
|
||||
InputStream in = data.getInputStream();
|
||||
InputStream in = mData.getInputStream();
|
||||
while ((n = in.read(buffer)) > 0) {
|
||||
pOut.write(buffer, 0, n);
|
||||
|
||||
// update signature buffer if signature is requested
|
||||
if (enableSignature) {
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.update(buffer, 0, n);
|
||||
} else {
|
||||
signatureGenerator.update(buffer, 0, n);
|
||||
@ -359,26 +338,26 @@ public class PgpSignEncrypt {
|
||||
}
|
||||
|
||||
progress += n;
|
||||
if (data.getSize() != 0) {
|
||||
updateProgress((int) (20 + (95 - 20) * progress / data.getSize()), 100);
|
||||
if (mData.getSize() != 0) {
|
||||
updateProgress((int) (20 + (95 - 20) * progress / mData.getSize()), 100);
|
||||
}
|
||||
}
|
||||
|
||||
literalGen.close();
|
||||
} else if (enableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||
} else if (mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||
/* sign-only of ascii text */
|
||||
|
||||
updateProgress(R.string.progress_signing, 40, 100);
|
||||
|
||||
// write directly on armor output stream
|
||||
armorOut.beginClearText(signatureHashAlgorithm);
|
||||
armorOut.beginClearText(mSignatureHashAlgorithm);
|
||||
|
||||
InputStream in = data.getInputStream();
|
||||
InputStream in = mData.getInputStream();
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
final byte[] newline = "\r\n".getBytes("UTF-8");
|
||||
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
processLine(reader.readLine(), armorOut, signatureV3Generator);
|
||||
} else {
|
||||
processLine(reader.readLine(), armorOut, signatureGenerator);
|
||||
@ -395,7 +374,7 @@ public class PgpSignEncrypt {
|
||||
armorOut.write(newline);
|
||||
|
||||
// update signature buffer with input line
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.update(newline);
|
||||
processLine(line, armorOut, signatureV3Generator);
|
||||
} else {
|
||||
@ -415,7 +394,7 @@ public class PgpSignEncrypt {
|
||||
|
||||
if (enableSignature) {
|
||||
updateProgress(R.string.progress_generating_signature, 95, 100);
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.generate().encode(pOut);
|
||||
} else {
|
||||
signatureGenerator.generate().encode(pOut);
|
||||
@ -432,12 +411,12 @@ public class PgpSignEncrypt {
|
||||
|
||||
encryptionOut.close();
|
||||
}
|
||||
if (enableAsciiArmorOutput) {
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
armorOut.close();
|
||||
}
|
||||
|
||||
out.close();
|
||||
outStream.close();
|
||||
mOutStream.close();
|
||||
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
}
|
||||
@ -449,35 +428,36 @@ public class PgpSignEncrypt {
|
||||
SignatureException {
|
||||
|
||||
OutputStream out;
|
||||
if (enableAsciiArmorOutput) {
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
// Ascii Armor (Radix-64)
|
||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(context));
|
||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
|
||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
|
||||
out = armorOut;
|
||||
} else {
|
||||
out = outStream;
|
||||
out = mOutStream;
|
||||
}
|
||||
|
||||
if (signatureKeyId == 0) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_no_signature_key));
|
||||
if (mSignatureKeyId == 0) {
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key));
|
||||
}
|
||||
|
||||
PGPSecretKeyRing signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
|
||||
PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(context, signatureKeyId);
|
||||
PGPSecretKeyRing signingKeyRing =
|
||||
ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId);
|
||||
PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId);
|
||||
if (signingKey == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_signature_failed));
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
||||
}
|
||||
|
||||
if (signaturePassphrase == null) {
|
||||
throw new PgpGeneralException(context.getString(R.string.error_no_signature_passphrase));
|
||||
if (mSignaturePassphrase == null) {
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_passphrase));
|
||||
}
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mSignaturePassphrase.toCharArray());
|
||||
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||
if (signaturePrivateKey == null) {
|
||||
throw new PgpGeneralException(
|
||||
context.getString(R.string.error_could_not_extract_private_key));
|
||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
||||
}
|
||||
updateProgress(R.string.progress_preparing_streams, 0, 100);
|
||||
|
||||
@ -490,12 +470,12 @@ public class PgpSignEncrypt {
|
||||
|
||||
// content signer based on signing key algorithm and chosen hash algorithm
|
||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
|
||||
.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
|
||||
.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
|
||||
PGPSignatureGenerator signatureGenerator = null;
|
||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
||||
signatureV3Generator.init(type, signaturePrivateKey);
|
||||
} else {
|
||||
@ -510,7 +490,7 @@ public class PgpSignEncrypt {
|
||||
|
||||
updateProgress(R.string.progress_signing, 40, 100);
|
||||
|
||||
InputStream inStream = data.getInputStream();
|
||||
InputStream inStream = mData.getInputStream();
|
||||
// if (binary) {
|
||||
// byte[] buffer = new byte[1 << 16];
|
||||
// int n = 0;
|
||||
@ -527,7 +507,7 @@ public class PgpSignEncrypt {
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
processLine(line, null, signatureV3Generator);
|
||||
signatureV3Generator.update(newline);
|
||||
} else {
|
||||
@ -538,13 +518,13 @@ public class PgpSignEncrypt {
|
||||
// }
|
||||
|
||||
BCPGOutputStream bOut = new BCPGOutputStream(out);
|
||||
if (signatureForceV3) {
|
||||
if (mSignatureForceV3) {
|
||||
signatureV3Generator.generate().encode(bOut);
|
||||
} else {
|
||||
signatureGenerator.generate().encode(bOut);
|
||||
}
|
||||
out.close();
|
||||
outStream.close();
|
||||
mOutStream.close();
|
||||
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
}
|
||||
|
@ -1,33 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
import org.spongycastle.asn1.DERObjectIdentifier;
|
||||
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.asn1.x509.*;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
@ -38,9 +29,23 @@ import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
|
||||
public class PgpToX509 {
|
||||
public final static String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";
|
||||
public final static String DN_COMMON_PART_OU = "OpenPGP Keychain cert";
|
||||
public static final String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";
|
||||
public static final String DN_COMMON_PART_OU = "OpenPGP Keychain cert";
|
||||
|
||||
/**
|
||||
* Creates a self-signed certificate from a public and private key. The (critical) key-usage
|
||||
@ -48,20 +53,14 @@ public class PgpToX509 {
|
||||
* and certificate-signing. The (non-critical) Netscape extension is set up with: SSL client and
|
||||
* S/MIME. A URI subjectAltName may also be set up.
|
||||
*
|
||||
* @param pubKey
|
||||
* public key
|
||||
* @param privKey
|
||||
* private key
|
||||
* @param subject
|
||||
* subject (and issuer) DN for this certificate, RFC 2253 format preferred.
|
||||
* @param startDate
|
||||
* date from which the certificate will be valid (defaults to current date and time
|
||||
* @param pubKey public key
|
||||
* @param privKey private key
|
||||
* @param subject subject (and issuer) DN for this certificate, RFC 2253 format preferred.
|
||||
* @param startDate date from which the certificate will be valid (defaults to current date and time
|
||||
* if null)
|
||||
* @param endDate
|
||||
* date until which the certificate will be valid (defaults to current date and time
|
||||
* @param endDate date until which the certificate will be valid (defaults to current date and time
|
||||
* if null) *
|
||||
* @param subjAltNameURI
|
||||
* URI to be placed in subjectAltName
|
||||
* @param subjAltNameURI URI to be placed in subjectAltName
|
||||
* @return self-signed certificate
|
||||
* @throws InvalidKeyException
|
||||
* @throws SignatureException
|
||||
@ -70,7 +69,6 @@ public class PgpToX509 {
|
||||
* @throws NoSuchProviderException
|
||||
* @throws CertificateException
|
||||
* @throws Exception
|
||||
*
|
||||
* @author Bruno Harbulot
|
||||
*/
|
||||
public static X509Certificate createSelfSignedCert(PublicKey pubKey, PrivateKey privKey,
|
||||
@ -172,14 +170,11 @@ public class PgpToX509 {
|
||||
/**
|
||||
* Creates a self-signed certificate from a PGP Secret Key.
|
||||
*
|
||||
* @param pgpSecKey
|
||||
* PGP Secret Key (from which one can extract the public and private keys and other
|
||||
* @param pgpSecKey PGP Secret Key (from which one can extract the public and private keys and other
|
||||
* attributes).
|
||||
* @param pgpPrivKey
|
||||
* PGP Private Key corresponding to the Secret Key (password callbacks should be done
|
||||
* @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks should be done
|
||||
* before calling this method)
|
||||
* @param subjAltNameURI
|
||||
* optional URI to embed in the subject alternative-name
|
||||
* @param subjAltNameURI optional URI to embed in the subject alternative-name
|
||||
* @return self-signed certificate
|
||||
* @throws PGPException
|
||||
* @throws NoSuchProviderException
|
||||
@ -187,7 +182,6 @@ public class PgpToX509 {
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws SignatureException
|
||||
* @throws CertificateException
|
||||
*
|
||||
* @author Bruno Harbulot
|
||||
*/
|
||||
public static X509Certificate createSelfSignedCert(PGPSecretKey pgpSecKey,
|
||||
@ -263,12 +257,11 @@ public class PgpToX509 {
|
||||
* allow passwords to be stored within your application.
|
||||
*
|
||||
* @author Bruno Harbulot.
|
||||
*
|
||||
*/
|
||||
public final static class PredefinedPasswordCallbackHandler implements CallbackHandler {
|
||||
public static final class PredefinedPasswordCallbackHandler implements CallbackHandler {
|
||||
|
||||
private char[] password;
|
||||
private String prompt;
|
||||
private char[] mPassword;
|
||||
private String mPrompt;
|
||||
|
||||
public PredefinedPasswordCallbackHandler(String password) {
|
||||
this(password == null ? null : password.toCharArray(), null);
|
||||
@ -283,16 +276,16 @@ public class PgpToX509 {
|
||||
}
|
||||
|
||||
public PredefinedPasswordCallbackHandler(char[] password, String prompt) {
|
||||
this.password = password;
|
||||
this.prompt = prompt;
|
||||
this.mPassword = password;
|
||||
this.mPrompt = prompt;
|
||||
}
|
||||
|
||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||
for (Callback callback : callbacks) {
|
||||
if (callback instanceof PasswordCallback) {
|
||||
PasswordCallback pwCallback = (PasswordCallback) callback;
|
||||
if ((this.prompt == null) || (this.prompt.equals(pwCallback.getPrompt()))) {
|
||||
pwCallback.setPassword(this.password);
|
||||
if ((this.mPrompt == null) || (this.mPrompt.equals(pwCallback.getPrompt()))) {
|
||||
pwCallback.setPassword(this.mPassword);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedCallbackException(callback, "Unrecognised callback.");
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp.exception;
|
||||
|
||||
public class NoAsymmetricEncryptionException extends Exception {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp.exception;
|
||||
|
||||
public class PgpGeneralException extends Exception {
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
|
||||
public class KeychainContract {
|
||||
|
||||
@ -88,7 +87,6 @@ public class KeychainContract {
|
||||
|
||||
public static final String PATH_PUBLIC = "public";
|
||||
public static final String PATH_SECRET = "secret";
|
||||
public static final String PATH_UNIFIED = "unified";
|
||||
|
||||
public static final String PATH_BY_MASTER_KEY_ID = "master_key_id";
|
||||
public static final String PATH_BY_KEY_ID = "key_id";
|
||||
@ -109,14 +107,18 @@ public class KeychainContract {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||
.appendPath(BASE_KEY_RINGS).build();
|
||||
|
||||
/** Use if multiple items get returned */
|
||||
/**
|
||||
* Use if multiple items get returned
|
||||
*/
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key_ring";
|
||||
|
||||
/** Use if a single item is returned */
|
||||
/**
|
||||
* Use if a single item is returned
|
||||
*/
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key_ring";
|
||||
|
||||
public static Uri buildUnifiedKeyRingsUri() {
|
||||
return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build();
|
||||
return CONTENT_URI;
|
||||
}
|
||||
|
||||
public static Uri buildPublicKeyRingsUri() {
|
||||
@ -180,10 +182,14 @@ public class KeychainContract {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||
.appendPath(BASE_KEY_RINGS).build();
|
||||
|
||||
/** Use if multiple items get returned */
|
||||
/**
|
||||
* Use if multiple items get returned
|
||||
*/
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key";
|
||||
|
||||
/** Use if a single item is returned */
|
||||
/**
|
||||
* Use if a single item is returned
|
||||
*/
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key";
|
||||
|
||||
public static Uri buildPublicKeysUri(String keyRingRowId) {
|
||||
@ -219,10 +225,14 @@ public class KeychainContract {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||
.appendPath(BASE_KEY_RINGS).build();
|
||||
|
||||
/** Use if multiple items get returned */
|
||||
/**
|
||||
* Use if multiple items get returned
|
||||
*/
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id";
|
||||
|
||||
/** Use if a single item is returned */
|
||||
/**
|
||||
* Use if a single item is returned
|
||||
*/
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.user_id";
|
||||
|
||||
public static Uri buildPublicUserIdsUri(String keyRingRowId) {
|
||||
@ -258,10 +268,14 @@ public class KeychainContract {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||
.appendPath(BASE_API_APPS).build();
|
||||
|
||||
/** Use if multiple items get returned */
|
||||
/**
|
||||
* Use if multiple items get returned
|
||||
*/
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_apps";
|
||||
|
||||
/** Use if a single item is returned */
|
||||
/**
|
||||
* Use if a single item is returned
|
||||
*/
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps";
|
||||
|
||||
public static Uri buildIdUri(String rowId) {
|
||||
|
@ -17,6 +17,10 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
|
||||
@ -25,11 +29,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
public class KeychainDatabase extends SQLiteOpenHelper {
|
||||
private static final String DATABASE_NAME = "apg.db";
|
||||
private static final int DATABASE_VERSION = 8;
|
||||
|
@ -17,22 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
@ -44,6 +28,13 @@ import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.text.TextUtils;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.*;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class KeychainProvider extends ContentProvider {
|
||||
// public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME
|
||||
@ -104,6 +95,15 @@ public class KeychainProvider extends ContentProvider {
|
||||
|
||||
String authority = KeychainContract.CONTENT_AUTHORITY;
|
||||
|
||||
/**
|
||||
* unified key rings
|
||||
*
|
||||
* <pre>
|
||||
* key_rings
|
||||
* </pre>
|
||||
*/
|
||||
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS, UNIFIED_KEY_RING);
|
||||
|
||||
/**
|
||||
* public key rings
|
||||
*
|
||||
@ -237,20 +237,11 @@ public class KeychainProvider extends ContentProvider {
|
||||
+ KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME);
|
||||
|
||||
/**
|
||||
* unified key rings
|
||||
* <pre>
|
||||
*
|
||||
* key_rings/unified
|
||||
*
|
||||
*/
|
||||
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
|
||||
+ KeychainContract.PATH_UNIFIED, UNIFIED_KEY_RING);
|
||||
|
||||
/**
|
||||
* certifications
|
||||
* <pre>
|
||||
*
|
||||
* key_rings/unified
|
||||
* <pre>
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
matcher.addURI(authority, KeychainContract.BASE_CERTS, CERTS);
|
||||
@ -394,7 +385,8 @@ public class KeychainProvider extends ContentProvider {
|
||||
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
|
||||
projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "."
|
||||
+ KeyRingsColumns.KEY_RING_DATA);
|
||||
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID);
|
||||
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
|
||||
+ KeyRingsColumns.MASTER_KEY_ID);
|
||||
// TODO: deprecated master key id
|
||||
//projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID);
|
||||
|
||||
@ -403,6 +395,10 @@ public class KeychainProvider extends ContentProvider {
|
||||
|
||||
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);
|
||||
|
||||
// type attribute is special: if there is any grouping, choose secret over public type
|
||||
projectionMap.put(KeyRingsColumns.TYPE,
|
||||
"MAX(" + Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + ") AS " + KeyRingsColumns.TYPE);
|
||||
|
||||
return projectionMap;
|
||||
}
|
||||
|
||||
@ -437,9 +433,11 @@ public class KeychainProvider extends ContentProvider {
|
||||
* Builds default query for keyRings: KeyRings table is joined with UserIds and Keys
|
||||
*/
|
||||
private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match) {
|
||||
if (match != UNIFIED_KEY_RING) {
|
||||
// public or secret keyring
|
||||
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
|
||||
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
|
||||
}
|
||||
|
||||
// join keyrings with keys and userIds
|
||||
// Only get user id and key with rank 0 (main user id and main key)
|
||||
@ -491,75 +489,26 @@ public class KeychainProvider extends ContentProvider {
|
||||
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
SQLiteDatabase db = mApgDatabase.getReadableDatabase();
|
||||
|
||||
String groupBy = null;
|
||||
|
||||
int match = mUriMatcher.match(uri);
|
||||
|
||||
// screw that switch
|
||||
if(match == UNIFIED_KEY_RING) {
|
||||
|
||||
// join keyrings with keys and userIds
|
||||
// Only get user id and key with rank 0 (main user id and main key)
|
||||
qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "("
|
||||
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "."
|
||||
+ KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "."
|
||||
+ KeysColumns.RANK + " = '0') " + " INNER JOIN " + Tables.USER_IDS + " ON "
|
||||
+ "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "."
|
||||
+ UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "."
|
||||
+ UserIdsColumns.RANK + " = '0')");
|
||||
|
||||
{
|
||||
HashMap<String, String> projectionMap = new HashMap<String, String>();
|
||||
|
||||
projectionMap.put(KeyRingsColumns.TYPE, "MAX(" + Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + ")");
|
||||
|
||||
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
|
||||
projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "."
|
||||
+ KeyRingsColumns.KEY_RING_DATA);
|
||||
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID);
|
||||
// TODO: deprecated master key id
|
||||
//projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID);
|
||||
|
||||
projectionMap.put(KeysColumns.FINGERPRINT, Tables.KEYS + "." + KeysColumns.FINGERPRINT);
|
||||
projectionMap.put(KeysColumns.IS_REVOKED, Tables.KEYS + "." + KeysColumns.IS_REVOKED);
|
||||
|
||||
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);
|
||||
|
||||
qb.setProjectionMap(projectionMap);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
|
||||
}
|
||||
|
||||
// If no sort order is specified use the default
|
||||
String orderBy;
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
orderBy = Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " DESC";
|
||||
} else {
|
||||
orderBy = Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " DESC, " + sortOrder;
|
||||
}
|
||||
|
||||
Cursor c = qb.query(db, projection, selection, selectionArgs,
|
||||
Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID,
|
||||
null, orderBy);
|
||||
|
||||
// Tell the cursor what uri to watch, so it knows when its source data changes
|
||||
c.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
|
||||
if (Constants.DEBUG) {
|
||||
Log.d(Constants.TAG,
|
||||
"Query: "
|
||||
+ qb.buildQuery(projection, selection, selectionArgs, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID, null,
|
||||
orderBy, null));
|
||||
Log.d(Constants.TAG, "Cursor: " + DatabaseUtils.dumpCursorToString(c));
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// all query() parameters, for good measure
|
||||
String groupBy = null, having = null;
|
||||
boolean all = false;
|
||||
|
||||
switch (match) {
|
||||
case UNIFIED_KEY_RING:
|
||||
qb = buildKeyRingQuery(qb, match);
|
||||
|
||||
// GROUP BY so we don't get duplicates
|
||||
groupBy = Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID;
|
||||
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
sortOrder = KeyRings.TYPE + " DESC, " +
|
||||
Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PUBLIC_KEY_RING:
|
||||
case SECRET_KEY_RING:
|
||||
qb = buildKeyRingQuery(qb, match);
|
||||
@ -740,8 +689,7 @@ public class KeychainProvider extends ContentProvider {
|
||||
+ Tables.KEYS + "." + Keys.KEY_RING_ROW_ID + " = "
|
||||
+ "signer." + UserIds.KEY_RING_ROW_ID
|
||||
+ " AND "
|
||||
+ Tables.KEYS + "." + Keys.RANK + " = "
|
||||
+ "signer." + UserIds.RANK
|
||||
+ "signer." + Keys.RANK + " = 0"
|
||||
+ ")");
|
||||
|
||||
// groupBy = Tables.USER_IDS + "." + UserIds.RANK;
|
||||
@ -801,7 +749,7 @@ public class KeychainProvider extends ContentProvider {
|
||||
orderBy = sortOrder;
|
||||
}
|
||||
|
||||
Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, orderBy);
|
||||
Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, having, orderBy);
|
||||
|
||||
// Tell the cursor what uri to watch, so it knows when its source data changes
|
||||
c.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
|
||||
public class KeychainServiceBlobContract {
|
||||
|
||||
|
@ -22,7 +22,6 @@ import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
|
||||
|
||||
public class KeychainServiceBlobDatabase extends SQLiteOpenHelper {
|
||||
|
@ -18,11 +18,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.Blobs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
@ -31,7 +26,10 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.Blobs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -40,7 +38,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KeychainServiceBlobProvider extends ContentProvider {
|
||||
private static final String STORE_PATH = Constants.path.APP_DIR + "/ApgBlobs";
|
||||
private static final String STORE_PATH = Constants.Path.APP_DIR + "/ApgBlobs";
|
||||
|
||||
private KeychainServiceBlobDatabase mBlobDatabase = null;
|
||||
|
||||
@ -55,7 +53,9 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues ignored) {
|
||||
// ContentValues are actually ignored, because we want to store a blob with no more
|
||||
@ -74,7 +74,9 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
||||
return Uri.withAppendedPath(insertedUri, password);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException,
|
||||
FileNotFoundException {
|
||||
@ -124,26 +126,34 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
|
@ -17,24 +17,17 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Date;
|
||||
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.bcpg.UserAttributePacket;
|
||||
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
||||
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.PGPSignature;
|
||||
import android.content.*;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.openpgp.*;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
||||
@ -50,15 +43,13 @@ import org.sufficientlysecure.keychain.service.remote.AppSettings;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class ProviderHelper {
|
||||
|
||||
@ -175,7 +166,8 @@ public class ProviderHelper {
|
||||
|
||||
// get current _ID of key
|
||||
long currentRowId = -1;
|
||||
Cursor oldQuery = context.getContentResolver().query(deleteUri, new String[]{KeyRings._ID}, null, null, null);
|
||||
Cursor oldQuery = context.getContentResolver()
|
||||
.query(deleteUri, new String[]{KeyRings._ID}, null, null, null);
|
||||
if (oldQuery != null && oldQuery.moveToFirst()) {
|
||||
currentRowId = oldQuery.getLong(0);
|
||||
} else {
|
||||
@ -191,10 +183,12 @@ public class ProviderHelper {
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
// use exactly the same _ID again to replace key in-place.
|
||||
// NOTE: If we would not use the same _ID again, getting back to the ViewKeyActivity would result in Nullpointer,
|
||||
// NOTE: If we would not use the same _ID again,
|
||||
// getting back to the ViewKeyActivity would result in Nullpointer,
|
||||
// because the currently loaded key would be gone from the database
|
||||
if (currentRowId != -1)
|
||||
if (currentRowId != -1) {
|
||||
values.put(KeyRings._ID, currentRowId);
|
||||
}
|
||||
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
||||
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
||||
|
||||
@ -279,7 +273,8 @@ public class ProviderHelper {
|
||||
|
||||
// get current _ID of key
|
||||
long currentRowId = -1;
|
||||
Cursor oldQuery = context.getContentResolver().query(deleteUri, new String[]{KeyRings._ID}, null, null, null);
|
||||
Cursor oldQuery = context.getContentResolver()
|
||||
.query(deleteUri, new String[]{KeyRings._ID}, null, null, null);
|
||||
if (oldQuery != null && oldQuery.moveToFirst()) {
|
||||
currentRowId = oldQuery.getLong(0);
|
||||
} else {
|
||||
@ -295,10 +290,12 @@ public class ProviderHelper {
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
// use exactly the same _ID again to replace key in-place.
|
||||
// NOTE: If we would not use the same _ID again, getting back to the ViewKeyActivity would result in Nullpointer,
|
||||
// NOTE: If we would not use the same _ID again,
|
||||
// getting back to the ViewKeyActivity would result in Nullpointer,
|
||||
// because the currently loaded key would be gone from the database
|
||||
if (currentRowId != -1)
|
||||
if (currentRowId != -1) {
|
||||
values.put(KeyRings._ID, currentRowId);
|
||||
}
|
||||
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
||||
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
||||
|
||||
@ -483,10 +480,10 @@ public class ProviderHelper {
|
||||
|
||||
ArrayList<Long> rowIds = new ArrayList<Long>();
|
||||
if (cursor != null) {
|
||||
int IdCol = cursor.getColumnIndex(KeyRings._ID);
|
||||
int idCol = cursor.getColumnIndex(KeyRings._ID);
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
rowIds.add(cursor.getLong(IdCol));
|
||||
rowIds.add(cursor.getLong(idCol));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
}
|
||||
|
@ -17,48 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
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.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.pgp.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.PgpKeyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -67,13 +25,32 @@ import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import org.spongycastle.openpgp.*;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.pgp.*;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.util.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This Service contains all important long lasting operations for APG. It receives Intents with
|
||||
* data from the activities or other apps, queues these intents, executes them, and stops itself
|
||||
* after doing them.
|
||||
*/
|
||||
public class KeychainIntentService extends IntentService implements ProgressDialogUpdater {
|
||||
public class KeychainIntentService extends IntentService
|
||||
implements ProgressDialogUpdater, KeychainServiceListener {
|
||||
|
||||
/* extras that can be given by intent */
|
||||
public static final String EXTRA_MESSENGER = "messenger";
|
||||
@ -331,8 +308,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||
.signatureKeyId(secretKeyId)
|
||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
.signatureHashAlgorithm(
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(
|
||||
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
|
||||
builder.build().generateSignature();
|
||||
} else if (signOnly) {
|
||||
@ -340,21 +319,26 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||
.signatureKeyId(secretKeyId)
|
||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
.signatureHashAlgorithm(
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(
|
||||
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
|
||||
builder.build().execute();
|
||||
} else {
|
||||
Log.d(Constants.TAG, "encrypt...");
|
||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||
.compressionId(compressionId)
|
||||
.symmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
|
||||
.symmetricEncryptionAlgorithm(
|
||||
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
|
||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||
.encryptionKeyIds(encryptionKeyIds)
|
||||
.encryptionPassphrase(encryptionPassphrase)
|
||||
.signatureKeyId(secretKeyId)
|
||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
.signatureHashAlgorithm(
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||
.signaturePassphrase(
|
||||
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||
|
||||
builder.build().execute();
|
||||
}
|
||||
@ -546,7 +530,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
ArrayList<PGPSecretKey> keys = PgpConversionHelper.BytesToPGPSecretKeyList(data
|
||||
.getByteArray(SAVE_KEYRING_KEYS));
|
||||
ArrayList<Integer> keysUsages = data.getIntegerArrayList(SAVE_KEYRING_KEYS_USAGES);
|
||||
ArrayList<GregorianCalendar> keysExpiryDates = (ArrayList<GregorianCalendar>) data.getSerializable(SAVE_KEYRING_KEYS_EXPIRY_DATES);
|
||||
ArrayList<GregorianCalendar> keysExpiryDates =
|
||||
(ArrayList<GregorianCalendar>) data.getSerializable(SAVE_KEYRING_KEYS_EXPIRY_DATES);
|
||||
|
||||
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
|
||||
|
||||
@ -601,7 +586,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
int keysTotal = 2;
|
||||
int keysCreated = 0;
|
||||
setProgress(
|
||||
getApplicationContext().getResources().getQuantityString(R.plurals.progress_generating, keysTotal),
|
||||
getApplicationContext().getResources().
|
||||
getQuantityString(R.plurals.progress_generating, keysTotal),
|
||||
keysCreated,
|
||||
keysTotal);
|
||||
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
|
||||
@ -712,10 +698,15 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
|
||||
Bundle resultData;
|
||||
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(this, this, this);
|
||||
|
||||
resultData = pgpImportExport
|
||||
.exportKeyRings(keyRingRowIds, keyType, outStream);
|
||||
|
||||
if (mIsCanceled) {
|
||||
boolean isDeleted = new File(outputFile).delete();
|
||||
}
|
||||
|
||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
sendErrorToHandler(e);
|
||||
@ -765,7 +756,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
// need to have access to the bufferedInput, so we can reuse it for the possible
|
||||
// PGPObject chunks after the first one, e.g. files with several consecutive ASCII
|
||||
// armor blocks
|
||||
BufferedInputStream bufferedInput = new BufferedInputStream(new ByteArrayInputStream(downloadedKey));
|
||||
BufferedInputStream bufferedInput =
|
||||
new BufferedInputStream(new ByteArrayInputStream(downloadedKey));
|
||||
try {
|
||||
|
||||
// read all available blocks... (asc files can contain many blocks with BEGIN END)
|
||||
@ -837,9 +829,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
|
||||
private void sendErrorToHandler(Exception e) {
|
||||
// Service was canceled. Do not send error to handler.
|
||||
if (this.mIsCanceled)
|
||||
if (this.mIsCanceled) {
|
||||
return;
|
||||
|
||||
}
|
||||
Log.e(Constants.TAG, "ApgService Exception: ", e);
|
||||
e.printStackTrace();
|
||||
|
||||
@ -850,9 +842,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
|
||||
private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) {
|
||||
// Service was canceled. Do not send message to handler.
|
||||
if (this.mIsCanceled)
|
||||
if (this.mIsCanceled) {
|
||||
return;
|
||||
|
||||
}
|
||||
Message msg = Message.obtain();
|
||||
msg.arg1 = arg1;
|
||||
if (arg2 != null) {
|
||||
@ -903,4 +895,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
public void setProgress(int progress, int max) {
|
||||
setProgress(null, progress, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasServiceStopped() {
|
||||
return mIsCanceled;
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.os.Bundle;
|
||||
@ -28,6 +25,8 @@ import android.os.Message;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||
|
||||
public class KeychainIntentServiceHandler extends Handler {
|
||||
|
||||
@ -73,7 +72,8 @@ public class KeychainIntentServiceHandler extends Handler {
|
||||
}
|
||||
|
||||
public void showProgressDialog(FragmentActivity activity) {
|
||||
// TODO: This is a hack!, see http://stackoverflow.com/questions/10114324/show-dialogfragment-from-onactivityresult
|
||||
// TODO: This is a hack!, see
|
||||
// http://stackoverflow.com/questions/10114324/show-dialogfragment-from-onactivityresult
|
||||
final FragmentManager manager = activity.getSupportFragmentManager();
|
||||
Handler handler = new Handler();
|
||||
handler.post(new Runnable() {
|
||||
|
@ -17,10 +17,15 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.*;
|
||||
import android.util.Log;
|
||||
import android.util.LongSparseArray;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
@ -34,28 +39,13 @@ import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This service runs in its own process, but is available to all other processes as the main
|
||||
* passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for
|
||||
* convenience.
|
||||
*
|
||||
*/
|
||||
public class PassphraseCacheService extends Service {
|
||||
public static final String TAG = Constants.TAG + ": PassphraseCacheService";
|
||||
@ -224,9 +214,9 @@ public class PassphraseCacheService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundValidKey)
|
||||
if (!foundValidKey) {
|
||||
return false;
|
||||
|
||||
}
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
"SC").build("".toCharArray());
|
||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||
|
@ -22,12 +22,12 @@ import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
|
||||
public class AppSettings {
|
||||
private String packageName;
|
||||
private byte[] packageSignature;
|
||||
private long keyId = Id.key.none;
|
||||
private int encryptionAlgorithm;
|
||||
private int hashAlgorithm;
|
||||
private int compression;
|
||||
private String mPackageName;
|
||||
private byte[] mPackageSignature;
|
||||
private long mKeyId = Id.key.none;
|
||||
private int mEncryptionAlgorithm;
|
||||
private int mHashAlgorithm;
|
||||
private int mCompression;
|
||||
|
||||
public AppSettings() {
|
||||
|
||||
@ -35,60 +35,60 @@ public class AppSettings {
|
||||
|
||||
public AppSettings(String packageName, byte[] packageSignature) {
|
||||
super();
|
||||
this.packageName = packageName;
|
||||
this.packageSignature = packageSignature;
|
||||
this.mPackageName = packageName;
|
||||
this.mPackageSignature = packageSignature;
|
||||
// defaults:
|
||||
this.encryptionAlgorithm = PGPEncryptedData.AES_256;
|
||||
this.hashAlgorithm = HashAlgorithmTags.SHA512;
|
||||
this.compression = Id.choice.compression.zlib;
|
||||
this.mEncryptionAlgorithm = PGPEncryptedData.AES_256;
|
||||
this.mHashAlgorithm = HashAlgorithmTags.SHA512;
|
||||
this.mCompression = Id.choice.compression.zlib;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
this.mPackageName = packageName;
|
||||
}
|
||||
|
||||
public byte[] getPackageSignature() {
|
||||
return packageSignature;
|
||||
return mPackageSignature;
|
||||
}
|
||||
|
||||
public void setPackageSignature(byte[] packageSignature) {
|
||||
this.packageSignature = packageSignature;
|
||||
this.mPackageSignature = packageSignature;
|
||||
}
|
||||
|
||||
public long getKeyId() {
|
||||
return keyId;
|
||||
return mKeyId;
|
||||
}
|
||||
|
||||
public void setKeyId(long scretKeyId) {
|
||||
this.keyId = scretKeyId;
|
||||
this.mKeyId = scretKeyId;
|
||||
}
|
||||
|
||||
public int getEncryptionAlgorithm() {
|
||||
return encryptionAlgorithm;
|
||||
return mEncryptionAlgorithm;
|
||||
}
|
||||
|
||||
public void setEncryptionAlgorithm(int encryptionAlgorithm) {
|
||||
this.encryptionAlgorithm = encryptionAlgorithm;
|
||||
this.mEncryptionAlgorithm = encryptionAlgorithm;
|
||||
}
|
||||
|
||||
public int getHashAlgorithm() {
|
||||
return hashAlgorithm;
|
||||
return mHashAlgorithm;
|
||||
}
|
||||
|
||||
public void setHashAlgorithm(int hashAlgorithm) {
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.mHashAlgorithm = hashAlgorithm;
|
||||
}
|
||||
|
||||
public int getCompression() {
|
||||
return compression;
|
||||
return mCompression;
|
||||
}
|
||||
|
||||
public void setCompression(int compression) {
|
||||
this.compression = compression;
|
||||
this.mCompression = compression;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,12 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -30,6 +24,11 @@ import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class AppSettingsActivity extends ActionBarActivity {
|
||||
private Uri mAppUri;
|
||||
@ -41,7 +40,8 @@ public class AppSettingsActivity extends ActionBarActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Inflate a "Done" custom action bar
|
||||
ActionBarHelper.setOneButtonView(getSupportActionBar(), R.string.api_settings_save, R.drawable.ic_action_done,
|
||||
ActionBarHelper.setOneButtonView(getSupportActionBar(),
|
||||
R.string.api_settings_save, R.drawable.ic_action_done,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -17,17 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
|
||||
import org.sufficientlysecure.keychain.util.AlgorithmNames;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
@ -40,20 +29,25 @@ import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.*;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
|
||||
import org.sufficientlysecure.keychain.util.AlgorithmNames;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class AppSettingsFragment extends Fragment implements
|
||||
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
|
||||
|
||||
// model
|
||||
private AppSettings appSettings;
|
||||
private AppSettings mAppSettings;
|
||||
|
||||
// view
|
||||
private LinearLayout mAdvancedSettingsContainer;
|
||||
@ -68,16 +62,16 @@ public class AppSettingsFragment extends Fragment implements
|
||||
|
||||
private SelectSecretKeyLayoutFragment mSelectKeyFragment;
|
||||
|
||||
KeyValueSpinnerAdapter encryptionAdapter;
|
||||
KeyValueSpinnerAdapter hashAdapter;
|
||||
KeyValueSpinnerAdapter compressionAdapter;
|
||||
KeyValueSpinnerAdapter mEncryptionAdapter;
|
||||
KeyValueSpinnerAdapter mHashAdapter;
|
||||
KeyValueSpinnerAdapter mCompressionAdapter;
|
||||
|
||||
public AppSettings getAppSettings() {
|
||||
return appSettings;
|
||||
return mAppSettings;
|
||||
}
|
||||
|
||||
public void setAppSettings(AppSettings appSettings) {
|
||||
this.appSettings = appSettings;
|
||||
this.mAppSettings = appSettings;
|
||||
setPackage(appSettings.getPackageName());
|
||||
mPackageName.setText(appSettings.getPackageName());
|
||||
|
||||
@ -93,10 +87,10 @@ public class AppSettingsFragment extends Fragment implements
|
||||
}
|
||||
|
||||
mSelectKeyFragment.selectKey(appSettings.getKeyId());
|
||||
mEncryptionAlgorithm.setSelection(encryptionAdapter.getPosition(appSettings
|
||||
mEncryptionAlgorithm.setSelection(mEncryptionAdapter.getPosition(appSettings
|
||||
.getEncryptionAlgorithm()));
|
||||
mHashAlgorithm.setSelection(hashAdapter.getPosition(appSettings.getHashAlgorithm()));
|
||||
mCompression.setSelection(compressionAdapter.getPosition(appSettings.getCompression()));
|
||||
mHashAlgorithm.setSelection(mHashAdapter.getPosition(appSettings.getHashAlgorithm()));
|
||||
mCompression.setSelection(mCompressionAdapter.getPosition(appSettings.getCompression()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,14 +133,14 @@ public class AppSettingsFragment extends Fragment implements
|
||||
|
||||
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
|
||||
|
||||
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
mEncryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
algorithmNames.getEncryptionNames());
|
||||
mEncryptionAlgorithm.setAdapter(encryptionAdapter);
|
||||
mEncryptionAlgorithm.setAdapter(mEncryptionAdapter);
|
||||
mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
appSettings.setEncryptionAlgorithm((int) id);
|
||||
mAppSettings.setEncryptionAlgorithm((int) id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -154,13 +148,13 @@ public class AppSettingsFragment extends Fragment implements
|
||||
}
|
||||
});
|
||||
|
||||
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
|
||||
mHashAlgorithm.setAdapter(hashAdapter);
|
||||
mHashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
|
||||
mHashAlgorithm.setAdapter(mHashAdapter);
|
||||
mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
appSettings.setHashAlgorithm((int) id);
|
||||
mAppSettings.setHashAlgorithm((int) id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -168,14 +162,14 @@ public class AppSettingsFragment extends Fragment implements
|
||||
}
|
||||
});
|
||||
|
||||
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
mCompressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||
algorithmNames.getCompressionNames());
|
||||
mCompression.setAdapter(compressionAdapter);
|
||||
mCompression.setAdapter(mCompressionAdapter);
|
||||
mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
appSettings.setCompression((int) id);
|
||||
mAppSettings.setCompression((int) id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -237,7 +231,7 @@ public class AppSettingsFragment extends Fragment implements
|
||||
*/
|
||||
@Override
|
||||
public void onKeySelected(long secretKeyId) {
|
||||
appSettings.setKeyId(secretKeyId);
|
||||
mAppSettings.setKeyId(secretKeyId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import org.openintents.openpgp.IOpenPgpService;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
@ -100,7 +99,8 @@ public class OpenPgpService extends RemoteService {
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds);
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
||||
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_USER_IDS, intent, 0);
|
||||
PendingIntent pi = PendingIntent.getActivity
|
||||
(getBaseContext(), PRIVATE_REQUEST_CODE_USER_IDS, intent, 0);
|
||||
|
||||
// return PendingIntent to be executed by client
|
||||
Intent result = new Intent();
|
||||
@ -126,7 +126,8 @@ public class OpenPgpService extends RemoteService {
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
|
||||
// pass params through to activity that it can be returned again later to repeat pgp operation
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_PASSPHRASE, intent, 0);
|
||||
PendingIntent pi = PendingIntent.getActivity
|
||||
(getBaseContext(), PRIVATE_REQUEST_CODE_PASSPHRASE, intent, 0);
|
||||
|
||||
// return PendingIntent to be executed by client
|
||||
Intent result = new Intent();
|
||||
@ -208,7 +209,8 @@ public class OpenPgpService extends RemoteService {
|
||||
} else {
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_ERROR,
|
||||
new OpenPgpError(OpenPgpError.GENERIC_ERROR, "Missing parameter user_ids or key_ids!"));
|
||||
new OpenPgpError(OpenPgpError.GENERIC_ERROR,
|
||||
"Missing parameter user_ids or key_ids!"));
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
return result;
|
||||
}
|
||||
@ -289,7 +291,8 @@ public class OpenPgpService extends RemoteService {
|
||||
|
||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
|
||||
builder.assumeSymmetric(false) // no support for symmetric encryption
|
||||
.enforcedKeyId(appSettings.getKeyId()) // allow only the private key for this app for decryption
|
||||
// allow only the private key for this app for decryption
|
||||
.enforcedKeyId(appSettings.getKeyId())
|
||||
.passphrase(passphrase);
|
||||
|
||||
// TODO: currently does not support binary signed-only content
|
||||
@ -403,7 +406,8 @@ public class OpenPgpService extends RemoteService {
|
||||
// version code is required and needs to correspond to version code of service!
|
||||
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != OpenPgpApi.API_VERSION) {
|
||||
Intent result = new Intent();
|
||||
OpenPgpError error = new OpenPgpError(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!");
|
||||
OpenPgpError error = new OpenPgpError
|
||||
(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!");
|
||||
result.putExtra(OpenPgpApi.RESULT_ERROR, error);
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
return result;
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@ -31,17 +28,19 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
|
||||
public class RegisteredAppsAdapter extends CursorAdapter {
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
private PackageManager pm;
|
||||
private PackageManager mPM;
|
||||
|
||||
public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
|
||||
super(context, c, flags);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
pm = context.getApplicationContext().getPackageManager();
|
||||
mPM = context.getApplicationContext().getPackageManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,10 +52,10 @@ public class RegisteredAppsAdapter extends CursorAdapter {
|
||||
if (packageName != null) {
|
||||
// get application name
|
||||
try {
|
||||
ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
|
||||
ApplicationInfo ai = mPM.getApplicationInfo(packageName, 0);
|
||||
|
||||
text.setText(pm.getApplicationLabel(ai));
|
||||
icon.setImageDrawable(pm.getApplicationIcon(ai));
|
||||
text.setText(mPM.getApplicationLabel(ai));
|
||||
icon.setImageDrawable(mPM.getApplicationIcon(ai));
|
||||
} catch (final NameNotFoundException e) {
|
||||
// fallback
|
||||
text.setText(packageName);
|
||||
|
@ -17,11 +17,10 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.DrawerActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class RegisteredAppsListActivity extends DrawerActivity {
|
||||
|
||||
@Override
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
@ -33,6 +29,9 @@ import android.support.v4.content.Loader;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
|
||||
public class RegisteredAppsListFragment extends ListFragment implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
@ -17,17 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
@ -38,6 +27,16 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Abstract service class for remote APIs that handle app registration and user input.
|
||||
@ -84,7 +83,8 @@ public abstract class RemoteService extends Service {
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
||||
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
|
||||
PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
|
||||
|
||||
// return PendingIntent to be executed by client
|
||||
Intent result = new Intent();
|
||||
@ -98,10 +98,12 @@ public abstract class RemoteService extends Service {
|
||||
|
||||
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
|
||||
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, getString(R.string.api_error_wrong_signature));
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
|
||||
getString(R.string.api_error_wrong_signature));
|
||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
||||
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_ERROR, intent, 0);
|
||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
|
||||
PRIVATE_REQUEST_CODE_ERROR, intent, 0);
|
||||
|
||||
// return PendingIntent to be executed by client
|
||||
Intent result = new Intent();
|
||||
@ -138,9 +140,10 @@ public abstract class RemoteService extends Service {
|
||||
|
||||
AppSettings settings = ProviderHelper.getApiAppSettings(this, uri);
|
||||
|
||||
if (settings != null)
|
||||
if (settings != null) {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.View;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -88,7 +87,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
||||
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
|
||||
|
||||
// Inflate a "Done"/"Cancel" custom action bar view
|
||||
ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.api_register_allow, R.drawable.ic_action_done,
|
||||
ActionBarHelper.setTwoButtonView(getSupportActionBar(),
|
||||
R.string.api_register_allow, R.drawable.ic_action_done,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -108,7 +108,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
||||
RemoteServiceActivity.this.finish();
|
||||
}
|
||||
}
|
||||
}, R.string.api_register_disallow, R.drawable.ic_action_cancel, new View.OnClickListener() {
|
||||
}, R.string.api_register_disallow, R.drawable.ic_action_cancel,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Disallow
|
||||
@ -161,7 +162,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
// Inflate a "Done"/"Cancel" custom action bar view
|
||||
ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
|
||||
ActionBarHelper.setTwoButtonView(getSupportActionBar(),
|
||||
R.string.btn_okay, R.drawable.ic_action_done,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -214,7 +216,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
||||
String text = "<font color=\"red\">" + errorMessage + "</font>";
|
||||
|
||||
// Inflate a "Done" custom action bar view
|
||||
ActionBarHelper.setOneButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
|
||||
ActionBarHelper.setOneButtonView(getSupportActionBar(),
|
||||
R.string.btn_okay, R.drawable.ic_action_done,
|
||||
new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.service.remote;
|
||||
|
||||
public class WrongPackageSignatureException extends Exception {
|
||||
|
@ -17,8 +17,20 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.*;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSignature;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -33,25 +45,7 @@ import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Signs the specified public key with the specified secret master key
|
||||
|
@ -17,37 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
@ -59,16 +28,34 @@ import android.os.Messenger;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import android.widget.*;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public class DecryptActivity extends DrawerActivity {
|
||||
@ -383,7 +370,7 @@ public class DecryptActivity extends DrawerActivity {
|
||||
if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) {
|
||||
filename = filename.substring(0, filename.length() - 4);
|
||||
}
|
||||
mOutputFilename = Constants.path.APP_DIR + "/" + filename;
|
||||
mOutputFilename = Constants.Path.APP_DIR + "/" + filename;
|
||||
}
|
||||
|
||||
private void updateSource() {
|
||||
@ -532,8 +519,11 @@ public class DecryptActivity extends DrawerActivity {
|
||||
AppMsg.STYLE_ALERT).show();
|
||||
} finally {
|
||||
try {
|
||||
if (inStream != null) inStream.close();
|
||||
} catch (Exception e){ }
|
||||
if (inStream != null) {
|
||||
inStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inStream = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -30,17 +26,14 @@ import android.support.v4.app.ActionBarDrawerToggle;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.*;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.FontAwesomeText;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
|
||||
|
||||
public class DrawerActivity extends ActionBarActivity {
|
||||
private DrawerLayout mDrawerLayout;
|
||||
@ -228,15 +221,15 @@ public class DrawerActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
private class NavigationDrawerAdapter extends ArrayAdapter<NavItem> {
|
||||
Context context;
|
||||
int layoutResourceId;
|
||||
NavItem data[] = null;
|
||||
Context mContext;
|
||||
int mLayoutResourceId;
|
||||
NavItem mData[] = null;
|
||||
|
||||
public NavigationDrawerAdapter(Context context, int layoutResourceId, NavItem[] data) {
|
||||
super(context, layoutResourceId, data);
|
||||
this.layoutResourceId = layoutResourceId;
|
||||
this.context = context;
|
||||
this.data = data;
|
||||
this.mLayoutResourceId = layoutResourceId;
|
||||
this.mContext = context;
|
||||
this.mData = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -245,21 +238,21 @@ public class DrawerActivity extends ActionBarActivity {
|
||||
NavItemHolder holder = null;
|
||||
|
||||
if (row == null) {
|
||||
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
|
||||
row = inflater.inflate(layoutResourceId, parent, false);
|
||||
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
|
||||
row = inflater.inflate(mLayoutResourceId, parent, false);
|
||||
|
||||
holder = new NavItemHolder();
|
||||
holder.img = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon);
|
||||
holder.txtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
|
||||
holder.mImg = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon);
|
||||
holder.mTxtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
|
||||
|
||||
row.setTag(holder);
|
||||
} else {
|
||||
holder = (NavItemHolder) row.getTag();
|
||||
}
|
||||
|
||||
NavItem item = data[position];
|
||||
holder.txtTitle.setText(item.title);
|
||||
holder.img.setIcon(item.icon);
|
||||
NavItem item = mData[position];
|
||||
holder.mTxtTitle.setText(item.title);
|
||||
holder.mImg.setIcon(item.icon);
|
||||
|
||||
return row;
|
||||
}
|
||||
@ -267,8 +260,8 @@ public class DrawerActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
static class NavItemHolder {
|
||||
FontAwesomeText img;
|
||||
TextView txtTitle;
|
||||
FontAwesomeText mImg;
|
||||
TextView mTxtTitle;
|
||||
}
|
||||
|
||||
}
|
@ -17,10 +17,25 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.*;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -44,30 +59,9 @@ import org.sufficientlysecure.keychain.ui.widget.UserIdEditor;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Vector;
|
||||
|
||||
public class EditKeyActivity extends ActionBarActivity {
|
||||
|
||||
@ -104,7 +98,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
Vector<String> mUserIds;
|
||||
Vector<PGPSecretKey> mKeys;
|
||||
Vector<Integer> mKeysUsages;
|
||||
boolean masterCanSign = true;
|
||||
boolean mMasterCanSign = true;
|
||||
|
||||
ExportHelper mExportHelper;
|
||||
|
||||
@ -146,7 +140,8 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
public void onClick(View v) {
|
||||
cancelClicked();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Bundle extras = intent.getExtras();
|
||||
|
||||
@ -269,8 +264,8 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
// get master key id using row id
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
||||
|
||||
masterCanSign = ProviderHelper.getMasterKeyCanSign(this, mDataUri);
|
||||
finallyEdit(masterKeyId, masterCanSign);
|
||||
mMasterCanSign = ProviderHelper.getMasterKeyCanSign(this, mDataUri);
|
||||
finallyEdit(masterKeyId, mMasterCanSign);
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +323,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
return true;
|
||||
case R.id.menu_key_edit_export_file:
|
||||
long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
|
||||
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);
|
||||
return true;
|
||||
case R.id.menu_key_edit_delete: {
|
||||
// Message is received after key is deleted
|
||||
@ -437,12 +432,12 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
|
||||
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||
mUserIdsView.setType(Id.type.user_id);
|
||||
mUserIdsView.setCanEdit(masterCanSign);
|
||||
mUserIdsView.setCanEdit(mMasterCanSign);
|
||||
mUserIdsView.setUserIds(mUserIds);
|
||||
container.addView(mUserIdsView);
|
||||
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||
mKeysView.setType(Id.type.key);
|
||||
mKeysView.setCanEdit(masterCanSign);
|
||||
mKeysView.setCanEdit(mMasterCanSign);
|
||||
mKeysView.setKeys(mKeys, mKeysUsages);
|
||||
container.addView(mKeysView);
|
||||
|
||||
@ -498,12 +493,13 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
String passphrase = null;
|
||||
if (mIsPassPhraseSet)
|
||||
if (mIsPassPhraseSet) {
|
||||
passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
|
||||
else
|
||||
} else {
|
||||
passphrase = "";
|
||||
}
|
||||
if (passphrase == null) {
|
||||
showPassphraseDialog(masterKeyId, masterCanSign);
|
||||
showPassphraseDialog(masterKeyId, mMasterCanSign);
|
||||
} else {
|
||||
mCurrentPassphrase = passphrase;
|
||||
finallySaveClicked();
|
||||
@ -536,7 +532,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
data.putSerializable(KeychainIntentService.SAVE_KEYRING_KEYS_EXPIRY_DATES,
|
||||
getKeysExpiryDates(mKeysView));
|
||||
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
|
||||
data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, masterCanSign);
|
||||
data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, mMasterCanSign);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
|
||||
@ -604,8 +600,6 @@ public class EditKeyActivity extends ActionBarActivity {
|
||||
} catch (UserIdEditor.NoEmailException e) {
|
||||
throw new PgpGeneralException(
|
||||
this.getString(R.string.error_user_id_needs_an_email_address));
|
||||
} catch (UserIdEditor.InvalidEmailException e) {
|
||||
throw new PgpGeneralException(e.getMessage());
|
||||
}
|
||||
|
||||
if (userId.equals("")) {
|
||||
|
@ -17,9 +17,22 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.*;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import com.beardedhen.androidbootstrap.FontAwesomeText;
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
@ -43,31 +56,8 @@ import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Choice;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import com.beardedhen.androidbootstrap.FontAwesomeText;
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
|
||||
public class EncryptActivity extends DrawerActivity {
|
||||
|
||||
|
@ -17,11 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
@ -31,6 +26,10 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
|
||||
public class HelpAboutFragment extends Fragment {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
@ -17,19 +17,16 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
|
||||
|
||||
public class HelpActivity extends ActionBarActivity {
|
||||
public static final String EXTRA_SELECTED_TAB = "selectedTab";
|
||||
public static final String EXTRA_SELECTED_TAB = "selected_tab";
|
||||
|
||||
ViewPager mViewPager;
|
||||
TabsAdapter mTabsAdapter;
|
||||
@ -61,17 +58,22 @@ public class HelpActivity extends ActionBarActivity {
|
||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_start)),
|
||||
HelpHtmlFragment.class, startBundle, (selectedTab == 0));
|
||||
|
||||
Bundle faqBundle = new Bundle();
|
||||
faqBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_faq);
|
||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_faq)),
|
||||
HelpHtmlFragment.class, faqBundle, (selectedTab == 1));
|
||||
|
||||
Bundle nfcBundle = new Bundle();
|
||||
nfcBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_nfc_beam);
|
||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_nfc_beam)),
|
||||
HelpHtmlFragment.class, nfcBundle, (selectedTab == 1) );
|
||||
HelpHtmlFragment.class, nfcBundle, (selectedTab == 2));
|
||||
|
||||
Bundle changelogBundle = new Bundle();
|
||||
changelogBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_changelog);
|
||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_changelog)),
|
||||
HelpHtmlFragment.class, changelogBundle, (selectedTab == 2) );
|
||||
HelpHtmlFragment.class, changelogBundle, (selectedTab == 3));
|
||||
|
||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_about)),
|
||||
HelpAboutFragment.class, null, (selectedTab == 3) );
|
||||
HelpAboutFragment.class, null, (selectedTab == 4));
|
||||
}
|
||||
}
|
@ -17,8 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -27,11 +25,12 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
|
||||
public class HelpHtmlFragment extends Fragment {
|
||||
private Activity mActivity;
|
||||
|
||||
private int htmlFile;
|
||||
private int mHtmlFile;
|
||||
|
||||
public static final String ARG_HTML_FILE = "htmlFile";
|
||||
|
||||
@ -53,7 +52,7 @@ public class HelpHtmlFragment extends Fragment {
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mActivity = getActivity();
|
||||
|
||||
htmlFile = getArguments().getInt(ARG_HTML_FILE);
|
||||
mHtmlFile = getArguments().getInt(ARG_HTML_FILE);
|
||||
|
||||
ScrollView scroller = new ScrollView(mActivity);
|
||||
HtmlTextView text = new HtmlTextView(mActivity);
|
||||
@ -66,7 +65,7 @@ public class HelpHtmlFragment extends Fragment {
|
||||
scroller.addView(text);
|
||||
|
||||
// load html from raw resource (Parsing handled by HtmlTextView library)
|
||||
text.setHtmlFromRawResource(getActivity(), htmlFile);
|
||||
text.setHtmlFromRawResource(getActivity(), mHtmlFile);
|
||||
|
||||
// no flickering when clicking textview for Android < 4
|
||||
text.setTextColor(getResources().getColor(android.R.color.black));
|
||||
|
@ -34,10 +34,8 @@ import android.support.v7.app.ActionBar;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
@ -169,7 +167,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
|
||||
query = "0x" + fingerprint;
|
||||
}
|
||||
} else {
|
||||
Log.e(Constants.TAG, "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or 'fingerprint' extra!");
|
||||
Log.e(Constants.TAG,
|
||||
"IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or 'fingerprint' extra!");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -400,7 +399,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
|
||||
AppMsg.makeText(ImportKeysActivity.this, toastMessage, AppMsg.STYLE_INFO)
|
||||
.show();
|
||||
if (bad > 0) {
|
||||
BadImportKeyDialogFragment badImportKeyDialogFragment = BadImportKeyDialogFragment.newInstance(bad);
|
||||
BadImportKeyDialogFragment badImportKeyDialogFragment =
|
||||
BadImportKeyDialogFragment.newInstance(bad);
|
||||
badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog");
|
||||
}
|
||||
}
|
||||
|
@ -17,17 +17,15 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||
|
||||
public class ImportKeysClipboardFragment extends Fragment {
|
||||
|
||||
@ -60,8 +58,9 @@ public class ImportKeysClipboardFragment extends Fragment {
|
||||
public void onClick(View v) {
|
||||
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
||||
String sendText = "";
|
||||
if (clipboardText != null)
|
||||
if (clipboardText != null) {
|
||||
sendText = clipboardText.toString();
|
||||
}
|
||||
mImportActivity.loadCallback(sendText.getBytes(), null, null, null);
|
||||
}
|
||||
});
|
||||
|
@ -17,11 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@ -29,8 +24,11 @@ import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
|
||||
public class ImportKeysFileFragment extends Fragment {
|
||||
private ImportKeysActivity mImportActivity;
|
||||
@ -62,7 +60,7 @@ public class ImportKeysFileFragment extends Fragment {
|
||||
// open .asc or .gpg files
|
||||
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
|
||||
// or gpg types!
|
||||
FileHelper.openFile(ImportKeysFileFragment.this, Constants.path.APP_DIR + "/",
|
||||
FileHelper.openFile(ImportKeysFileFragment.this, Constants.Path.APP_DIR + "/",
|
||||
"*/*", Id.request.filename);
|
||||
}
|
||||
});
|
||||
|
@ -17,25 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -44,8 +25,21 @@ import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.*;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportKeysListFragment extends ListFragment implements
|
||||
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||
@ -184,7 +178,8 @@ public class ImportKeysListFragment extends ListFragment implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) {
|
||||
public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>>
|
||||
onCreateLoader(int id, Bundle args) {
|
||||
switch (id) {
|
||||
case LOADER_ID_BYTES: {
|
||||
InputData inputData = getInputData(mKeyBytes, mDataUri);
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -26,8 +24,8 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
public class ImportKeysNFCFragment extends Fragment {
|
||||
|
||||
|
@ -17,14 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -36,9 +28,15 @@ import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ImportKeysQrCodeFragment extends Fragment {
|
||||
|
||||
|
@ -17,11 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -36,8 +31,11 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class ImportKeysServerFragment extends Fragment {
|
||||
public static final String ARG_QUERY = "query";
|
||||
@ -96,7 +94,8 @@ public class ImportKeysServerFragment extends Fragment {
|
||||
search(query, keyServer);
|
||||
|
||||
// close keyboard after pressing search
|
||||
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
InputMethodManager imm =
|
||||
(InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mQueryEditText.getWindowToken(), 0);
|
||||
}
|
||||
});
|
||||
@ -110,7 +109,6 @@ public class ImportKeysServerFragment extends Fragment {
|
||||
search(query, keyServer);
|
||||
|
||||
// Don't return true to let the keyboard close itself after pressing search
|
||||
// http://stackoverflow.com/questions/2342620/how-to-hide-keyboard-after-typing-in-edittext-in-android
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
@ -17,15 +17,14 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
|
||||
public class KeyListActivity extends DrawerActivity {
|
||||
|
||||
@ -60,7 +59,19 @@ public class KeyListActivity extends DrawerActivity {
|
||||
return true;
|
||||
case R.id.menu_key_list_export:
|
||||
// TODO fix this for unified keylist
|
||||
mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.path.APP_DIR_FILE_PUB);
|
||||
mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB);
|
||||
|
||||
return true;
|
||||
case R.id.menu_key_list_create:
|
||||
createKey();
|
||||
|
||||
return true;
|
||||
case R.id.menu_key_list_create_expert:
|
||||
createKeyExpert();
|
||||
|
||||
return true;
|
||||
case R.id.menu_key_list_secret_export:
|
||||
mExportHelper.showExportKeysDialog(null, Id.type.secret_key, Constants.Path.APP_DIR_FILE_SEC);
|
||||
|
||||
return true;
|
||||
default:
|
||||
@ -68,4 +79,18 @@ public class KeyListActivity extends DrawerActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void createKey() {
|
||||
Intent intent = new Intent(this, EditKeyActivity.class);
|
||||
intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
|
||||
intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
|
||||
intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view
|
||||
startActivityForResult(intent, 0);
|
||||
}
|
||||
|
||||
private void createKeyExpert() {
|
||||
Intent intent = new Intent(this, EditKeyActivity.class);
|
||||
intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
|
||||
startActivityForResult(intent, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
@ -17,28 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
@ -46,45 +24,47 @@ import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.*;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
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.*;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.*;
|
||||
import android.widget.AbsListView.MultiChoiceModeListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.HighlightQueryCursorAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
|
||||
* StickyListHeaders library which does not extend upon ListView.
|
||||
*/
|
||||
public class KeyListFragment extends Fragment implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener,
|
||||
public class KeyListFragment extends Fragment
|
||||
implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener,
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
private KeyListAdapter mAdapter;
|
||||
@ -202,6 +182,23 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
showDeleteKeyDialog(mode, ids);
|
||||
break;
|
||||
}
|
||||
case R.id.menu_key_list_multi_export: {
|
||||
// todo: public/secret needs to be handled differently here
|
||||
ids = mStickyList.getWrappedList().getCheckedItemIds();
|
||||
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
|
||||
mExportHelper
|
||||
.showExportKeysDialog(ids,
|
||||
Id.type.public_key,
|
||||
Constants.Path.APP_DIR_FILE_PUB);
|
||||
break;
|
||||
}
|
||||
case R.id.menu_key_list_multi_select_all: {
|
||||
// select all
|
||||
for (int i = 0; i < mStickyList.getCount(); i++) {
|
||||
mStickyList.setItemChecked(i, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -254,8 +251,15 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
};
|
||||
|
||||
static final int INDEX_TYPE = 1;
|
||||
static final int INDEX_UID = 3;
|
||||
static final String SORT_ORDER = UserIds.USER_ID + " ASC";
|
||||
static final int INDEX_MASTER_KEY_ID = 2;
|
||||
static final int INDEX_USER_ID = 3;
|
||||
static final int INDEX_IS_REVOKED = 4;
|
||||
|
||||
static final String SORT_ORDER =
|
||||
// show secret before public key
|
||||
KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings.TYPE + " DESC, "
|
||||
// sort by user id otherwise
|
||||
+ UserIds.USER_ID + " ASC";
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
@ -310,9 +314,10 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
} else {
|
||||
viewIntent = new Intent(getActivity(), ViewKeyActivityJB.class);
|
||||
}
|
||||
viewIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsByMasterKeyIdUri(
|
||||
Long.toString(mAdapter.getMasterKeyId(position)))
|
||||
);
|
||||
viewIntent.setData(
|
||||
KeychainContract
|
||||
.KeyRings.buildPublicKeyRingsByMasterKeyIdUri(
|
||||
Long.toString(mAdapter.getMasterKeyId(position))));
|
||||
startActivity(viewIntent);
|
||||
}
|
||||
|
||||
@ -349,8 +354,12 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
for (String userId : notDeleted) {
|
||||
notDeletedMsg += userId + "\n";
|
||||
}
|
||||
Toast.makeText(getActivity(), getString(R.string.error_can_not_delete_contacts, notDeletedMsg)
|
||||
+ getResources().getQuantityString(R.plurals.error_can_not_delete_info, notDeleted.size()),
|
||||
Toast.makeText(getActivity(),
|
||||
getString(R.string.error_can_not_delete_contacts, notDeletedMsg)
|
||||
+ getResources()
|
||||
.getQuantityString(
|
||||
R.plurals.error_can_not_delete_info,
|
||||
notDeleted.size()),
|
||||
Toast.LENGTH_LONG).show();
|
||||
|
||||
mode.finish();
|
||||
@ -452,45 +461,22 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
/**
|
||||
* Implements StickyListHeadersAdapter from library
|
||||
*/
|
||||
private class KeyListAdapter extends CursorAdapter implements StickyListHeadersAdapter {
|
||||
private class KeyListAdapter extends HighlightQueryCursorAdapter implements StickyListHeadersAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
private int mIndexUserId;
|
||||
private int mIndexIsRevoked;
|
||||
private int mMasterKeyId;
|
||||
|
||||
private String mCurQuery;
|
||||
|
||||
@SuppressLint("UseSparseArrays")
|
||||
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
|
||||
|
||||
public KeyListAdapter(Context context, Cursor c, int flags) {
|
||||
super(context, c, flags);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
initIndex(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor swapCursor(Cursor newCursor) {
|
||||
initIndex(newCursor);
|
||||
|
||||
return super.swapCursor(newCursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
||||
* performance comparison see http://stackoverflow.com/a/17999582
|
||||
*
|
||||
* @param cursor
|
||||
*/
|
||||
private void initIndex(Cursor cursor) {
|
||||
if (cursor != null) {
|
||||
mIndexUserId = cursor.getColumnIndexOrThrow(KeychainContract.UserIds.USER_ID);
|
||||
mIndexIsRevoked = cursor.getColumnIndexOrThrow(KeychainContract.Keys.IS_REVOKED);
|
||||
mMasterKeyId = cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.MASTER_KEY_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind cursor data to the item list view
|
||||
* <p/>
|
||||
@ -504,7 +490,7 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
||||
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
|
||||
|
||||
String userId = cursor.getString(mIndexUserId);
|
||||
String userId = cursor.getString(INDEX_USER_ID);
|
||||
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
|
||||
if (userIdSplit[0] != null) {
|
||||
mainUserId.setText(highlightSearchQuery(userIdSplit[0]));
|
||||
@ -528,7 +514,7 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
revoked.setVisibility(View.GONE);
|
||||
button.setVisibility(View.VISIBLE);
|
||||
|
||||
final long id = cursor.getLong(mMasterKeyId);
|
||||
final long id = cursor.getLong(INDEX_MASTER_KEY_ID);
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
|
||||
@ -545,7 +531,7 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
// this is a public key - hide the edit button, show if it's revoked
|
||||
button.setVisibility(View.GONE);
|
||||
|
||||
boolean isRevoked = cursor.getInt(mIndexIsRevoked) > 0;
|
||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
||||
revoked.setVisibility(isRevoked ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
@ -553,23 +539,11 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
}
|
||||
|
||||
public long getMasterKeyId(int id) {
|
||||
|
||||
if (!mCursor.moveToPosition(id)) {
|
||||
throw new IllegalStateException("couldn't move cursor to position " + id);
|
||||
}
|
||||
|
||||
return mCursor.getLong(mMasterKeyId);
|
||||
|
||||
}
|
||||
|
||||
public int getKeyType(int position) {
|
||||
|
||||
if (!mCursor.moveToPosition(position)) {
|
||||
throw new IllegalStateException("couldn't move cursor to position " + position);
|
||||
}
|
||||
|
||||
return mCursor.getInt(KeyListFragment.INDEX_TYPE);
|
||||
|
||||
return mCursor.getLong(INDEX_MASTER_KEY_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -590,8 +564,8 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
if (convertView == null) {
|
||||
holder = new HeaderViewHolder();
|
||||
convertView = mInflater.inflate(R.layout.key_list_header, parent, false);
|
||||
holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
|
||||
holder.count = (TextView) convertView.findViewById(R.id.contacts_num);
|
||||
holder.mText = (TextView) convertView.findViewById(R.id.stickylist_header_text);
|
||||
holder.mCount = (TextView) convertView.findViewById(R.id.contacts_num);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (HeaderViewHolder) convertView.getTag();
|
||||
@ -611,22 +585,22 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
{ // set contact count
|
||||
int num = mCursor.getCount();
|
||||
String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num);
|
||||
holder.count.setText(contactsTotal);
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
holder.mCount.setText(contactsTotal);
|
||||
holder.mCount.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
holder.text.setText(convertView.getResources().getString(R.string.my_keys));
|
||||
holder.mText.setText(convertView.getResources().getString(R.string.my_keys));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
// set header text as first char in user id
|
||||
String userId = mCursor.getString(KeyListFragment.INDEX_UID);
|
||||
String userId = mCursor.getString(KeyListFragment.INDEX_USER_ID);
|
||||
String headerText = convertView.getResources().getString(R.string.user_id_no_name);
|
||||
if (userId != null && userId.length() > 0) {
|
||||
headerText = "" + userId.subSequence(0, 1).charAt(0);
|
||||
}
|
||||
holder.text.setText(headerText);
|
||||
holder.count.setVisibility(View.GONE);
|
||||
holder.mText.setText(headerText);
|
||||
holder.mCount.setVisibility(View.GONE);
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@ -646,11 +620,11 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
}
|
||||
|
||||
// early breakout: all secret keys are assigned id 0
|
||||
if(mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET)
|
||||
if (mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) {
|
||||
return 1L;
|
||||
|
||||
}
|
||||
// otherwise, return the first character of the name as ID
|
||||
String userId = mCursor.getString(KeyListFragment.INDEX_UID);
|
||||
String userId = mCursor.getString(KeyListFragment.INDEX_USER_ID);
|
||||
if (userId != null && userId.length() > 0) {
|
||||
return userId.charAt(0);
|
||||
} else {
|
||||
@ -659,8 +633,8 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
}
|
||||
|
||||
class HeaderViewHolder {
|
||||
TextView text;
|
||||
TextView count;
|
||||
TextView mText;
|
||||
TextView mCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -675,8 +649,9 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
long[] ids = new long[mSelection.size()];
|
||||
int i = 0;
|
||||
// get master key ids
|
||||
for (int pos : mSelection.keySet())
|
||||
for (int pos : mSelection.keySet()) {
|
||||
ids[i++] = mAdapter.getMasterKeyId(pos);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
@ -698,43 +673,17 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
||||
/**
|
||||
* Change color for multi-selection
|
||||
*/
|
||||
if (mSelection.get(position) != null) {
|
||||
// selected position color
|
||||
v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
|
||||
} else {
|
||||
// default color
|
||||
v.setBackgroundColor(Color.TRANSPARENT);
|
||||
if (mSelection.get(position) != null) {
|
||||
// this is a selected position, change color!
|
||||
v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// search highlight methods
|
||||
|
||||
public void setSearchQuery(String searchQuery) {
|
||||
mCurQuery = searchQuery;
|
||||
}
|
||||
|
||||
public String getSearchQuery() {
|
||||
return mCurQuery;
|
||||
}
|
||||
|
||||
protected Spannable highlightSearchQuery(String text) {
|
||||
Spannable highlight = Spannable.Factory.getInstance().newSpannable(text);
|
||||
|
||||
if (mCurQuery != null) {
|
||||
Pattern pattern = Pattern.compile("(?i)" + mCurQuery);
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
if (matcher.find()) {
|
||||
highlight.setSpan(
|
||||
new ForegroundColorSpan(mContext.getResources().getColor(R.color.emphasis)),
|
||||
matcher.start(),
|
||||
matcher.end(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
return highlight;
|
||||
} else {
|
||||
return highlight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,11 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.*;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -24,24 +29,13 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public class PreferencesActivity extends PreferenceActivity {
|
||||
|
||||
public final static String ACTION_PREFS_GEN = "org.sufficientlysecure.keychain.ui.PREFS_GEN";
|
||||
public final static String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
|
||||
public static final String ACTION_PREFS_GEN = "org.sufficientlysecure.keychain.ui.PREFS_GEN";
|
||||
public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
|
||||
|
||||
private PreferenceScreen mKeyServerPreference = null;
|
||||
private static Preferences mPreferences;
|
||||
@ -62,9 +56,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.gen_preferences);
|
||||
|
||||
initializePassPassPhraceCacheTtl(
|
||||
(IntegerListPreference) findPreference(Constants.pref.PASS_PHRASE_CACHE_TTL));
|
||||
(IntegerListPreference) findPreference(Constants.Pref.PASS_PHRASE_CACHE_TTL));
|
||||
|
||||
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.pref.KEY_SERVERS);
|
||||
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS);
|
||||
String servers[] = mPreferences.getKeyServers();
|
||||
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
||||
servers.length, servers.length));
|
||||
@ -84,7 +78,7 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.adv_preferences);
|
||||
|
||||
initializeEncryptionAlgorithm(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM));
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM));
|
||||
|
||||
int[] valueIds = new int[]{Id.choice.compression.none, Id.choice.compression.zip,
|
||||
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
||||
@ -99,20 +93,22 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
}
|
||||
|
||||
initializeHashAlgorithm(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_HASH_ALGORITHM),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM),
|
||||
valueIds, entries, values);
|
||||
|
||||
initializeMessageCompression(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||
valueIds, entries, values);
|
||||
|
||||
initializeFileCompression(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_FILE_COMPRESSION),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
|
||||
entries, values);
|
||||
|
||||
initializeAsciiArmour((CheckBoxPreference) findPreference(Constants.pref.DEFAULT_ASCII_ARMOUR));
|
||||
initializeAsciiArmour(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOUR));
|
||||
|
||||
initializeForceV3Signatures((CheckBoxPreference) findPreference(Constants.pref.FORCE_V3_SIGNATURES));
|
||||
initializeForceV3Signatures(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
|
||||
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||
// Load the legacy preferences headers
|
||||
@ -149,7 +145,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
loadHeadersFromResource(R.xml.preference_headers, target);
|
||||
}
|
||||
|
||||
/** This fragment shows the general preferences in android 3.0+ */
|
||||
/**
|
||||
* This fragment shows the general preferences in android 3.0+
|
||||
*/
|
||||
public static class GeneralPrefsFragment extends PreferenceFragment {
|
||||
|
||||
private PreferenceScreen mKeyServerPreference = null;
|
||||
@ -162,9 +160,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.gen_preferences);
|
||||
|
||||
initializePassPassPhraceCacheTtl(
|
||||
(IntegerListPreference) findPreference(Constants.pref.PASS_PHRASE_CACHE_TTL));
|
||||
(IntegerListPreference) findPreference(Constants.Pref.PASS_PHRASE_CACHE_TTL));
|
||||
|
||||
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.pref.KEY_SERVERS);
|
||||
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS);
|
||||
String servers[] = mPreferences.getKeyServers();
|
||||
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
||||
servers.length, servers.length));
|
||||
@ -204,7 +202,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/** This fragment shows the advanced preferences in android 3.0+ */
|
||||
/**
|
||||
* This fragment shows the advanced preferences in android 3.0+
|
||||
*/
|
||||
public static class AdvancedPrefsFragment extends PreferenceFragment {
|
||||
|
||||
@Override
|
||||
@ -215,7 +215,7 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.adv_preferences);
|
||||
|
||||
initializeEncryptionAlgorithm(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM));
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM));
|
||||
|
||||
int[] valueIds = new int[]{Id.choice.compression.none, Id.choice.compression.zip,
|
||||
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
||||
@ -230,20 +230,22 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
}
|
||||
|
||||
initializeHashAlgorithm(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_HASH_ALGORITHM),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM),
|
||||
valueIds, entries, values);
|
||||
|
||||
initializeMessageCompression(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||
valueIds, entries, values);
|
||||
|
||||
initializeFileCompression(
|
||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_FILE_COMPRESSION),
|
||||
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
|
||||
entries, values);
|
||||
|
||||
initializeAsciiArmour((CheckBoxPreference) findPreference(Constants.pref.DEFAULT_ASCII_ARMOUR));
|
||||
initializeAsciiArmour(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOUR));
|
||||
|
||||
initializeForceV3Signatures((CheckBoxPreference) findPreference(Constants.pref.FORCE_V3_SIGNATURES));
|
||||
initializeForceV3Signatures(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,8 +321,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private static void initializeMessageCompression
|
||||
(final IntegerListPreference mMessageCompression, int[] valueIds, String[] entries, String[] values) {
|
||||
private static void initializeMessageCompression(
|
||||
final IntegerListPreference mMessageCompression,
|
||||
int[] valueIds, String[] entries, String[] values) {
|
||||
mMessageCompression.setEntries(entries);
|
||||
mMessageCompression.setEntryValues(values);
|
||||
mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression());
|
||||
|
@ -16,14 +16,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.ui.widget.Editor;
|
||||
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@ -33,6 +25,13 @@ import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.ui.widget.Editor;
|
||||
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
public class PreferencesKeyServerActivity extends ActionBarActivity implements OnClickListener,
|
||||
EditorListener {
|
||||
@ -63,7 +62,8 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
|
||||
// cancel
|
||||
cancelClicked();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
setContentView(R.layout.key_server_preference);
|
||||
|
||||
|
@ -17,14 +17,13 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.View;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
|
||||
public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||
|
||||
@ -39,7 +38,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||
|
||||
SelectPublicKeyFragment mSelectFragment;
|
||||
|
||||
long selectedMasterKeyIds[];
|
||||
long mSelectedMasterKeyIds[];
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -59,7 +58,8 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||
// cancel
|
||||
cancelClicked();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
setContentView(R.layout.select_public_key_activity);
|
||||
|
||||
@ -79,7 +79,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
// Create an instance of the fragment
|
||||
mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
|
||||
mSelectFragment = SelectPublicKeyFragment.newInstance(mSelectedMasterKeyIds);
|
||||
|
||||
// Add the fragment to the 'fragment_container' FrameLayout
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
@ -124,7 +124,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||
// }
|
||||
|
||||
// preselected master keys
|
||||
selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
|
||||
mSelectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
|
||||
}
|
||||
|
||||
private void cancelClicked() {
|
||||
|
@ -17,19 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
@ -45,12 +32,19 @@ import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
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 android.widget.*;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Vector;
|
||||
|
||||
public class SelectPublicKeyFragment extends ListFragmentWorkaround implements TextWatcher,
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
@ -138,7 +132,8 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
||||
mSearchView = new EditText(context);
|
||||
mSearchView.setId(SEARCH_ID);
|
||||
mSearchView.setHint(R.string.menu_search);
|
||||
mSearchView.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_action_search), null, null, null);
|
||||
mSearchView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
getResources().getDrawable(R.drawable.ic_action_search), null, null, null);
|
||||
|
||||
linearLayout.addView(mSearchView, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
@ -17,14 +17,13 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.Menu;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
public class SelectSecretKeyActivity extends ActionBarActivity {
|
||||
|
||||
|
@ -17,17 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -39,6 +28,16 @@ import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListView;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class SelectSecretKeyFragment extends ListFragment implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
@ -17,6 +17,16 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
@ -24,21 +34,6 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
|
||||
public class SelectSecretKeyLayoutFragment extends Fragment {
|
||||
|
||||
private TextView mKeyUserId;
|
||||
@ -106,7 +101,10 @@ public class SelectSecretKeyLayoutFragment extends Fragment {
|
||||
mKeyUserIdRest.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
mKeyMasterKeyIdHex.setText(getActivity().getResources().getString(R.string.no_keys_added_or_updated) + " for master id: " + secretKeyId);
|
||||
mKeyMasterKeyIdHex.setText(
|
||||
getActivity().getResources()
|
||||
.getString(R.string.no_keys_added_or_updated)
|
||||
+ " for master id: " + secretKeyId);
|
||||
mKeyUserId.setVisibility(View.GONE);
|
||||
mKeyUserIdRest.setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -17,13 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@ -36,8 +29,13 @@ import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
/**
|
||||
* Sends the selected public key to a keyserver
|
||||
|
@ -29,7 +29,6 @@ import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -124,7 +123,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
return true;
|
||||
case R.id.menu_key_view_export_file:
|
||||
long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
|
||||
mExportHelper.showExportKeysDialog(ids, Id.type.public_key, Constants.path.APP_DIR_FILE_PUB);
|
||||
mExportHelper.showExportKeysDialog(ids, Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB);
|
||||
return true;
|
||||
case R.id.menu_key_view_share_default_fingerprint:
|
||||
shareKey(mDataUri, true);
|
||||
@ -240,7 +239,8 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
// we delete only this key, so MESSAGE_NOT_DELETED will solely contain this key
|
||||
Toast.makeText(ViewKeyActivity.this,
|
||||
getString(R.string.error_can_not_delete_contact)
|
||||
+ getResources().getQuantityString(R.plurals.error_can_not_delete_info, 1),
|
||||
+ getResources()
|
||||
.getQuantityString(R.plurals.error_can_not_delete_info, 1),
|
||||
Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
setResult(RESULT_CANCELED);
|
||||
|
@ -18,10 +18,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NdefMessage;
|
||||
@ -35,6 +31,9 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
|
||||
|
@ -42,6 +42,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
|
||||
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
|
||||
|
@ -35,11 +35,10 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
@ -143,7 +142,10 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
mActionEdit.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
|
||||
editIntent.setData(KeychainContract.KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)));
|
||||
editIntent.setData(
|
||||
KeychainContract
|
||||
.KeyRings.buildSecretKeyRingsByMasterKeyIdUri(
|
||||
Long.toString(masterKeyId)));
|
||||
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
|
||||
startActivityForResult(editIntent, 0);
|
||||
}
|
||||
@ -188,21 +190,29 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
|
||||
}
|
||||
|
||||
static final String[] KEYRING_PROJECTION = new String[]{KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID,
|
||||
static final String[] KEYRING_PROJECTION =
|
||||
new String[]{KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID,
|
||||
KeychainContract.UserIds.USER_ID};
|
||||
static final int KEYRING_INDEX_ID = 0;
|
||||
static final int KEYRING_INDEX_MASTER_KEY_ID = 1;
|
||||
static final int KEYRING_INDEX_USER_ID = 2;
|
||||
|
||||
static final String[] USER_IDS_PROJECTION = new String[]{ KeychainContract.UserIds._ID, KeychainContract.UserIds.USER_ID,
|
||||
KeychainContract.UserIds.RANK, "verified" };
|
||||
static final String[] USER_IDS_PROJECTION =
|
||||
new String[]{KeychainContract.UserIds._ID, KeychainContract.UserIds.USER_ID,
|
||||
KeychainContract.UserIds.RANK, };
|
||||
// not the main user id
|
||||
static final String USER_IDS_SELECTION = KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " > 0 ";
|
||||
static final String USER_IDS_SORT_ORDER = KeychainContract.UserIds.USER_ID + " COLLATE LOCALIZED ASC";
|
||||
static final String USER_IDS_SELECTION =
|
||||
KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " > 0 ";
|
||||
static final String USER_IDS_SORT_ORDER =
|
||||
KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.USER_ID + " COLLATE LOCALIZED ASC";
|
||||
|
||||
static final String[] KEYS_PROJECTION = new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
|
||||
KeychainContract.Keys.IS_MASTER_KEY, KeychainContract.Keys.ALGORITHM, KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY, KeychainContract.Keys.CAN_SIGN,
|
||||
KeychainContract.Keys.CAN_ENCRYPT, KeychainContract.Keys.CREATION, KeychainContract.Keys.EXPIRY, KeychainContract.Keys.FINGERPRINT};
|
||||
static final String[] KEYS_PROJECTION =
|
||||
new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
|
||||
KeychainContract.Keys.IS_MASTER_KEY, KeychainContract.Keys.ALGORITHM,
|
||||
KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY,
|
||||
KeychainContract.Keys.CAN_SIGN, KeychainContract.Keys.CAN_ENCRYPT,
|
||||
KeychainContract.Keys.CREATION, KeychainContract.Keys.EXPIRY,
|
||||
KeychainContract.Keys.FINGERPRINT};
|
||||
static final String KEYS_SORT_ORDER = KeychainContract.Keys.RANK + " ASC";
|
||||
static final int KEYS_INDEX_ID = 0;
|
||||
static final int KEYS_INDEX_KEY_ID = 1;
|
||||
@ -285,7 +295,8 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
} else {
|
||||
Date creationDate = new Date(data.getLong(KEYS_INDEX_CREATION) * 1000);
|
||||
|
||||
mCreation.setText(DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
|
||||
mCreation.setText(
|
||||
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
|
||||
creationDate));
|
||||
}
|
||||
|
||||
@ -295,7 +306,8 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
} else {
|
||||
Date expiryDate = new Date(data.getLong(KEYS_INDEX_EXPIRY) * 1000);
|
||||
|
||||
mExpiry.setText(DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
|
||||
mExpiry.setText(
|
||||
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
|
||||
expiryDate));
|
||||
}
|
||||
|
||||
@ -323,18 +335,56 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
|
||||
private SpannableStringBuilder colorizeFingerprint(String fingerprint) {
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder(fingerprint);
|
||||
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.BLACK);
|
||||
|
||||
try {
|
||||
// for each 4 characters of the fingerprint + 1 space
|
||||
for (int i = 0; i < fingerprint.length(); i += 5) {
|
||||
int minFingLength = Math.min(i + 4, fingerprint.length());
|
||||
String fourChars = fingerprint.substring(i, minFingLength);
|
||||
int spanEnd = Math.min(i + 4, fingerprint.length());
|
||||
String fourChars = fingerprint.substring(i, spanEnd);
|
||||
|
||||
// Create a foreground color by converting the 4 fingerprint chars to an int hashcode
|
||||
int raw = Integer.parseInt(fourChars, 16);
|
||||
byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)};
|
||||
int[] color = OtherHelper.getRgbForData(bytes);
|
||||
int r = color[0];
|
||||
int g = color[1];
|
||||
int b = color[2];
|
||||
|
||||
// we cannot change black by multiplication, so adjust it to an almost-black grey,
|
||||
// which will then be brightened to the minimal brightness level
|
||||
if (r == 0 && g == 0 && b == 0) {
|
||||
r = 1;
|
||||
g = 1;
|
||||
b = 1;
|
||||
}
|
||||
|
||||
// Convert rgb to brightness
|
||||
double brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
|
||||
// If a color is too dark to be seen on black,
|
||||
// then brighten it up to a minimal brightness.
|
||||
if (brightness < 80) {
|
||||
double factor = 80.0 / brightness;
|
||||
r = Math.min(255, (int) (r * factor));
|
||||
g = Math.min(255, (int) (g * factor));
|
||||
b = Math.min(255, (int) (b * factor));
|
||||
|
||||
// If it is too light, then darken it to a respective maximal brightness.
|
||||
} else if (brightness > 180) {
|
||||
double factor = 180.0 / brightness;
|
||||
r = (int) (r * factor);
|
||||
g = (int) (g * factor);
|
||||
b = (int) (b * factor);
|
||||
}
|
||||
|
||||
// Create a foreground color with the 3 digest integers as RGB
|
||||
// and then converting that int to hex to use as a color
|
||||
fcs = new ForegroundColorSpan(
|
||||
Color.parseColor(String.format("#%06X", (0xFFFFFF & fourChars.hashCode()))));
|
||||
sb.setSpan(fcs, i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new ForegroundColorSpan(Color.rgb(r, g, b)),
|
||||
i, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "Colorization failed", e);
|
||||
// if anything goes wrong, then just display the fingerprint without colour,
|
||||
// instead of partially correct colour or wrong colours
|
||||
return new SpannableStringBuilder(fingerprint);
|
||||
}
|
||||
|
||||
return sb;
|
||||
@ -377,5 +427,4 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
startActivity(signIntent);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -22,24 +22,25 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
||||
* You can pass the result and an exception in it if an error occurred.
|
||||
* Concept found at:
|
||||
* https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader
|
||||
*
|
||||
* @param <T> - Typ of the result which is wrapped
|
||||
*/
|
||||
public class AsyncTaskResultWrapper<T> {
|
||||
|
||||
private final T result;
|
||||
private final Exception error;
|
||||
private final T mResult;
|
||||
private final Exception mError;
|
||||
|
||||
public AsyncTaskResultWrapper(T result, Exception error) {
|
||||
this.result = result;
|
||||
this.error = error;
|
||||
this.mResult = result;
|
||||
this.mError = error;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public Exception getError() {
|
||||
return error;
|
||||
return mError;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.text.Spannable;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -17,12 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@ -36,21 +30,28 @@ import android.widget.CheckBox;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
protected LayoutInflater mInflater;
|
||||
protected Activity mActivity;
|
||||
|
||||
protected List<ImportKeysListEntry> data;
|
||||
protected List<ImportKeysListEntry> mData;
|
||||
|
||||
static class ViewHolder {
|
||||
private TextView mainUserId;
|
||||
private TextView mainUserIdRest;
|
||||
private TextView keyId;
|
||||
private TextView fingerprint;
|
||||
private TextView algorithm;
|
||||
private TextView status;
|
||||
private TextView mMainUserId;
|
||||
private TextView mMainUserIdRest;
|
||||
private TextView mKeyId;
|
||||
private TextView mFingerprint;
|
||||
private TextView mAlgorithm;
|
||||
private TextView mStatus;
|
||||
|
||||
}
|
||||
|
||||
public ImportKeysAdapter(Activity activity) {
|
||||
super(activity, -1);
|
||||
mActivity = activity;
|
||||
@ -61,7 +62,7 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
public void setData(List<ImportKeysListEntry> data) {
|
||||
clear();
|
||||
if (data != null) {
|
||||
this.data = data;
|
||||
this.mData = data;
|
||||
|
||||
// add data to extended ArrayAdapter
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
@ -75,15 +76,16 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
}
|
||||
|
||||
public List<ImportKeysListEntry> getData() {
|
||||
return data;
|
||||
return mData;
|
||||
}
|
||||
|
||||
public ArrayList<ImportKeysListEntry> getSelectedData() {
|
||||
ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>();
|
||||
for (ImportKeysListEntry entry : data) {
|
||||
if (entry.isSelected())
|
||||
for (ImportKeysListEntry entry : mData) {
|
||||
if (entry.isSelected()) {
|
||||
selectedData.add(entry);
|
||||
}
|
||||
}
|
||||
return selectedData;
|
||||
}
|
||||
|
||||
@ -93,20 +95,19 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ImportKeysListEntry entry = data.get(position);
|
||||
ImportKeysListEntry entry = mData.get(position);
|
||||
ViewHolder holder;
|
||||
if (convertView == null) {
|
||||
holder = new ViewHolder();
|
||||
convertView = mInflater.inflate(R.layout.import_keys_list_entry, null);
|
||||
holder.mainUserId = (TextView) convertView.findViewById(R.id.mainUserId);
|
||||
holder.mainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest);
|
||||
holder.keyId = (TextView) convertView.findViewById(R.id.keyId);
|
||||
holder.fingerprint = (TextView) convertView.findViewById(R.id.fingerprint);
|
||||
holder.algorithm = (TextView) convertView.findViewById(R.id.algorithm);
|
||||
holder.status = (TextView) convertView.findViewById(R.id.status);
|
||||
holder.mMainUserId = (TextView) convertView.findViewById(R.id.mainUserId);
|
||||
holder.mMainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest);
|
||||
holder.mKeyId = (TextView) convertView.findViewById(R.id.keyId);
|
||||
holder.mFingerprint = (TextView) convertView.findViewById(R.id.fingerprint);
|
||||
holder.mAlgorithm = (TextView) convertView.findViewById(R.id.algorithm);
|
||||
holder.mStatus = (TextView) convertView.findViewById(R.id.status);
|
||||
convertView.setTag(holder);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
// main user id
|
||||
@ -118,39 +119,40 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
// show red user id if it is a secret key
|
||||
if (entry.secretKey) {
|
||||
userIdSplit[0] = mActivity.getString(R.string.secret_key) + " " + userIdSplit[0];
|
||||
holder.mainUserId.setTextColor(Color.RED);
|
||||
holder.mMainUserId.setTextColor(Color.RED);
|
||||
}
|
||||
holder.mainUserId.setText(userIdSplit[0]);
|
||||
holder.mMainUserId.setText(userIdSplit[0]);
|
||||
} else {
|
||||
holder.mainUserId.setText(R.string.user_id_no_name);
|
||||
holder.mMainUserId.setText(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
// email
|
||||
if (userIdSplit[1] != null) {
|
||||
holder.mainUserIdRest.setText(userIdSplit[1]);
|
||||
holder.mainUserIdRest.setVisibility(View.VISIBLE);
|
||||
holder.mMainUserIdRest.setText(userIdSplit[1]);
|
||||
holder.mMainUserIdRest.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.mainUserIdRest.setVisibility(View.GONE);
|
||||
holder.mMainUserIdRest.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.keyId.setText(entry.hexKeyId);
|
||||
holder.mKeyId.setText(entry.hexKeyId);
|
||||
|
||||
if (entry.fingerPrint != null) {
|
||||
holder.fingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
|
||||
holder.fingerprint.setVisibility(View.VISIBLE);
|
||||
holder.mFingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
|
||||
holder.mFingerprint.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.fingerprint.setVisibility(View.GONE);
|
||||
holder.mFingerprint.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm);
|
||||
holder.mAlgorithm.setText("" + entry.bitStrength + "/" + entry.algorithm);
|
||||
|
||||
if (entry.revoked) {
|
||||
holder.status.setText(R.string.revoked);
|
||||
holder.mStatus.setText(R.string.revoked);
|
||||
} else {
|
||||
holder.status.setVisibility(View.GONE);
|
||||
holder.mStatus.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
LinearLayout ll = (LinearLayout) convertView.findViewById(R.id.list);
|
||||
ll.removeAllViews();
|
||||
if (entry.userIds.size() == 1) {
|
||||
ll.setVisibility(View.GONE);
|
||||
} else {
|
||||
|
@ -19,12 +19,6 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
@ -33,6 +27,11 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
private static final long serialVersionUID = -7797972103284992662L;
|
||||
public ArrayList<String> userIds;
|
||||
@ -46,9 +45,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
public String algorithm;
|
||||
public boolean secretKey;
|
||||
|
||||
private boolean selected;
|
||||
private boolean mSelected;
|
||||
|
||||
private byte[] bytes = new byte[]{};
|
||||
private byte[] mBytes = new byte[]{};
|
||||
|
||||
public ImportKeysListEntry(ImportKeysListEntry b) {
|
||||
this.userIds = b.userIds;
|
||||
@ -60,8 +59,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
this.bitStrength = b.bitStrength;
|
||||
this.algorithm = b.algorithm;
|
||||
this.secretKey = b.secretKey;
|
||||
this.selected = b.selected;
|
||||
this.bytes = b.bytes;
|
||||
this.mSelected = b.mSelected;
|
||||
this.mBytes = b.mBytes;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
@ -79,9 +78,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
dest.writeInt(bitStrength);
|
||||
dest.writeString(algorithm);
|
||||
dest.writeByte((byte) (secretKey ? 1 : 0));
|
||||
dest.writeByte((byte) (selected ? 1 : 0));
|
||||
dest.writeInt(bytes.length);
|
||||
dest.writeByteArray(bytes);
|
||||
dest.writeByte((byte) (mSelected ? 1 : 0));
|
||||
dest.writeInt(mBytes.length);
|
||||
dest.writeByteArray(mBytes);
|
||||
}
|
||||
|
||||
public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() {
|
||||
@ -97,9 +96,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
vr.bitStrength = source.readInt();
|
||||
vr.algorithm = source.readString();
|
||||
vr.secretKey = source.readByte() == 1;
|
||||
vr.selected = source.readByte() == 1;
|
||||
vr.bytes = new byte[source.readInt()];
|
||||
source.readByteArray(vr.bytes);
|
||||
vr.mSelected = source.readByte() == 1;
|
||||
vr.mBytes = new byte[source.readInt()];
|
||||
source.readByteArray(vr.mBytes);
|
||||
|
||||
return vr;
|
||||
}
|
||||
@ -114,11 +113,11 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
return mBytes;
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
this.mBytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,16 +127,16 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
// keys from keyserver are always public keys
|
||||
secretKey = false;
|
||||
// do not select by default
|
||||
selected = false;
|
||||
mSelected = false;
|
||||
userIds = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
this.selected = selected;
|
||||
this.mSelected = selected;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,13 +146,13 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||
public ImportKeysListEntry(PGPKeyRing pgpKeyRing) {
|
||||
// save actual key object into entry, used to import it later
|
||||
try {
|
||||
this.bytes = pgpKeyRing.getEncoded();
|
||||
this.mBytes = pgpKeyRing.getEncoded();
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e);
|
||||
}
|
||||
|
||||
// selected is default
|
||||
this.selected = true;
|
||||
this.mSelected = true;
|
||||
|
||||
if (pgpKeyRing instanceof PGPSecretKeyRing) {
|
||||
secretKey = true;
|
||||
|
@ -17,10 +17,8 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
@ -29,22 +27,26 @@ import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||
public class ImportKeysListLoader
|
||||
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||
|
||||
public static class FileHasNoContent extends Exception {
|
||||
|
||||
}
|
||||
|
||||
public static class NonPgpPart extends Exception {
|
||||
private int count;
|
||||
private int mCount;
|
||||
|
||||
public NonPgpPart(int count) {
|
||||
this.count = count;
|
||||
this.mCount = count;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
return mCount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,8 +54,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
||||
|
||||
InputData mInputData;
|
||||
|
||||
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
|
||||
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
|
||||
ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>();
|
||||
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
|
||||
|
||||
public ImportKeysListLoader(Context context, InputData inputData) {
|
||||
super(context);
|
||||
@ -64,16 +66,16 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
||||
@Override
|
||||
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
||||
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, null);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, null);
|
||||
|
||||
if (mInputData == null) {
|
||||
Log.e(Constants.TAG, "Input data is null!");
|
||||
return entryListWrapper;
|
||||
return mEntryListWrapper;
|
||||
}
|
||||
|
||||
generateListOfKeyrings(mInputData);
|
||||
|
||||
return entryListWrapper;
|
||||
return mEntryListWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,25 +143,25 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "Exception on parsing key file!", e);
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, e);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, e);
|
||||
nonPgpCounter = 0;
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
Log.e(Constants.TAG, "File has no content!", new FileHasNoContent());
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||
(data, new FileHasNoContent());
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||
(mData, new FileHasNoContent());
|
||||
}
|
||||
|
||||
if (nonPgpCounter > 0) {
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||
(data, new NonPgpPart(nonPgpCounter));
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||
(mData, new NonPgpPart(nonPgpCounter));
|
||||
}
|
||||
}
|
||||
|
||||
private void addToData(PGPKeyRing keyring) {
|
||||
ImportKeysListEntry item = new ImportKeysListEntry(keyring);
|
||||
data.add(item);
|
||||
mData.add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer;
|
||||
@ -27,14 +26,15 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||
public class ImportKeysListServerLoader
|
||||
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||
Context mContext;
|
||||
|
||||
String mServerQuery;
|
||||
String mKeyServer;
|
||||
|
||||
private ArrayList<ImportKeysListEntry> entryList = new ArrayList<ImportKeysListEntry>();
|
||||
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
|
||||
private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<ImportKeysListEntry>();
|
||||
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
|
||||
|
||||
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
|
||||
super(context);
|
||||
@ -46,16 +46,16 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultW
|
||||
@Override
|
||||
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
||||
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
|
||||
|
||||
if (mServerQuery == null) {
|
||||
Log.e(Constants.TAG, "mServerQuery is null!");
|
||||
return entryListWrapper;
|
||||
return mEntryListWrapper;
|
||||
}
|
||||
|
||||
queryServer(mServerQuery, mKeyServer);
|
||||
|
||||
return entryListWrapper;
|
||||
return mEntryListWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,18 +89,19 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultW
|
||||
try {
|
||||
ArrayList<ImportKeysListEntry> searchResult = server.search(query);
|
||||
|
||||
mEntryList.clear();
|
||||
// add result to data
|
||||
entryList.addAll(searchResult);
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
|
||||
mEntryList.addAll(searchResult);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
|
||||
} catch (KeyServer.InsufficientQuery e) {
|
||||
Log.e(Constants.TAG, "InsufficientQuery", e);
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e);
|
||||
} catch (KeyServer.QueryException e) {
|
||||
Log.e(Constants.TAG, "QueryException", e);
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e);
|
||||
} catch (KeyServer.TooManyResponses e) {
|
||||
Log.e(Constants.TAG, "TooManyResponses", e);
|
||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,15 +17,11 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
|
||||
private final HashMap<Integer, String> mData;
|
||||
private final int[] mKeys;
|
||||
|
@ -17,12 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.view.LayoutInflater;
|
||||
@ -31,7 +25,11 @@ import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
|
||||
|
||||
public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
||||
@ -46,8 +44,8 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
||||
private int mIndexProjectionValid;
|
||||
private int mIndexProjectionAvailable;
|
||||
|
||||
public final static String PROJECTION_ROW_AVAILABLE = "available";
|
||||
public final static String PROJECTION_ROW_VALID = "valid";
|
||||
public static final String PROJECTION_ROW_AVAILABLE = "available";
|
||||
public static final String PROJECTION_ROW_VALID = "valid";
|
||||
|
||||
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
|
||||
int keyType) {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
@ -19,12 +36,12 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
|
||||
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
|
||||
|
||||
static final class TabInfo {
|
||||
private final Class<?> clss;
|
||||
private final Bundle args;
|
||||
private final Class<?> mClss;
|
||||
private final Bundle mArgs;
|
||||
|
||||
TabInfo(Class<?> _class, Bundle _args) {
|
||||
clss = _class;
|
||||
args = _args;
|
||||
TabInfo(Class<?> mClss, Bundle mArgs) {
|
||||
this.mClss = mClss;
|
||||
this.mArgs = mArgs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +71,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
TabInfo info = mTabs.get(position);
|
||||
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
|
||||
return Fragment.instantiate(mContext, info.mClss.getName(), info.mArgs);
|
||||
}
|
||||
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
@ -29,6 +25,9 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
|
||||
public class ViewKeyKeysAdapter extends CursorAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
@ -27,6 +24,8 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
|
||||
public class ViewKeyUserIdsAdapter extends CursorAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
|
@ -23,7 +23,6 @@ import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
public class BadImportKeyDialogFragment extends DialogFragment {
|
||||
|
@ -27,13 +27,11 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Choice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
|
||||
public class CreateKeyDialogFragment extends DialogFragment {
|
||||
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
@ -32,6 +28,9 @@ import android.os.Messenger;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
|
||||
public class DeleteFileDialogFragment extends DialogFragment {
|
||||
private static final String ARG_DELETE_FILE = "delete_file";
|
||||
@ -89,7 +88,8 @@ public class DeleteFileDialogFragment extends DialogFragment {
|
||||
null);
|
||||
|
||||
// Message is received after deleting is done in ApgService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(activity, deletingDialog) {
|
||||
KeychainIntentServiceHandler saveHandler =
|
||||
new KeychainIntentServiceHandler(activity, deletingDialog) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard ApgHandler first
|
||||
super.handleMessage(message);
|
||||
|
@ -28,7 +28,6 @@ import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -118,9 +117,10 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
||||
String selectionIDs = "";
|
||||
for (int i = 0; i < keyRingRowIds.length; i++) {
|
||||
selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'";
|
||||
if (i+1 < keyRingRowIds.length)
|
||||
if (i + 1 < keyRingRowIds.length) {
|
||||
selectionIDs += ",";
|
||||
}
|
||||
}
|
||||
selection += selectionIDs + ")";
|
||||
|
||||
Cursor cursor = activity.getContentResolver().query(queryUri, projection,
|
||||
@ -140,7 +140,9 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
||||
|
||||
// check if a corresponding secret key exists...
|
||||
Cursor secretCursor = activity.getContentResolver().query(
|
||||
KeychainContract.KeyRings.buildSecretKeyRingsByMasterKeyIdUri(String.valueOf(masterKeyId)),
|
||||
KeychainContract.KeyRings
|
||||
.buildSecretKeyRingsByMasterKeyIdUri(
|
||||
String.valueOf(masterKeyId)),
|
||||
null, null, null, null
|
||||
);
|
||||
if (secretCursor != null && secretCursor.getCount() > 0) {
|
||||
|
@ -17,11 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@ -38,8 +33,11 @@ import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class FileDialogFragment extends DialogFragment {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
@ -202,8 +200,7 @@ public class FileDialogFragment extends DialogFragment {
|
||||
/**
|
||||
* Send message back to handler which is initialized in a activity
|
||||
*
|
||||
* @param what
|
||||
* Message integer you want to send
|
||||
* @param what Message integer you want to send
|
||||
*/
|
||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||
Message msg = Message.obtain();
|
||||
|
@ -17,20 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@ -52,6 +38,19 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
import android.widget.Toast;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class PassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
@ -62,15 +61,13 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
|
||||
private Messenger mMessenger;
|
||||
private EditText mPassphraseEditText;
|
||||
private boolean canKB;
|
||||
private boolean mCanKB;
|
||||
|
||||
/**
|
||||
* Creates new instance of this dialog fragment
|
||||
*
|
||||
* @param secretKeyId
|
||||
* secret key id you want to use
|
||||
* @param messenger
|
||||
* to communicate back after caching the passphrase
|
||||
* @param secretKeyId secret key id you want to use
|
||||
* @param messenger to communicate back after caching the passphrase
|
||||
* @return
|
||||
* @throws PgpGeneralException
|
||||
*/
|
||||
@ -131,7 +128,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
}
|
||||
});
|
||||
alert.setCancelable(false);
|
||||
canKB = false;
|
||||
mCanKB = false;
|
||||
return alert.create();
|
||||
}
|
||||
String userId = PgpKeyHelper.getMainUserIdSafe(activity, secretKey);
|
||||
@ -224,14 +221,14 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
}
|
||||
});
|
||||
|
||||
canKB = true;
|
||||
mCanKB = true;
|
||||
return alert.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle arg0) {
|
||||
super.onActivityCreated(arg0);
|
||||
if (canKB) {
|
||||
if (mCanKB) {
|
||||
// request focus and open soft keyboard
|
||||
mPassphraseEditText.requestFocus();
|
||||
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||
@ -266,8 +263,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
/**
|
||||
* Send message back to handler which is initialized in a activity
|
||||
*
|
||||
* @param what
|
||||
* Message integer you want to send
|
||||
* @param what Message integer you want to send
|
||||
*/
|
||||
private void sendMessageToHandler(Integer what) {
|
||||
Message msg = Message.obtain();
|
||||
|
@ -26,7 +26,6 @@ import android.content.DialogInterface.OnKeyListener;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
public class ProgressDialogFragment extends DialogFragment {
|
||||
@ -101,9 +100,10 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
|
||||
if (this.mOnCancelListener != null)
|
||||
if (this.mOnCancelListener != null) {
|
||||
this.mOnCancelListener.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dialog
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@ -40,6 +36,9 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
import android.widget.Toast;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
@ -56,10 +55,8 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
||||
/**
|
||||
* Creates new instance of this dialog fragment
|
||||
*
|
||||
* @param title
|
||||
* title of dialog
|
||||
* @param messenger
|
||||
* to communicate back after setting the passphrase
|
||||
* @param title title of dialog
|
||||
* @param messenger to communicate back after setting the passphrase
|
||||
* @return
|
||||
*/
|
||||
public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
|
||||
@ -169,8 +166,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
||||
/**
|
||||
* Send message back to handler which is initialized in a activity
|
||||
*
|
||||
* @param what
|
||||
* Message integer you want to send
|
||||
* @param what Message integer you want to send
|
||||
*/
|
||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||
Message msg = Message.obtain();
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@ -31,6 +28,8 @@ import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class ShareNfcDialogFragment extends DialogFragment {
|
||||
|
@ -28,7 +28,6 @@ import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
|
@ -24,7 +24,7 @@ import android.widget.ListView;
|
||||
/**
|
||||
* Automatically calculate height of ListView based on contained items. This enables to put this
|
||||
* ListView into a ScrollView without messing up.
|
||||
*
|
||||
* <p/>
|
||||
* from
|
||||
* http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview-
|
||||
* or-has-the-scrollview-dis
|
||||
|
@ -16,20 +16,7 @@
|
||||
|
||||
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.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.util.Choice;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
@ -39,13 +26,17 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.DatePicker;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import android.widget.*;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.util.Choice;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
private PGPSecretKey mKey;
|
||||
@ -63,7 +54,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
GregorianCalendar mExpiryDate;
|
||||
|
||||
private int mDatePickerResultCount = 0;
|
||||
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = new DatePickerDialog.OnDateSetListener() {
|
||||
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener =
|
||||
new DatePickerDialog.OnDateSetListener() {
|
||||
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
|
||||
// Note: Ignore results after the first one - android sends multiples.
|
||||
if (mDatePickerResultCount++ == 0) {
|
||||
@ -110,6 +102,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
setExpiryDate(null);
|
||||
|
||||
mExpiryDateButton.setOnClickListener(new OnClickListener() {
|
||||
@TargetApi(11)
|
||||
public void onClick(View v) {
|
||||
GregorianCalendar date = mExpiryDate;
|
||||
if (date == null) {
|
||||
@ -137,13 +130,15 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
});
|
||||
|
||||
// setCalendarViewShown() is supported from API 11 onwards.
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
// Hide calendarView in tablets because of the unix warparound bug.
|
||||
dialog.getDatePicker().setCalendarViewShown(false);
|
||||
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
if (dialog != null && mCreatedDate != null) {
|
||||
dialog.getDatePicker().setMinDate(mCreatedDate.getTime().getTime()+ DateUtils.DAY_IN_MILLIS);
|
||||
dialog.getDatePicker()
|
||||
.setMinDate(
|
||||
mCreatedDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS);
|
||||
} else {
|
||||
//When created date isn't available
|
||||
dialog.getDatePicker().setMinDate(date.getTime().getTime() + DateUtils.DAY_IN_MILLIS);
|
||||
@ -285,9 +280,11 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
|
||||
class ExpiryDatePickerDialog extends DatePickerDialog {
|
||||
|
||||
public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
|
||||
public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack,
|
||||
int year, int monthOfYear, int dayOfMonth) {
|
||||
super(context, callBack, year, monthOfYear, dayOfMonth);
|
||||
}
|
||||
|
||||
//Set permanent title.
|
||||
public void setTitle(CharSequence title) {
|
||||
super.setTitle(getContext().getString(R.string.expiry_date_dialog_title));
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.widget;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@ -25,8 +23,8 @@ import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
private EditorListener mEditorListener = null;
|
||||
|
@ -31,9 +31,7 @@ import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -57,7 +55,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
|
||||
private Choice mNewKeyAlgorithmChoice;
|
||||
private int mNewKeySize;
|
||||
private boolean canEdit = true;
|
||||
private boolean mCanEdit = true;
|
||||
|
||||
private ActionBarActivity mActivity;
|
||||
|
||||
@ -97,8 +95,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
}
|
||||
|
||||
public void setCanEdit(boolean bCanEdit) {
|
||||
canEdit = bCanEdit;
|
||||
if (!canEdit) {
|
||||
mCanEdit = bCanEdit;
|
||||
if (!mCanEdit) {
|
||||
mPlusButton.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
@ -139,7 +137,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void onClick(View v) {
|
||||
if (canEdit) {
|
||||
if (mCanEdit) {
|
||||
switch (mType) {
|
||||
case Id.type.user_id: {
|
||||
UserIdEditor view = (UserIdEditor) mInflater.inflate(
|
||||
@ -153,8 +151,11 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
}
|
||||
|
||||
case Id.type.key: {
|
||||
CreateKeyDialogFragment mCreateKeyDialogFragment = CreateKeyDialogFragment.newInstance(mEditors.getChildCount());
|
||||
mCreateKeyDialogFragment.setOnAlgorithmSelectedListener(new CreateKeyDialogFragment.OnAlgorithmSelectedListener() {
|
||||
CreateKeyDialogFragment mCreateKeyDialogFragment =
|
||||
CreateKeyDialogFragment.newInstance(mEditors.getChildCount());
|
||||
mCreateKeyDialogFragment
|
||||
.setOnAlgorithmSelectedListener(
|
||||
new CreateKeyDialogFragment.OnAlgorithmSelectedListener() {
|
||||
@Override
|
||||
public void onAlgorithmSelected(Choice algorithmChoice, int keySize) {
|
||||
mNewKeyAlgorithmChoice = algorithmChoice;
|
||||
@ -188,7 +189,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
if (mEditors.getChildCount() == 0) {
|
||||
view.setIsMainUserId(true);
|
||||
}
|
||||
view.setCanEdit(canEdit);
|
||||
view.setCanEdit(mCanEdit);
|
||||
mEditors.addView(view);
|
||||
}
|
||||
|
||||
@ -209,7 +210,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
view.setEditorListener(this);
|
||||
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
||||
view.setValue(list.get(i), isMasterKey, usages.get(i));
|
||||
view.setCanEdit(canEdit);
|
||||
view.setCanEdit(mCanEdit);
|
||||
mEditors.addView(view);
|
||||
}
|
||||
|
||||
|
@ -16,21 +16,22 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.widget;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.widget.*;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Patterns;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import android.widget.*;
|
||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ContactHelper;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
|
||||
private EditorListener mEditorListener = null;
|
||||
|
||||
@ -40,14 +41,6 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
|
||||
private AutoCompleteTextView mEmail;
|
||||
private EditText mComment;
|
||||
|
||||
// see http://www.regular-expressions.info/email.html
|
||||
// RFC 2822 if we omit the syntax using double quotes and square brackets
|
||||
// android.util.Patterns.EMAIL_ADDRESS is only available as of Android 2.2+
|
||||
private static final Pattern EMAIL_PATTERN = Pattern
|
||||
.compile(
|
||||
"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static class NoNameException extends Exception {
|
||||
static final long serialVersionUID = 0xf812773343L;
|
||||
|
||||
@ -111,6 +104,31 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
|
||||
(this.getContext(), android.R.layout.simple_dropdown_item_1line,
|
||||
ContactHelper.getMailAccounts(getContext())
|
||||
));
|
||||
mEmail.addTextChangedListener(new TextWatcher(){
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { }
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { }
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
String email = editable.toString();
|
||||
if (email.length() > 0) {
|
||||
Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
|
||||
if (emailMatcher.matches()) {
|
||||
mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
android.R.drawable.presence_online, 0);
|
||||
} else {
|
||||
mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
android.R.drawable.presence_offline, 0);
|
||||
}
|
||||
} else {
|
||||
// remove drawable if email is empty
|
||||
mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
super.onFinishInflate();
|
||||
}
|
||||
@ -138,19 +156,11 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
|
||||
}
|
||||
}
|
||||
|
||||
public String getValue() throws NoNameException, NoEmailException, InvalidEmailException {
|
||||
public String getValue() throws NoNameException, NoEmailException {
|
||||
String name = ("" + mName.getText()).trim();
|
||||
String email = ("" + mEmail.getText()).trim();
|
||||
String comment = ("" + mComment.getText()).trim();
|
||||
|
||||
if (email.length() > 0) {
|
||||
Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
|
||||
if (!emailMatcher.matches()) {
|
||||
throw new InvalidEmailException(getContext().getString(R.string.error_invalid_email,
|
||||
email));
|
||||
}
|
||||
}
|
||||
|
||||
String userId = name;
|
||||
if (comment.length() > 0) {
|
||||
userId += " (" + comment + ")";
|
||||
|
@ -17,13 +17,14 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@SuppressLint("UseSparseArrays")
|
||||
public class AlgorithmNames {
|
||||
|
@ -18,24 +18,7 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.text.Html;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
@ -51,7 +34,14 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||
|
||||
import android.text.Html;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
@ -82,21 +72,38 @@ public class HkpKeyServer extends KeyServer {
|
||||
}
|
||||
|
||||
private String mHost;
|
||||
private short mPort = 11371;
|
||||
private short mPort;
|
||||
|
||||
// example:
|
||||
// pub 2048R/<a href="/pks/lookup?op=get&search=0x887DF4BE9F5C9090">9F5C9090</a> 2009-08-17 <a
|
||||
// href="/pks/lookup?op=vindex&search=0x887DF4BE9F5C9090">Jörg Runge
|
||||
// <joerg@joergrunge.de></a>
|
||||
public static Pattern PUB_KEY_LINE = Pattern
|
||||
public static final Pattern PUB_KEY_LINE = Pattern
|
||||
.compile(
|
||||
"pub +([0-9]+)([a-z]+)/.*?0x([0-9a-z]+).*? +([0-9-]+) +(.+)[\n\r]+((?: +.+[\n\r]+)*)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
public static Pattern USER_ID_LINE = Pattern.compile("^ +(.+)$", Pattern.MULTILINE
|
||||
public static final Pattern USER_ID_LINE = Pattern.compile("^ +(.+)$", Pattern.MULTILINE
|
||||
| Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public HkpKeyServer(String host) {
|
||||
private static final short PORT_DEFAULT = 11371;
|
||||
|
||||
/**
|
||||
* @param hostAndPort may be just
|
||||
* "<code>hostname</code>" (eg. "<code>pool.sks-keyservers.net</code>"), then it will
|
||||
* connect using {@link #PORT_DEFAULT}. However, port may be specified after colon
|
||||
* ("<code>hostname:port</code>", eg. "<code>p80.pool.sks-keyservers.net:80</code>").
|
||||
*/
|
||||
public HkpKeyServer(String hostAndPort) {
|
||||
String host = hostAndPort;
|
||||
short port = PORT_DEFAULT;
|
||||
final int colonPosition = hostAndPort.lastIndexOf(':');
|
||||
if (colonPosition > 0) {
|
||||
host = hostAndPort.substring(0, colonPosition);
|
||||
final String portStr = hostAndPort.substring(colonPosition + 1);
|
||||
port = Short.decode(portStr);
|
||||
}
|
||||
mHost = host;
|
||||
mPort = port;
|
||||
}
|
||||
|
||||
public HkpKeyServer(String host, short port) {
|
||||
@ -104,7 +111,7 @@ public class HkpKeyServer extends KeyServer {
|
||||
mPort = port;
|
||||
}
|
||||
|
||||
static private String readAll(InputStream in, String encoding) throws IOException {
|
||||
private static String readAll(InputStream in, String encoding) throws IOException {
|
||||
ByteArrayOutputStream raw = new ByteArrayOutputStream();
|
||||
|
||||
byte buffer[] = new byte[1 << 16];
|
||||
|
@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
|
||||
/**
|
||||
@ -28,20 +27,19 @@ import com.google.zxing.integration.android.IntentIntegrator;
|
||||
*/
|
||||
public final class IntentIntegratorSupportV4 extends IntentIntegrator {
|
||||
|
||||
private final Fragment fragment;
|
||||
private final Fragment mFragment;
|
||||
|
||||
/**
|
||||
* @param fragment
|
||||
* Fragment to handle activity response.
|
||||
* @param fragment Fragment to handle activity response.
|
||||
*/
|
||||
public IntentIntegratorSupportV4(Fragment fragment) {
|
||||
super(fragment.getActivity());
|
||||
this.fragment = fragment;
|
||||
this.mFragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startActivityForResult(Intent intent, int code) {
|
||||
fragment.startActivityForResult(intent, code);
|
||||
mFragment.startActivityForResult(intent, code);
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user