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
|
#OS Specific
|
||||||
[Tt]humbs.db
|
[Tt]humbs.db
|
||||||
|
|
||||||
|
|
||||||
|
#Lint output
|
||||||
|
OpenPGP-Keychain/lint-report.html
|
||||||
|
OpenPGP-Keychain/lint-report_files/*
|
@ -3,7 +3,7 @@ jdk: oraclejdk7
|
|||||||
before_install:
|
before_install:
|
||||||
# Install base Android SDK
|
# Install base Android SDK
|
||||||
- sudo apt-get update -qq
|
- 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
|
- wget http://dl.google.com/android/android-sdk_r22.3-linux.tgz
|
||||||
- tar xzf android-sdk_r22.3-linux.tgz
|
- tar xzf android-sdk_r22.3-linux.tgz
|
||||||
- export ANDROID_HOME=$PWD/android-sdk-linux
|
- export ANDROID_HOME=$PWD/android-sdk-linux
|
||||||
|
@ -57,5 +57,7 @@ android {
|
|||||||
// Do not abort build if lint finds errors
|
// Do not abort build if lint finds errors
|
||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
|
htmlReport true
|
||||||
|
htmlOutput file("lint-report.html")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain;
|
package org.sufficientlysecure.keychain;
|
||||||
|
|
||||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
|
||||||
public final class Constants {
|
public final class Constants {
|
||||||
|
|
||||||
public static final boolean DEBUG = BuildConfig.DEBUG;
|
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 String INTENT_PREFIX = PACKAGE_NAME + ".action.";
|
||||||
|
|
||||||
public static final class path {
|
public static final class Path {
|
||||||
public static final String APP_DIR = Environment.getExternalStorageDirectory()
|
public static final String APP_DIR = Environment.getExternalStorageDirectory()
|
||||||
+ "/OpenPGP-Keychain";
|
+ "/OpenPGP-Keychain";
|
||||||
public static final String APP_DIR_FILE_SEC = APP_DIR + "/secexport.asc";
|
public static final String APP_DIR_FILE_SEC = APP_DIR + "/secexport.asc";
|
||||||
public static final String APP_DIR_FILE_PUB = APP_DIR + "/pubexport.asc";
|
public static final String APP_DIR_FILE_PUB = APP_DIR + "/pubexport.asc";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class pref {
|
public static final class Pref {
|
||||||
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm";
|
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm";
|
||||||
public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm";
|
public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm";
|
||||||
public static final String DEFAULT_ASCII_ARMOUR = "defaultAsciiArmour";
|
public static final String DEFAULT_ASCII_ARMOUR = "defaultAsciiArmour";
|
||||||
@ -59,7 +59,7 @@ public final class Constants {
|
|||||||
public static final String KEY_SERVERS = "keyServers";
|
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";
|
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
|
// Create APG directory on sdcard if not existing
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
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()) {
|
if (!dir.exists() && !dir.mkdirs()) {
|
||||||
// ignore this for now, it's not crucial
|
// ignore this for now, it's not crucial
|
||||||
// that the directory doesn't exist at this point
|
// that the directory doesn't exist at this point
|
||||||
|
@ -37,8 +37,9 @@ import android.os.Handler;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
public class DialogFragmentWorkaround {
|
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 =
|
||||||
: new SDKLevelPriorLevel17Impl());
|
((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) ? new SDKLevel17Impl()
|
||||||
|
: new SDKLevelPriorLevel17Impl());
|
||||||
|
|
||||||
private static final int RUNNABLE_DELAY = 300;
|
private static final int RUNNABLE_DELAY = 300;
|
||||||
|
|
||||||
|
@ -17,24 +17,23 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.helper;
|
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.app.Activity;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
public class ActionBarHelper {
|
public class ActionBarHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set actionbar without home button if called from another app
|
* Set actionbar without home button if called from another app
|
||||||
*
|
*
|
||||||
* @param activity
|
* @param activity
|
||||||
*/
|
*/
|
||||||
public static void setBackButton(ActionBarActivity activity) {
|
public static void setBackButton(ActionBarActivity activity) {
|
||||||
@ -54,7 +53,7 @@ public class ActionBarHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets custom view on ActionBar for Done/Cancel activities
|
* Sets custom view on ActionBar for Done/Cancel activities
|
||||||
*
|
*
|
||||||
* @param actionBar
|
* @param actionBar
|
||||||
* @param firstText
|
* @param firstText
|
||||||
* @param firstDrawableId
|
* @param firstDrawableId
|
||||||
@ -63,9 +62,9 @@ public class ActionBarHelper {
|
|||||||
* @param secondDrawableId
|
* @param secondDrawableId
|
||||||
* @param secondOnClickListener
|
* @param secondOnClickListener
|
||||||
*/
|
*/
|
||||||
public static void setTwoButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
|
public static void setTwoButtonView(ActionBar actionBar,
|
||||||
OnClickListener firstOnClickListener, int secondText, int secondDrawableId,
|
int firstText, int firstDrawableId, OnClickListener firstOnClickListener,
|
||||||
OnClickListener secondOnClickListener) {
|
int secondText, int secondDrawableId, OnClickListener secondOnClickListener) {
|
||||||
|
|
||||||
// Inflate the custom action bar view
|
// Inflate the custom action bar view
|
||||||
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
|
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
|
||||||
@ -94,13 +93,13 @@ public class ActionBarHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets custom view on ActionBar for Done activities
|
* Sets custom view on ActionBar for Done activities
|
||||||
*
|
*
|
||||||
* @param actionBar
|
* @param actionBar
|
||||||
* @param firstText
|
* @param firstText
|
||||||
* @param firstOnClickListener
|
* @param firstOnClickListener
|
||||||
*/
|
*/
|
||||||
public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
|
public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
|
||||||
OnClickListener firstOnClickListener) {
|
OnClickListener firstOnClickListener) {
|
||||||
// Inflate a "Done" custom action bar view to serve as the "Up" affordance.
|
// Inflate a "Done" custom action bar view to serve as the "Up" affordance.
|
||||||
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
|
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
|
||||||
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -16,6 +16,16 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.helper;
|
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.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
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.ui.dialog.FileDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 {
|
public class ExportHelper {
|
||||||
protected FileDialogFragment mFileDialog;
|
protected FileDialogFragment mFileDialog;
|
||||||
protected String mExportFilename;
|
protected String mExportFilename;
|
||||||
|
|
||||||
ActionBarActivity activity;
|
ActionBarActivity mActivity;
|
||||||
|
|
||||||
public ExportHelper(ActionBarActivity activity) {
|
public ExportHelper(ActionBarActivity activity) {
|
||||||
super();
|
super();
|
||||||
this.activity = activity;
|
this.mActivity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteKey(Uri dataUri, final int keyType, Handler deleteHandler) {
|
public void deleteKey(Uri dataUri, final int keyType, Handler deleteHandler) {
|
||||||
@ -54,16 +54,16 @@ public class ExportHelper {
|
|||||||
Messenger messenger = new Messenger(deleteHandler);
|
Messenger messenger = new Messenger(deleteHandler);
|
||||||
|
|
||||||
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
|
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
|
||||||
new long[] { keyRingRowId }, keyType);
|
new long[]{keyRingRowId}, keyType);
|
||||||
|
|
||||||
deleteKeyDialog.show(activity.getSupportFragmentManager(), "deleteKeyDialog");
|
deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show dialog where to export keys
|
* Show dialog where to export keys
|
||||||
*/
|
*/
|
||||||
public void showExportKeysDialog(final long[] rowIds, final int keyType,
|
public void showExportKeysDialog(final long[] rowIds, final int keyType,
|
||||||
final String exportFilename) {
|
final String exportFilename) {
|
||||||
mExportFilename = exportFilename;
|
mExportFilename = exportFilename;
|
||||||
|
|
||||||
// Message is received after file is selected
|
// Message is received after file is selected
|
||||||
@ -87,23 +87,23 @@ public class ExportHelper {
|
|||||||
String title = null;
|
String title = null;
|
||||||
if (rowIds == null) {
|
if (rowIds == null) {
|
||||||
// export all keys
|
// export all keys
|
||||||
title = activity.getString(R.string.title_export_keys);
|
title = mActivity.getString(R.string.title_export_keys);
|
||||||
} else {
|
} else {
|
||||||
// export only key specified at data uri
|
// 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;
|
String message = null;
|
||||||
if (keyType == Id.type.public_key) {
|
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 {
|
} 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,
|
mFileDialog = FileDialogFragment.newInstance(messenger, title, message,
|
||||||
exportFilename, null);
|
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");
|
Log.d(Constants.TAG, "exportKeys started");
|
||||||
|
|
||||||
// Send all information needed to service to export key in other thread
|
// 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);
|
intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING);
|
||||||
|
|
||||||
@ -134,8 +134,16 @@ public class ExportHelper {
|
|||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
|
|
||||||
// Message is received after exporting is done in ApgService
|
// Message is received after exporting is done in ApgService
|
||||||
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(activity,
|
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(mActivity,
|
||||||
activity.getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) {
|
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) {
|
public void handleMessage(Message message) {
|
||||||
// handle messages by standard ApgHandler first
|
// handle messages by standard ApgHandler first
|
||||||
super.handleMessage(message);
|
super.handleMessage(message);
|
||||||
@ -147,13 +155,13 @@ public class ExportHelper {
|
|||||||
int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT);
|
int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT);
|
||||||
String toastMessage;
|
String toastMessage;
|
||||||
if (exported == 1) {
|
if (exported == 1) {
|
||||||
toastMessage = activity.getString(R.string.key_exported);
|
toastMessage = mActivity.getString(R.string.key_exported);
|
||||||
} else if (exported > 0) {
|
} else if (exported > 0) {
|
||||||
toastMessage = activity.getString(R.string.keys_exported, exported);
|
toastMessage = mActivity.getString(R.string.keys_exported, exported);
|
||||||
} else {
|
} 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);
|
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
||||||
|
|
||||||
// show progress dialog
|
// show progress dialog
|
||||||
exportHandler.showProgressDialog(activity);
|
exportHandler.showProgressDialog(mActivity);
|
||||||
|
|
||||||
// start service with intent
|
// start service with intent
|
||||||
activity.startService(intent);
|
mActivity.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.helper;
|
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.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -30,12 +26,15 @@ import android.net.Uri;
|
|||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
public class FileHelper {
|
public class FileHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if external storage is mounted if file is located on external storage
|
* Checks if external storage is mounted if file is located on external storage
|
||||||
*
|
*
|
||||||
* @param file
|
* @param file
|
||||||
* @return true if storage is mounted
|
* @return true if storage is mounted
|
||||||
*/
|
*/
|
||||||
@ -52,15 +51,12 @@ public class FileHelper {
|
|||||||
/**
|
/**
|
||||||
* Opens the preferred installed file manager on Android and shows a toast if no manager is
|
* Opens the preferred installed file manager on Android and shows a toast if no manager is
|
||||||
* installed.
|
* installed.
|
||||||
*
|
*
|
||||||
* @param activity
|
* @param activity
|
||||||
* @param filename
|
* @param filename default selected file, not supported by all file managers
|
||||||
* default selected file, not supported by all file managers
|
* @param mimeType can be text/plain for example
|
||||||
* @param mimeType
|
* @param requestCode requestCode used to identify the result coming back from file manager to
|
||||||
* can be text/plain for example
|
* onActivityResult() in your activity
|
||||||
* @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) {
|
public static void openFile(Activity activity, String filename, String mimeType, int requestCode) {
|
||||||
Intent intent = buildFileIntent(filename, mimeType);
|
Intent intent = buildFileIntent(filename, mimeType);
|
||||||
@ -97,14 +93,13 @@ public class FileHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a file path from a Uri.
|
* Get a file path from a Uri.
|
||||||
*
|
* <p/>
|
||||||
* from https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/
|
* from https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/
|
||||||
* afilechooser/utils/FileUtils.java
|
* afilechooser/utils/FileUtils.java
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param uri
|
* @param uri
|
||||||
* @return
|
* @return
|
||||||
*
|
|
||||||
* @author paulburke
|
* @author paulburke
|
||||||
*/
|
*/
|
||||||
public static String getPath(Context context, Uri uri) {
|
public static String getPath(Context context, Uri uri) {
|
||||||
@ -115,21 +110,19 @@ public class FileHelper {
|
|||||||
+ uri.getPathSegments().toString());
|
+ uri.getPathSegments().toString());
|
||||||
|
|
||||||
if ("content".equalsIgnoreCase(uri.getScheme())) {
|
if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||||
String[] projection = { "_data" };
|
String[] projection = {"_data"};
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||||
int column_index = cursor.getColumnIndexOrThrow("_data");
|
int columnIndex = cursor.getColumnIndexOrThrow("_data");
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
return cursor.getString(column_index);
|
return cursor.getString(columnIndex);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Eat it
|
// Eat it
|
||||||
}
|
}
|
||||||
}
|
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||||
|
|
||||||
else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
|
||||||
return uri.getPath();
|
return uri.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,19 +17,21 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.helper;
|
package org.sufficientlysecure.keychain.helper;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import android.os.Bundle;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 {
|
public class OtherHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs bundle content to debug for inspecting the content
|
* Logs bundle content to debug for inspecting the content
|
||||||
*
|
*
|
||||||
* @param bundle
|
* @param bundle
|
||||||
* @param bundleName
|
* @param bundleName
|
||||||
*/
|
*/
|
||||||
@ -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;
|
package org.sufficientlysecure.keychain.helper;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,8 +37,8 @@ public class Preferences {
|
|||||||
return getPreferences(context, false);
|
return getPreferences(context, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized Preferences getPreferences(Context context, boolean force_new) {
|
public static synchronized Preferences getPreferences(Context context, boolean forceNew) {
|
||||||
if (mPreferences == null || force_new) {
|
if (mPreferences == null || forceNew) {
|
||||||
mPreferences = new Preferences(context);
|
mPreferences = new Preferences(context);
|
||||||
}
|
}
|
||||||
return mPreferences;
|
return mPreferences;
|
||||||
@ -50,17 +49,17 @@ public class Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getLanguage() {
|
public String getLanguage() {
|
||||||
return mSharedPreferences.getString(Constants.pref.LANGUAGE, "");
|
return mSharedPreferences.getString(Constants.Pref.LANGUAGE, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLanguage(String value) {
|
public void setLanguage(String value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putString(Constants.pref.LANGUAGE, value);
|
editor.putString(Constants.Pref.LANGUAGE, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getPassPhraseCacheTtl() {
|
public long getPassPhraseCacheTtl() {
|
||||||
int ttl = mSharedPreferences.getInt(Constants.pref.PASS_PHRASE_CACHE_TTL, 180);
|
int ttl = mSharedPreferences.getInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, 180);
|
||||||
// fix the value if it was set to "never" in previous versions, which currently is not
|
// fix the value if it was set to "never" in previous versions, which currently is not
|
||||||
// supported
|
// supported
|
||||||
if (ttl == 0) {
|
if (ttl == 0) {
|
||||||
@ -71,77 +70,77 @@ public class Preferences {
|
|||||||
|
|
||||||
public void setPassPhraseCacheTtl(int value) {
|
public void setPassPhraseCacheTtl(int value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putInt(Constants.pref.PASS_PHRASE_CACHE_TTL, value);
|
editor.putInt(Constants.Pref.PASS_PHRASE_CACHE_TTL, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultEncryptionAlgorithm() {
|
public int getDefaultEncryptionAlgorithm() {
|
||||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM,
|
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM,
|
||||||
PGPEncryptedData.AES_256);
|
PGPEncryptedData.AES_256);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultEncryptionAlgorithm(int value) {
|
public void setDefaultEncryptionAlgorithm(int value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putInt(Constants.pref.DEFAULT_ENCRYPTION_ALGORITHM, value);
|
editor.putInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultHashAlgorithm() {
|
public int getDefaultHashAlgorithm() {
|
||||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_HASH_ALGORITHM,
|
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM,
|
||||||
HashAlgorithmTags.SHA512);
|
HashAlgorithmTags.SHA512);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultHashAlgorithm(int value) {
|
public void setDefaultHashAlgorithm(int value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putInt(Constants.pref.DEFAULT_HASH_ALGORITHM, value);
|
editor.putInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultMessageCompression() {
|
public int getDefaultMessageCompression() {
|
||||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_MESSAGE_COMPRESSION,
|
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION,
|
||||||
Id.choice.compression.zlib);
|
Id.choice.compression.zlib);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultMessageCompression(int value) {
|
public void setDefaultMessageCompression(int value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putInt(Constants.pref.DEFAULT_MESSAGE_COMPRESSION, value);
|
editor.putInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultFileCompression() {
|
public int getDefaultFileCompression() {
|
||||||
return mSharedPreferences.getInt(Constants.pref.DEFAULT_FILE_COMPRESSION,
|
return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION,
|
||||||
Id.choice.compression.none);
|
Id.choice.compression.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultFileCompression(int value) {
|
public void setDefaultFileCompression(int value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putInt(Constants.pref.DEFAULT_FILE_COMPRESSION, value);
|
editor.putInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDefaultAsciiArmour() {
|
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) {
|
public void setDefaultAsciiArmour(boolean value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putBoolean(Constants.pref.DEFAULT_ASCII_ARMOUR, value);
|
editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOUR, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getForceV3Signatures() {
|
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) {
|
public void setForceV3Signatures(boolean value) {
|
||||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||||
editor.putBoolean(Constants.pref.FORCE_V3_SIGNATURES, value);
|
editor.putBoolean(Constants.Pref.FORCE_V3_SIGNATURES, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getKeyServers() {
|
public String[] getKeyServers() {
|
||||||
String rawData = mSharedPreferences.getString(Constants.pref.KEY_SERVERS,
|
String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS,
|
||||||
Constants.defaults.KEY_SERVERS);
|
Constants.Defaults.KEY_SERVERS);
|
||||||
Vector<String> servers = new Vector<String>();
|
Vector<String> servers = new Vector<String>();
|
||||||
String chunks[] = rawData.split(",");
|
String chunks[] = rawData.split(",");
|
||||||
for (String c : chunks) {
|
for (String c : chunks) {
|
||||||
@ -166,7 +165,7 @@ public class Preferences {
|
|||||||
}
|
}
|
||||||
rawData += tmp;
|
rawData += tmp;
|
||||||
}
|
}
|
||||||
editor.putString(Constants.pref.KEY_SERVERS, rawData);
|
editor.putString(Constants.Pref.KEY_SERVERS, rawData);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
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.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
@ -31,12 +26,17 @@ import org.spongycastle.openpgp.PGPSignatureList;
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 {
|
public class PgpConversionHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from byte[] to PGPKeyRing
|
* Convert from byte[] to PGPKeyRing
|
||||||
*
|
*
|
||||||
* @param keysBytes
|
* @param keysBytes
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -56,7 +56,7 @@ public class PgpConversionHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from byte[] to ArrayList<PGPSecretKey>
|
* Convert from byte[] to ArrayList<PGPSecretKey>
|
||||||
*
|
*
|
||||||
* @param keysBytes
|
* @param keysBytes
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -75,9 +75,9 @@ public class PgpConversionHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from byte[] to PGPSecretKey
|
* Convert from byte[] to PGPSecretKey
|
||||||
*
|
* <p/>
|
||||||
* Singles keys are encoded as keyRings with one single key in it by Bouncy Castle
|
* Singles keys are encoded as keyRings with one single key in it by Bouncy Castle
|
||||||
*
|
*
|
||||||
* @param keyBytes
|
* @param keyBytes
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -90,13 +90,13 @@ public class PgpConversionHelper {
|
|||||||
Log.e(Constants.TAG, "Error while converting to PGPSecretKey!", e);
|
Log.e(Constants.TAG, "Error while converting to PGPSecretKey!", e);
|
||||||
}
|
}
|
||||||
PGPSecretKey secKey = null;
|
PGPSecretKey secKey = null;
|
||||||
if(obj instanceof PGPSecretKey) {
|
if (obj instanceof PGPSecretKey) {
|
||||||
if ((secKey = (PGPSecretKey)obj ) == null) {
|
if ((secKey = (PGPSecretKey) obj) == null) {
|
||||||
Log.e(Constants.TAG, "No keys given!");
|
Log.e(Constants.TAG, "No keys given!");
|
||||||
}
|
}
|
||||||
} else if(obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings
|
} else if (obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings
|
||||||
PGPSecretKeyRing keyRing = null;
|
PGPSecretKeyRing keyRing = null;
|
||||||
if ((keyRing = (PGPSecretKeyRing)obj) == null) {
|
if ((keyRing = (PGPSecretKeyRing) obj) == null) {
|
||||||
Log.e(Constants.TAG, "No keys given!");
|
Log.e(Constants.TAG, "No keys given!");
|
||||||
}
|
}
|
||||||
secKey = keyRing.getSecretKey();
|
secKey = keyRing.getSecretKey();
|
||||||
@ -129,7 +129,7 @@ public class PgpConversionHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from ArrayList<PGPSecretKey> to byte[]
|
* Convert from ArrayList<PGPSecretKey> to byte[]
|
||||||
*
|
*
|
||||||
* @param keys
|
* @param keys
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -148,7 +148,7 @@ public class PgpConversionHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from PGPSecretKey to byte[]
|
* Convert from PGPSecretKey to byte[]
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -164,7 +164,7 @@ public class PgpConversionHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from PGPSecretKeyRing to byte[]
|
* Convert from PGPSecretKeyRing to byte[]
|
||||||
*
|
*
|
||||||
* @param keyRing
|
* @param keyRing
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -18,38 +18,16 @@
|
|||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
import org.spongycastle.bcpg.ArmoredInputStream;
|
import org.spongycastle.bcpg.ArmoredInputStream;
|
||||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||||
import org.spongycastle.openpgp.PGPCompressedData;
|
import org.spongycastle.openpgp.*;
|
||||||
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.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
|
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
||||||
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
import org.spongycastle.openpgp.operator.jcajce.*;
|
||||||
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.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
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.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.*;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
@ -72,57 +45,57 @@ import java.util.Iterator;
|
|||||||
* This class uses a Builder pattern!
|
* This class uses a Builder pattern!
|
||||||
*/
|
*/
|
||||||
public class PgpDecryptVerify {
|
public class PgpDecryptVerify {
|
||||||
private Context context;
|
private Context mContext;
|
||||||
private InputData data;
|
private InputData mData;
|
||||||
private OutputStream outStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
private ProgressDialogUpdater progressDialogUpdater;
|
private ProgressDialogUpdater mProgressDialogUpdater;
|
||||||
private boolean assumeSymmetric;
|
private boolean mAssumeSymmetric;
|
||||||
private String passphrase;
|
private String mPassphrase;
|
||||||
private long enforcedKeyId;
|
private long mEnforcedKeyId;
|
||||||
|
|
||||||
private PgpDecryptVerify(Builder builder) {
|
private PgpDecryptVerify(Builder builder) {
|
||||||
// private Constructor can only be called from Builder
|
// private Constructor can only be called from Builder
|
||||||
this.context = builder.context;
|
this.mContext = builder.mContext;
|
||||||
this.data = builder.data;
|
this.mData = builder.mData;
|
||||||
this.outStream = builder.outStream;
|
this.mOutStream = builder.mOutStream;
|
||||||
|
|
||||||
this.progressDialogUpdater = builder.progressDialogUpdater;
|
this.mProgressDialogUpdater = builder.mProgressDialogUpdater;
|
||||||
this.assumeSymmetric = builder.assumeSymmetric;
|
this.mAssumeSymmetric = builder.mAssumeSymmetric;
|
||||||
this.passphrase = builder.passphrase;
|
this.mPassphrase = builder.mPassphrase;
|
||||||
this.enforcedKeyId = builder.enforcedKeyId;
|
this.mEnforcedKeyId = builder.mEnforcedKeyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
// mandatory parameter
|
// mandatory parameter
|
||||||
private Context context;
|
private Context mContext;
|
||||||
private InputData data;
|
private InputData mData;
|
||||||
private OutputStream outStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
// optional
|
// optional
|
||||||
private ProgressDialogUpdater progressDialogUpdater = null;
|
private ProgressDialogUpdater mProgressDialogUpdater = null;
|
||||||
private boolean assumeSymmetric = false;
|
private boolean mAssumeSymmetric = false;
|
||||||
private String passphrase = "";
|
private String mPassphrase = "";
|
||||||
private long enforcedKeyId = 0;
|
private long mEnforcedKeyId = 0;
|
||||||
|
|
||||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
public Builder(Context context, InputData data, OutputStream outStream) {
|
||||||
this.context = context;
|
this.mContext = context;
|
||||||
this.data = data;
|
this.mData = data;
|
||||||
this.outStream = outStream;
|
this.mOutStream = outStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder progressDialogUpdater(ProgressDialogUpdater progressDialogUpdater) {
|
public Builder progressDialogUpdater(ProgressDialogUpdater progressDialogUpdater) {
|
||||||
this.progressDialogUpdater = progressDialogUpdater;
|
this.mProgressDialogUpdater = progressDialogUpdater;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder assumeSymmetric(boolean assumeSymmetric) {
|
public Builder assumeSymmetric(boolean assumeSymmetric) {
|
||||||
this.assumeSymmetric = assumeSymmetric;
|
this.mAssumeSymmetric = assumeSymmetric;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder passphrase(String passphrase) {
|
public Builder passphrase(String passphrase) {
|
||||||
this.passphrase = passphrase;
|
this.mPassphrase = passphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +107,7 @@ public class PgpDecryptVerify {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Builder enforcedKeyId(long enforcedKeyId) {
|
public Builder enforcedKeyId(long enforcedKeyId) {
|
||||||
this.enforcedKeyId = enforcedKeyId;
|
this.mEnforcedKeyId = enforcedKeyId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,14 +117,14 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateProgress(int message, int current, int total) {
|
public void updateProgress(int message, int current, int total) {
|
||||||
if (progressDialogUpdater != null) {
|
if (mProgressDialogUpdater != null) {
|
||||||
progressDialogUpdater.setProgress(message, current, total);
|
mProgressDialogUpdater.setProgress(message, current, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateProgress(int current, int total) {
|
public void updateProgress(int current, int total) {
|
||||||
if (progressDialogUpdater != null) {
|
if (mProgressDialogUpdater != null) {
|
||||||
progressDialogUpdater.setProgress(current, total);
|
mProgressDialogUpdater.setProgress(current, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +169,7 @@ public class PgpDecryptVerify {
|
|||||||
public PgpDecryptVerifyResult execute()
|
public PgpDecryptVerifyResult execute()
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
||||||
// automatically works with ascii armor input and binary
|
// automatically works with ascii armor input and binary
|
||||||
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
|
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
|
||||||
if (in instanceof ArmoredInputStream) {
|
if (in instanceof ArmoredInputStream) {
|
||||||
ArmoredInputStream aIn = (ArmoredInputStream) in;
|
ArmoredInputStream aIn = (ArmoredInputStream) in;
|
||||||
// it is ascii armored
|
// it is ascii armored
|
||||||
@ -240,7 +213,7 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (enc == null) {
|
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;
|
InputStream clear;
|
||||||
@ -250,7 +223,7 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
// TODO: currently we always only look at the first known key or symmetric encryption,
|
// TODO: currently we always only look at the first known key or symmetric encryption,
|
||||||
// there might be more...
|
// there might be more...
|
||||||
if (assumeSymmetric) {
|
if (mAssumeSymmetric) {
|
||||||
PGPPBEEncryptedData pbe = null;
|
PGPPBEEncryptedData pbe = null;
|
||||||
Iterator<?> it = enc.getEncryptedDataObjects();
|
Iterator<?> it = enc.getEncryptedDataObjects();
|
||||||
// find secret key
|
// find secret key
|
||||||
@ -264,7 +237,7 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
if (pbe == null) {
|
if (pbe == null) {
|
||||||
throw new PgpGeneralException(
|
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);
|
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
||||||
@ -273,7 +246,7 @@ public class PgpDecryptVerify {
|
|||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
|
||||||
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
|
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
|
||||||
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
passphrase.toCharArray());
|
mPassphrase.toCharArray());
|
||||||
|
|
||||||
clear = pbe.getDataStream(decryptorFactory);
|
clear = pbe.getDataStream(decryptorFactory);
|
||||||
|
|
||||||
@ -290,33 +263,37 @@ public class PgpDecryptVerify {
|
|||||||
Object obj = it.next();
|
Object obj = it.next();
|
||||||
if (obj instanceof PGPPublicKeyEncryptedData) {
|
if (obj instanceof PGPPublicKeyEncryptedData) {
|
||||||
PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
|
PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
|
||||||
secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, encData.getKeyID());
|
secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID());
|
||||||
if (secretKey != null) {
|
if (secretKey != null) {
|
||||||
// secret key exists in database
|
// secret key exists in database
|
||||||
|
|
||||||
// allow only a specific key for decryption?
|
// allow only a specific key for decryption?
|
||||||
if (enforcedKeyId != 0) {
|
if (mEnforcedKeyId != 0) {
|
||||||
// TODO: improve this code! get master key directly!
|
// 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();
|
long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID();
|
||||||
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
|
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
|
||||||
Log.d(Constants.TAG, "enforcedKeyId: " + enforcedKeyId);
|
Log.d(Constants.TAG, "enforcedKeyId: " + mEnforcedKeyId);
|
||||||
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
|
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
|
||||||
|
|
||||||
if (enforcedKeyId != masterKeyId) {
|
if (mEnforcedKeyId != masterKeyId) {
|
||||||
throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found));
|
throw new PgpGeneralException(
|
||||||
|
mContext.getString(R.string.error_no_secret_key_found));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pbe = encData;
|
pbe = encData;
|
||||||
|
|
||||||
// if no passphrase was explicitly set try to get it from the cache service
|
// 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
|
// 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 was not cached, return here
|
||||||
if (passphrase == null) {
|
// indicating that a passphrase is missing!
|
||||||
|
if (mPassphrase == null) {
|
||||||
returnData.setKeyPassphraseNeeded(true);
|
returnData.setKeyPassphraseNeeded(true);
|
||||||
return returnData;
|
return returnData;
|
||||||
}
|
}
|
||||||
@ -330,7 +307,7 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (secretKey == null) {
|
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;
|
currentProgress += 5;
|
||||||
@ -339,14 +316,14 @@ public class PgpDecryptVerify {
|
|||||||
try {
|
try {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
passphrase.toCharArray());
|
mPassphrase.toCharArray());
|
||||||
privateKey = secretKey.extractPrivateKey(keyDecryptor);
|
privateKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||||
} catch (PGPException e) {
|
} 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) {
|
if (privateKey == null) {
|
||||||
throw new PgpGeneralException(
|
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;
|
currentProgress += 5;
|
||||||
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
||||||
@ -386,7 +363,7 @@ public class PgpDecryptVerify {
|
|||||||
for (int i = 0; i < sigList.size(); ++i) {
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
signature = sigList.get(i);
|
signature = sigList.get(i);
|
||||||
signatureKey = ProviderHelper
|
signatureKey = ProviderHelper
|
||||||
.getPGPPublicKeyByKeyId(context, signature.getKeyID());
|
.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
|
||||||
if (signatureKeyId == 0) {
|
if (signatureKeyId == 0) {
|
||||||
signatureKeyId = signature.getKeyID();
|
signatureKeyId = signature.getKeyID();
|
||||||
}
|
}
|
||||||
@ -397,7 +374,7 @@ public class PgpDecryptVerify {
|
|||||||
signatureKeyId = signature.getKeyID();
|
signatureKeyId = signature.getKeyID();
|
||||||
String userId = null;
|
String userId = null;
|
||||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
|
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
|
||||||
context, signatureKeyId);
|
mContext, signatureKeyId);
|
||||||
if (signKeyRing != null) {
|
if (signKeyRing != null) {
|
||||||
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
||||||
}
|
}
|
||||||
@ -409,7 +386,8 @@ public class PgpDecryptVerify {
|
|||||||
signatureResult.setKeyId(signatureKeyId);
|
signatureResult.setKeyId(signatureKeyId);
|
||||||
|
|
||||||
if (signature != null) {
|
if (signature != null) {
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
|
||||||
signature.init(contentVerifierBuilderProvider, signatureKey);
|
signature.init(contentVerifierBuilderProvider, signatureKey);
|
||||||
@ -444,9 +422,9 @@ public class PgpDecryptVerify {
|
|||||||
int n;
|
int n;
|
||||||
// TODO: progress calculation is broken here! Try to rework it based on commented code!
|
// TODO: progress calculation is broken here! Try to rework it based on commented code!
|
||||||
// int progress = 0;
|
// int progress = 0;
|
||||||
long startPos = data.getStreamPosition();
|
long startPos = mData.getStreamPosition();
|
||||||
while ((n = dataIn.read(buffer)) > 0) {
|
while ((n = dataIn.read(buffer)) > 0) {
|
||||||
outStream.write(buffer, 0, n);
|
mOutStream.write(buffer, 0, n);
|
||||||
// progress += n;
|
// progress += n;
|
||||||
if (signature != null) {
|
if (signature != null) {
|
||||||
try {
|
try {
|
||||||
@ -460,11 +438,11 @@ public class PgpDecryptVerify {
|
|||||||
// unknown size, but try to at least have a moving, slowing down progress bar
|
// unknown size, but try to at least have a moving, slowing down progress bar
|
||||||
// currentProgress = startProgress + (endProgress - startProgress) * progress
|
// currentProgress = startProgress + (endProgress - startProgress) * progress
|
||||||
// / (progress + 100000);
|
// / (progress + 100000);
|
||||||
if (data.getSize() - startPos == 0) {
|
if (mData.getSize() - startPos == 0) {
|
||||||
currentProgress = endProgress;
|
currentProgress = endProgress;
|
||||||
} else {
|
} else {
|
||||||
currentProgress = (int) (startProgress + (endProgress - startProgress)
|
currentProgress = (int) (startProgress + (endProgress - startProgress)
|
||||||
* (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
|
* (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos));
|
||||||
}
|
}
|
||||||
updateProgress(currentProgress, 100);
|
updateProgress(currentProgress, 100);
|
||||||
}
|
}
|
||||||
@ -480,7 +458,7 @@ public class PgpDecryptVerify {
|
|||||||
signatureResult.setSignatureOnly(false);
|
signatureResult.setSignatureOnly(false);
|
||||||
|
|
||||||
//Now check binding signatures
|
//Now check binding signatures
|
||||||
boolean validKeyBinding = verifyKeyBinding(context, messageSignature, signatureKey);
|
boolean validKeyBinding = verifyKeyBinding(mContext, messageSignature, signatureKey);
|
||||||
boolean validSignature = signature.verify(messageSignature);
|
boolean validSignature = signature.verify(messageSignature);
|
||||||
|
|
||||||
// TODO: implement CERTIFIED!
|
// TODO: implement CERTIFIED!
|
||||||
@ -499,7 +477,7 @@ public class PgpDecryptVerify {
|
|||||||
} else {
|
} else {
|
||||||
// failed
|
// failed
|
||||||
Log.d(Constants.TAG, "Integrity verification: 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 {
|
} else {
|
||||||
// no integrity check
|
// no integrity check
|
||||||
@ -555,21 +533,21 @@ public class PgpDecryptVerify {
|
|||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
byte[] clearText = out.toByteArray();
|
byte[] clearText = out.toByteArray();
|
||||||
outStream.write(clearText);
|
mOutStream.write(clearText);
|
||||||
|
|
||||||
updateProgress(R.string.progress_processing_signature, 60, 100);
|
updateProgress(R.string.progress_processing_signature, 60, 100);
|
||||||
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
|
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
|
||||||
|
|
||||||
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
||||||
if (sigList == null) {
|
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;
|
PGPSignature signature = null;
|
||||||
long signatureKeyId = 0;
|
long signatureKeyId = 0;
|
||||||
PGPPublicKey signatureKey = null;
|
PGPPublicKey signatureKey = null;
|
||||||
for (int i = 0; i < sigList.size(); ++i) {
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
signature = sigList.get(i);
|
signature = sigList.get(i);
|
||||||
signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(context, signature.getKeyID());
|
signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
|
||||||
if (signatureKeyId == 0) {
|
if (signatureKeyId == 0) {
|
||||||
signatureKeyId = signature.getKeyID();
|
signatureKeyId = signature.getKeyID();
|
||||||
}
|
}
|
||||||
@ -579,7 +557,7 @@ public class PgpDecryptVerify {
|
|||||||
} else {
|
} else {
|
||||||
signatureKeyId = signature.getKeyID();
|
signatureKeyId = signature.getKeyID();
|
||||||
String userId = null;
|
String userId = null;
|
||||||
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
|
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext,
|
||||||
signatureKeyId);
|
signatureKeyId);
|
||||||
if (signKeyRing != null) {
|
if (signKeyRing != null) {
|
||||||
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
|
||||||
@ -623,7 +601,7 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Now check binding signatures
|
//Now check binding signatures
|
||||||
boolean validKeyBinding = verifyKeyBinding(context, signature, signatureKey);
|
boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey);
|
||||||
boolean validSignature = signature.verify();
|
boolean validSignature = signature.verify();
|
||||||
|
|
||||||
if (validSignature & validKeyBinding) {
|
if (validSignature & validKeyBinding) {
|
||||||
@ -638,7 +616,8 @@ public class PgpDecryptVerify {
|
|||||||
return returnData;
|
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();
|
long signatureKeyId = signature.getKeyID();
|
||||||
boolean validKeyBinding = false;
|
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
|
//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.
|
//either, so we will err on bad subkey binding here.
|
||||||
PGPSignature sig = itr.next();
|
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.
|
//check and if ok, check primary key binding.
|
||||||
try {
|
try {
|
||||||
sig.init(contentVerifierBuilderProvider, masterPublicKey);
|
sig.init(contentVerifierBuilderProvider, masterPublicKey);
|
||||||
@ -684,34 +664,37 @@ public class PgpDecryptVerify {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validTempSubkeyBinding)
|
if (validTempSubkeyBinding) {
|
||||||
validSubkeyBinding = true;
|
validSubkeyBinding = true;
|
||||||
|
}
|
||||||
if (validTempSubkeyBinding) {
|
if (validTempSubkeyBinding) {
|
||||||
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(),
|
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(),
|
||||||
masterPublicKey, signingPublicKey);
|
masterPublicKey, signingPublicKey);
|
||||||
if (validPrimaryKeyBinding)
|
if (validPrimaryKeyBinding) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(),
|
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(),
|
||||||
masterPublicKey, signingPublicKey);
|
masterPublicKey, signingPublicKey);
|
||||||
if (validPrimaryKeyBinding)
|
if (validPrimaryKeyBinding) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (validSubkeyBinding & validPrimaryKeyBinding);
|
return (validSubkeyBinding & validPrimaryKeyBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector Pkts,
|
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
|
||||||
PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
|
PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
|
||||||
boolean validPrimaryKeyBinding = false;
|
boolean validPrimaryKeyBinding = false;
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
PGPSignatureList eSigList;
|
PGPSignatureList eSigList;
|
||||||
|
|
||||||
if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
|
if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
|
||||||
try {
|
try {
|
||||||
eSigList = Pkts.getEmbeddedSignatures();
|
eSigList = pkts.getEmbeddedSignatures();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return false;
|
return false;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
@ -723,8 +706,9 @@ public class PgpDecryptVerify {
|
|||||||
try {
|
try {
|
||||||
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
|
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
|
||||||
validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey);
|
validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey);
|
||||||
if (validPrimaryKeyBinding)
|
if (validPrimaryKeyBinding) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
continue;
|
continue;
|
||||||
} catch (SignatureException e) {
|
} catch (SignatureException e) {
|
||||||
|
@ -19,36 +19,35 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
|
|
||||||
public class PgpDecryptVerifyResult implements Parcelable {
|
public class PgpDecryptVerifyResult implements Parcelable {
|
||||||
boolean symmetricPassphraseNeeded;
|
boolean mSymmetricPassphraseNeeded;
|
||||||
boolean keyPassphraseNeeded;
|
boolean mKeyPassphraseNeeded;
|
||||||
OpenPgpSignatureResult signatureResult;
|
OpenPgpSignatureResult mSignatureResult;
|
||||||
|
|
||||||
public boolean isSymmetricPassphraseNeeded() {
|
public boolean isSymmetricPassphraseNeeded() {
|
||||||
return symmetricPassphraseNeeded;
|
return mSymmetricPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSymmetricPassphraseNeeded(boolean symmetricPassphraseNeeded) {
|
public void setSymmetricPassphraseNeeded(boolean symmetricPassphraseNeeded) {
|
||||||
this.symmetricPassphraseNeeded = symmetricPassphraseNeeded;
|
this.mSymmetricPassphraseNeeded = symmetricPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isKeyPassphraseNeeded() {
|
public boolean isKeyPassphraseNeeded() {
|
||||||
return keyPassphraseNeeded;
|
return mKeyPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyPassphraseNeeded(boolean keyPassphraseNeeded) {
|
public void setKeyPassphraseNeeded(boolean keyPassphraseNeeded) {
|
||||||
this.keyPassphraseNeeded = keyPassphraseNeeded;
|
this.mKeyPassphraseNeeded = keyPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenPgpSignatureResult getSignatureResult() {
|
public OpenPgpSignatureResult getSignatureResult() {
|
||||||
return signatureResult;
|
return mSignatureResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
|
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
|
||||||
this.signatureResult = signatureResult;
|
this.mSignatureResult = signatureResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PgpDecryptVerifyResult() {
|
public PgpDecryptVerifyResult() {
|
||||||
@ -56,9 +55,9 @@ public class PgpDecryptVerifyResult implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) {
|
public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) {
|
||||||
this.symmetricPassphraseNeeded = b.symmetricPassphraseNeeded;
|
this.mSymmetricPassphraseNeeded = b.mSymmetricPassphraseNeeded;
|
||||||
this.keyPassphraseNeeded = b.keyPassphraseNeeded;
|
this.mKeyPassphraseNeeded = b.mKeyPassphraseNeeded;
|
||||||
this.signatureResult = b.signatureResult;
|
this.mSignatureResult = b.mSignatureResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,17 +66,17 @@ public class PgpDecryptVerifyResult implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeByte((byte) (symmetricPassphraseNeeded ? 1 : 0));
|
dest.writeByte((byte) (mSymmetricPassphraseNeeded ? 1 : 0));
|
||||||
dest.writeByte((byte) (keyPassphraseNeeded ? 1 : 0));
|
dest.writeByte((byte) (mKeyPassphraseNeeded ? 1 : 0));
|
||||||
dest.writeParcelable(signatureResult, 0);
|
dest.writeParcelable(mSignatureResult, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {
|
public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {
|
||||||
public PgpDecryptVerifyResult createFromParcel(final Parcel source) {
|
public PgpDecryptVerifyResult createFromParcel(final Parcel source) {
|
||||||
PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult();
|
PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult();
|
||||||
vr.symmetricPassphraseNeeded = source.readByte() == 1;
|
vr.mSymmetricPassphraseNeeded = source.readByte() == 1;
|
||||||
vr.keyPassphraseNeeded = source.readByte() == 1;
|
vr.mKeyPassphraseNeeded = source.readByte() == 1;
|
||||||
vr.signatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
||||||
return vr;
|
return vr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,22 +17,10 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import java.io.File;
|
import android.content.Context;
|
||||||
import java.io.FileNotFoundException;
|
import android.content.pm.PackageInfo;
|
||||||
import java.io.IOException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import java.io.InputStream;
|
import org.spongycastle.openpgp.*;
|
||||||
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 org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -42,21 +30,25 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
|
|
||||||
import android.content.Context;
|
import java.io.File;
|
||||||
import android.content.pm.PackageInfo;
|
import java.io.IOException;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
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 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);
|
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
|
||||||
|
|
||||||
public static Pattern PGP_SIGNED_MESSAGE = Pattern
|
public static final Pattern PGP_SIGNED_MESSAGE = Pattern
|
||||||
.compile(
|
.compile(
|
||||||
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
|
||||||
Pattern.DOTALL);
|
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-----).*",
|
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
@ -140,7 +132,7 @@ public class PgpHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random filename
|
* Generate a random filename
|
||||||
*
|
*
|
||||||
* @param length
|
* @param length
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -170,7 +162,7 @@ public class PgpHelper {
|
|||||||
/**
|
/**
|
||||||
* Go once through stream to get length of stream. The length is later used to display progress
|
* Go once through stream to get length of stream. The length is later used to display progress
|
||||||
* when encrypting/decrypting
|
* when encrypting/decrypting
|
||||||
*
|
*
|
||||||
* @param in
|
* @param in
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
@ -187,9 +179,9 @@ public class PgpHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes file securely by overwriting it with random data before deleting it.
|
* Deletes file securely by overwriting it with random data before deleting it.
|
||||||
*
|
* <p/>
|
||||||
* TODO: Does this really help on flash storage?
|
* TODO: Does this really help on flash storage?
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param progress
|
* @param progress
|
||||||
* @param file
|
* @param file
|
||||||
@ -206,8 +198,9 @@ public class PgpHelper {
|
|||||||
int pos = 0;
|
int pos = 0;
|
||||||
String msg = context.getString(R.string.progress_deleting_securely, file.getName());
|
String msg = context.getString(R.string.progress_deleting_securely, file.getName());
|
||||||
while (pos < length) {
|
while (pos < length) {
|
||||||
if (progress != null)
|
if (progress != null) {
|
||||||
progress.setProgress(msg, (int) (100 * pos / length), 100);
|
progress.setProgress(msg, (int) (100 * pos / length), 100);
|
||||||
|
}
|
||||||
random.nextBytes(data);
|
random.nextBytes(data);
|
||||||
raf.write(data);
|
raf.write(data);
|
||||||
pos += data.length;
|
pos += data.length;
|
||||||
|
@ -17,20 +17,11 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import android.content.Context;
|
||||||
import java.io.FileNotFoundException;
|
import android.os.Bundle;
|
||||||
import java.io.IOException;
|
import android.os.Environment;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.*;
|
||||||
import org.spongycastle.openpgp.PGPKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
@ -39,26 +30,36 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
|||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
|
||||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
import org.sufficientlysecure.keychain.util.*;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
|
||||||
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import java.io.ByteArrayOutputStream;
|
||||||
import android.os.Bundle;
|
import java.io.IOException;
|
||||||
import android.os.Environment;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PgpImportExport {
|
public class PgpImportExport {
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ProgressDialogUpdater mProgress;
|
private ProgressDialogUpdater mProgress;
|
||||||
|
|
||||||
|
private KeychainServiceListener mKeychainServiceListener;
|
||||||
|
|
||||||
public PgpImportExport(Context context, ProgressDialogUpdater progress) {
|
public PgpImportExport(Context context, ProgressDialogUpdater progress) {
|
||||||
super();
|
super();
|
||||||
this.mContext = context;
|
this.mContext = context;
|
||||||
this.mProgress = progress;
|
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) {
|
public void updateProgress(int message, int current, int total) {
|
||||||
if (mProgress != null) {
|
if (mProgress != null) {
|
||||||
mProgress.setProgress(message, current, total);
|
mProgress.setProgress(message, current, total);
|
||||||
@ -96,8 +97,8 @@ public class PgpImportExport {
|
|||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (aos != null) aos.close();
|
if (aos != null) { aos.close(); }
|
||||||
if (bos != null) bos.close();
|
if (bos != null) { bos.close(); }
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,8 +189,10 @@ public class PgpImportExport {
|
|||||||
if (secretKeyRing != null) {
|
if (secretKeyRing != null) {
|
||||||
secretKeyRing.encode(arOutStream);
|
secretKeyRing.encode(arOutStream);
|
||||||
}
|
}
|
||||||
// Else if it's a public key get the PGPPublicKeyRing
|
if (mKeychainServiceListener.hasServiceStopped()) {
|
||||||
// and encode that to the output
|
arOutStream.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
updateProgress(i * 100 / rowIdsSize, 100);
|
updateProgress(i * 100 / rowIdsSize, 100);
|
||||||
PGPPublicKeyRing publicKeyRing =
|
PGPPublicKeyRing publicKeyRing =
|
||||||
@ -198,6 +201,11 @@ public class PgpImportExport {
|
|||||||
if (publicKeyRing != null) {
|
if (publicKeyRing != null) {
|
||||||
publicKeyRing.encode(arOutStream);
|
publicKeyRing.encode(arOutStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mKeychainServiceListener.hasServiceStopped()) {
|
||||||
|
arOutStream.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arOutStream.close();
|
arOutStream.close();
|
||||||
@ -245,8 +253,9 @@ public class PgpImportExport {
|
|||||||
}
|
}
|
||||||
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
|
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
|
||||||
}
|
}
|
||||||
if (newPubRing != null)
|
if (newPubRing != null) {
|
||||||
ProviderHelper.saveKeyRing(mContext, newPubRing);
|
ProviderHelper.saveKeyRing(mContext, newPubRing);
|
||||||
|
}
|
||||||
// TODO: remove status returns, use exceptions!
|
// TODO: remove status returns, use exceptions!
|
||||||
status = Id.return_value.ok;
|
status = Id.return_value.ok;
|
||||||
}
|
}
|
||||||
|
@ -17,21 +17,9 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import android.content.Context;
|
||||||
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 org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.*;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -39,7 +27,9 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import android.content.Context;
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class PgpKeyHelper {
|
public class PgpKeyHelper {
|
||||||
|
|
||||||
|
@ -17,48 +17,20 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import android.content.Context;
|
||||||
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 org.spongycastle.bcpg.CompressionAlgorithmTags;
|
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
|
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.*;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
|
||||||
import org.spongycastle.openpgp.PGPKeyPair;
|
|
||||||
import org.spongycastle.openpgp.PGPKeyRingGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||||
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||||
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.*;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -68,21 +40,27 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
import org.sufficientlysecure.keychain.util.Primes;
|
import org.sufficientlysecure.keychain.util.Primes;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
|
|
||||||
import 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 {
|
public class PgpKeyOperation {
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ProgressDialogUpdater mProgress;
|
private ProgressDialogUpdater mProgress;
|
||||||
|
|
||||||
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
|
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
|
||||||
SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
|
SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
|
||||||
SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
|
SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
|
||||||
SymmetricKeyAlgorithmTags.TRIPLE_DES };
|
SymmetricKeyAlgorithmTags.TRIPLE_DES};
|
||||||
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] { HashAlgorithmTags.SHA1,
|
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{HashAlgorithmTags.SHA1,
|
||||||
HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160 };
|
HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160};
|
||||||
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] {
|
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
|
||||||
CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
|
CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
|
||||||
CompressionAlgorithmTags.ZIP };
|
CompressionAlgorithmTags.ZIP};
|
||||||
|
|
||||||
public PgpKeyOperation(Context context, ProgressDialogUpdater progress) {
|
public PgpKeyOperation(Context context, ProgressDialogUpdater progress) {
|
||||||
super();
|
super();
|
||||||
@ -104,7 +82,7 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new secret key.
|
* Creates new secret key.
|
||||||
*
|
*
|
||||||
* @param algorithmChoice
|
* @param algorithmChoice
|
||||||
* @param keySize
|
* @param keySize
|
||||||
* @param passphrase
|
* @param passphrase
|
||||||
@ -119,8 +97,9 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
// TODO: key flags?
|
// TODO: key flags?
|
||||||
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
|
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
|
||||||
boolean isMasterKey) throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
boolean isMasterKey)
|
||||||
PgpGeneralException, InvalidAlgorithmParameterException {
|
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||||
|
PgpGeneralException, InvalidAlgorithmParameterException {
|
||||||
|
|
||||||
if (keySize < 512) {
|
if (keySize < 512) {
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_key_size_minimum512bit));
|
throw new PgpGeneralException(mContext.getString(R.string.error_key_size_minimum512bit));
|
||||||
@ -134,41 +113,41 @@ public class PgpKeyOperation {
|
|||||||
KeyPairGenerator keyGen = null;
|
KeyPairGenerator keyGen = null;
|
||||||
|
|
||||||
switch (algorithmChoice) {
|
switch (algorithmChoice) {
|
||||||
case Id.choice.algorithm.dsa: {
|
case Id.choice.algorithm.dsa: {
|
||||||
keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
keyGen.initialize(keySize, new SecureRandom());
|
keyGen.initialize(keySize, new SecureRandom());
|
||||||
algorithm = PGPPublicKey.DSA;
|
algorithm = PGPPublicKey.DSA;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case Id.choice.algorithm.elgamal: {
|
|
||||||
if (isMasterKey) {
|
|
||||||
throw new PgpGeneralException(
|
|
||||||
mContext.getString(R.string.error_master_key_must_not_be_el_gamal));
|
|
||||||
}
|
}
|
||||||
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
BigInteger p = Primes.getBestPrime(keySize);
|
|
||||||
BigInteger g = new BigInteger("2");
|
|
||||||
|
|
||||||
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
|
case Id.choice.algorithm.elgamal: {
|
||||||
|
if (isMasterKey) {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
mContext.getString(R.string.error_master_key_must_not_be_el_gamal));
|
||||||
|
}
|
||||||
|
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
BigInteger p = Primes.getBestPrime(keySize);
|
||||||
|
BigInteger g = new BigInteger("2");
|
||||||
|
|
||||||
keyGen.initialize(elParams);
|
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
|
||||||
algorithm = PGPPublicKey.ELGAMAL_ENCRYPT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Id.choice.algorithm.rsa: {
|
keyGen.initialize(elParams);
|
||||||
keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
algorithm = PGPPublicKey.ELGAMAL_ENCRYPT;
|
||||||
keyGen.initialize(keySize, new SecureRandom());
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
algorithm = PGPPublicKey.RSA_GENERAL;
|
case Id.choice.algorithm.rsa: {
|
||||||
break;
|
keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
}
|
keyGen.initialize(keySize, new SecureRandom());
|
||||||
|
|
||||||
default: {
|
algorithm = PGPPublicKey.RSA_GENERAL;
|
||||||
throw new PgpGeneralException(
|
break;
|
||||||
mContext.getString(R.string.error_unknown_algorithm_choice));
|
}
|
||||||
}
|
|
||||||
|
default: {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
mContext.getString(R.string.error_unknown_algorithm_choice));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// build new key pair
|
// build new key pair
|
||||||
@ -184,13 +163,13 @@ public class PgpKeyOperation {
|
|||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||||
|
|
||||||
PGPSecretKey secKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
PGPSecretKey secKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
||||||
sha1Calc, isMasterKey, keyEncryptor);
|
sha1Calc, isMasterKey, keyEncryptor);
|
||||||
|
|
||||||
return secKey;
|
return secKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
|
public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
|
||||||
String newPassPhrase) throws IOException, PGPException,
|
String newPassPhrase) throws IOException, PGPException,
|
||||||
NoSuchProviderException {
|
NoSuchProviderException {
|
||||||
|
|
||||||
updateProgress(R.string.progress_building_key, 0, 100);
|
updateProgress(R.string.progress_building_key, 0, 100);
|
||||||
@ -218,9 +197,9 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void buildSecretKey(ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
|
public void buildSecretKey(ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
|
||||||
ArrayList<Integer> keysUsages, ArrayList<GregorianCalendar> keysExpiryDates,
|
ArrayList<Integer> keysUsages, ArrayList<GregorianCalendar> keysExpiryDates,
|
||||||
long masterKeyId, String oldPassPhrase,
|
long masterKeyId, String oldPassPhrase,
|
||||||
String newPassPhrase) throws PgpGeneralException, NoSuchProviderException,
|
String newPassPhrase) throws PgpGeneralException, NoSuchProviderException,
|
||||||
PGPException, NoSuchAlgorithmException, SignatureException, IOException {
|
PGPException, NoSuchAlgorithmException, SignatureException, IOException {
|
||||||
|
|
||||||
Log.d(Constants.TAG, "userIds: " + userIds.toString());
|
Log.d(Constants.TAG, "userIds: " + userIds.toString());
|
||||||
@ -237,8 +216,10 @@ public class PgpKeyOperation {
|
|||||||
updateProgress(R.string.progress_preparing_master_key, 10, 100);
|
updateProgress(R.string.progress_preparing_master_key, 10, 100);
|
||||||
|
|
||||||
int usageId = keysUsages.get(0);
|
int usageId = keysUsages.get(0);
|
||||||
boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
boolean canSign =
|
||||||
boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
(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);
|
String mainUserId = userIds.get(0);
|
||||||
|
|
||||||
@ -303,13 +284,17 @@ public class PgpKeyOperation {
|
|||||||
GregorianCalendar expiryDate = keysExpiryDates.get(0);
|
GregorianCalendar expiryDate = keysExpiryDates.get(0);
|
||||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||||
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
long numDays =
|
||||||
if (numDays <= 0)
|
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
if (numDays <= 0) {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||||
|
}
|
||||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||||
} else {
|
} else {
|
||||||
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
|
//do this explicitly, although since we're rebuilding,
|
||||||
//this happens anyway
|
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||||
|
//this happens anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProgress(R.string.progress_building_master_key, 30, 100);
|
updateProgress(R.string.progress_building_master_key, 30, 100);
|
||||||
@ -352,8 +337,10 @@ public class PgpKeyOperation {
|
|||||||
keyFlags = 0;
|
keyFlags = 0;
|
||||||
|
|
||||||
usageId = keysUsages.get(i);
|
usageId = keysUsages.get(i);
|
||||||
canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
canSign =
|
||||||
canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
(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) {
|
if (canSign) {
|
||||||
Date todayDate = new Date(); //both sig times the same
|
Date todayDate = new Date(); //both sig times the same
|
||||||
keyFlags |= KeyFlags.SIGN_DATA;
|
keyFlags |= KeyFlags.SIGN_DATA;
|
||||||
@ -382,13 +369,17 @@ public class PgpKeyOperation {
|
|||||||
GregorianCalendar expiryDate = keysExpiryDates.get(i);
|
GregorianCalendar expiryDate = keysExpiryDates.get(i);
|
||||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||||
long numDays = (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
long numDays =
|
||||||
if (numDays <= 0)
|
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
if (numDays <= 0) {
|
||||||
|
throw new PgpGeneralException
|
||||||
|
(mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||||
|
}
|
||||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||||
} else {
|
} else {
|
||||||
hashedPacketsGen.setKeyExpirationTime(false, 0); //do this explicitly, although since we're rebuilding,
|
//do this explicitly, although since we're rebuilding,
|
||||||
//this happens anyway
|
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||||
|
//this happens anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
|
keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
|
||||||
|
@ -18,28 +18,11 @@
|
|||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.bcpg.BCPGOutputStream;
|
import org.spongycastle.bcpg.BCPGOutputStream;
|
||||||
import org.spongycastle.openpgp.PGPCompressedDataGenerator;
|
import org.spongycastle.openpgp.*;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPException;
|
|
||||||
import org.spongycastle.openpgp.PGPLiteralData;
|
|
||||||
import org.spongycastle.openpgp.PGPLiteralDataGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
|
||||||
import org.spongycastle.openpgp.PGPV3SignatureGenerator;
|
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.*;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -49,11 +32,7 @@ import org.sufficientlysecure.keychain.util.InputData;
|
|||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
@ -63,110 +42,110 @@ import java.util.Date;
|
|||||||
* This class uses a Builder pattern!
|
* This class uses a Builder pattern!
|
||||||
*/
|
*/
|
||||||
public class PgpSignEncrypt {
|
public class PgpSignEncrypt {
|
||||||
private Context context;
|
private Context mContext;
|
||||||
private InputData data;
|
private InputData mData;
|
||||||
private OutputStream outStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
private ProgressDialogUpdater progress;
|
private ProgressDialogUpdater mProgress;
|
||||||
private boolean enableAsciiArmorOutput;
|
private boolean mEnableAsciiArmorOutput;
|
||||||
private int compressionId;
|
private int mCompressionId;
|
||||||
private long[] encryptionKeyIds;
|
private long[] mEncryptionKeyIds;
|
||||||
private String encryptionPassphrase;
|
private String mEncryptionPassphrase;
|
||||||
private int symmetricEncryptionAlgorithm;
|
private int mSymmetricEncryptionAlgorithm;
|
||||||
private long signatureKeyId;
|
private long mSignatureKeyId;
|
||||||
private int signatureHashAlgorithm;
|
private int mSignatureHashAlgorithm;
|
||||||
private boolean signatureForceV3;
|
private boolean mSignatureForceV3;
|
||||||
private String signaturePassphrase;
|
private String mSignaturePassphrase;
|
||||||
|
|
||||||
private PgpSignEncrypt(Builder builder) {
|
private PgpSignEncrypt(Builder builder) {
|
||||||
// private Constructor can only be called from Builder
|
// private Constructor can only be called from Builder
|
||||||
this.context = builder.context;
|
this.mContext = builder.mContext;
|
||||||
this.data = builder.data;
|
this.mData = builder.mData;
|
||||||
this.outStream = builder.outStream;
|
this.mOutStream = builder.mOutStream;
|
||||||
|
|
||||||
this.progress = builder.progress;
|
this.mProgress = builder.mProgress;
|
||||||
this.enableAsciiArmorOutput = builder.enableAsciiArmorOutput;
|
this.mEnableAsciiArmorOutput = builder.mEnableAsciiArmorOutput;
|
||||||
this.compressionId = builder.compressionId;
|
this.mCompressionId = builder.mCompressionId;
|
||||||
this.encryptionKeyIds = builder.encryptionKeyIds;
|
this.mEncryptionKeyIds = builder.mEncryptionKeyIds;
|
||||||
this.encryptionPassphrase = builder.encryptionPassphrase;
|
this.mEncryptionPassphrase = builder.mEncryptionPassphrase;
|
||||||
this.symmetricEncryptionAlgorithm = builder.symmetricEncryptionAlgorithm;
|
this.mSymmetricEncryptionAlgorithm = builder.mSymmetricEncryptionAlgorithm;
|
||||||
this.signatureKeyId = builder.signatureKeyId;
|
this.mSignatureKeyId = builder.mSignatureKeyId;
|
||||||
this.signatureHashAlgorithm = builder.signatureHashAlgorithm;
|
this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm;
|
||||||
this.signatureForceV3 = builder.signatureForceV3;
|
this.mSignatureForceV3 = builder.mSignatureForceV3;
|
||||||
this.signaturePassphrase = builder.signaturePassphrase;
|
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
// mandatory parameter
|
// mandatory parameter
|
||||||
private Context context;
|
private Context mContext;
|
||||||
private InputData data;
|
private InputData mData;
|
||||||
private OutputStream outStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
// optional
|
// optional
|
||||||
private ProgressDialogUpdater progress = null;
|
private ProgressDialogUpdater mProgress = null;
|
||||||
private boolean enableAsciiArmorOutput = false;
|
private boolean mEnableAsciiArmorOutput = false;
|
||||||
private int compressionId = Id.choice.compression.none;
|
private int mCompressionId = Id.choice.compression.none;
|
||||||
private long[] encryptionKeyIds = new long[0];
|
private long[] mEncryptionKeyIds = new long[0];
|
||||||
private String encryptionPassphrase = null;
|
private String mEncryptionPassphrase = null;
|
||||||
private int symmetricEncryptionAlgorithm = 0;
|
private int mSymmetricEncryptionAlgorithm = 0;
|
||||||
private long signatureKeyId = Id.key.none;
|
private long mSignatureKeyId = Id.key.none;
|
||||||
private int signatureHashAlgorithm = 0;
|
private int mSignatureHashAlgorithm = 0;
|
||||||
private boolean signatureForceV3 = false;
|
private boolean mSignatureForceV3 = false;
|
||||||
private String signaturePassphrase = null;
|
private String mSignaturePassphrase = null;
|
||||||
|
|
||||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
public Builder(Context context, InputData data, OutputStream outStream) {
|
||||||
this.context = context;
|
this.mContext = context;
|
||||||
this.data = data;
|
this.mData = data;
|
||||||
this.outStream = outStream;
|
this.mOutStream = outStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder progress(ProgressDialogUpdater progress) {
|
public Builder progress(ProgressDialogUpdater progress) {
|
||||||
this.progress = progress;
|
this.mProgress = progress;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder enableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
|
public Builder enableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
|
||||||
this.enableAsciiArmorOutput = enableAsciiArmorOutput;
|
this.mEnableAsciiArmorOutput = enableAsciiArmorOutput;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder compressionId(int compressionId) {
|
public Builder compressionId(int compressionId) {
|
||||||
this.compressionId = compressionId;
|
this.mCompressionId = compressionId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder encryptionKeyIds(long[] encryptionKeyIds) {
|
public Builder encryptionKeyIds(long[] encryptionKeyIds) {
|
||||||
this.encryptionKeyIds = encryptionKeyIds;
|
this.mEncryptionKeyIds = encryptionKeyIds;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder encryptionPassphrase(String encryptionPassphrase) {
|
public Builder encryptionPassphrase(String encryptionPassphrase) {
|
||||||
this.encryptionPassphrase = encryptionPassphrase;
|
this.mEncryptionPassphrase = encryptionPassphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder symmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
|
public Builder symmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
|
||||||
this.symmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
|
this.mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder signatureKeyId(long signatureKeyId) {
|
public Builder signatureKeyId(long signatureKeyId) {
|
||||||
this.signatureKeyId = signatureKeyId;
|
this.mSignatureKeyId = signatureKeyId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder signatureHashAlgorithm(int signatureHashAlgorithm) {
|
public Builder signatureHashAlgorithm(int signatureHashAlgorithm) {
|
||||||
this.signatureHashAlgorithm = signatureHashAlgorithm;
|
this.mSignatureHashAlgorithm = signatureHashAlgorithm;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder signatureForceV3(boolean signatureForceV3) {
|
public Builder signatureForceV3(boolean signatureForceV3) {
|
||||||
this.signatureForceV3 = signatureForceV3;
|
this.mSignatureForceV3 = signatureForceV3;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder signaturePassphrase(String signaturePassphrase) {
|
public Builder signaturePassphrase(String signaturePassphrase) {
|
||||||
this.signaturePassphrase = signaturePassphrase;
|
this.mSignaturePassphrase = signaturePassphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,14 +155,14 @@ public class PgpSignEncrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateProgress(int message, int current, int total) {
|
public void updateProgress(int message, int current, int total) {
|
||||||
if (progress != null) {
|
if (mProgress != null) {
|
||||||
progress.setProgress(message, current, total);
|
mProgress.setProgress(message, current, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateProgress(int current, int total) {
|
public void updateProgress(int current, int total) {
|
||||||
if (progress != null) {
|
if (mProgress != null) {
|
||||||
progress.setProgress(current, total);
|
mProgress.setProgress(current, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,17 +180,17 @@ public class PgpSignEncrypt {
|
|||||||
throws IOException, PgpGeneralException, PGPException, NoSuchProviderException,
|
throws IOException, PgpGeneralException, PGPException, NoSuchProviderException,
|
||||||
NoSuchAlgorithmException, SignatureException {
|
NoSuchAlgorithmException, SignatureException {
|
||||||
|
|
||||||
boolean enableSignature = signatureKeyId != Id.key.none;
|
boolean enableSignature = mSignatureKeyId != Id.key.none;
|
||||||
boolean enableEncryption = (encryptionKeyIds.length != 0 || encryptionPassphrase != null);
|
boolean enableEncryption = (mEncryptionKeyIds.length != 0 || mEncryptionPassphrase != null);
|
||||||
boolean enableCompression = (enableEncryption && compressionId != Id.choice.compression.none);
|
boolean enableCompression = (enableEncryption && mCompressionId != Id.choice.compression.none);
|
||||||
|
|
||||||
Log.d(Constants.TAG, "enableSignature:" + enableSignature
|
Log.d(Constants.TAG, "enableSignature:" + enableSignature
|
||||||
+ "\nenableEncryption:" + enableEncryption
|
+ "\nenableEncryption:" + enableEncryption
|
||||||
+ "\nenableCompression:" + enableCompression
|
+ "\nenableCompression:" + enableCompression
|
||||||
+ "\nenableAsciiArmorOutput:" + enableAsciiArmorOutput);
|
+ "\nenableAsciiArmorOutput:" + mEnableAsciiArmorOutput);
|
||||||
|
|
||||||
int signatureType;
|
int signatureType;
|
||||||
if (enableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
if (mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||||
// for sign-only ascii text
|
// for sign-only ascii text
|
||||||
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
|
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
|
||||||
} else {
|
} else {
|
||||||
@ -220,12 +199,12 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
ArmoredOutputStream armorOut = null;
|
ArmoredOutputStream armorOut = null;
|
||||||
OutputStream out;
|
OutputStream out;
|
||||||
if (enableAsciiArmorOutput) {
|
if (mEnableAsciiArmorOutput) {
|
||||||
armorOut = new ArmoredOutputStream(outStream);
|
armorOut = new ArmoredOutputStream(mOutStream);
|
||||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(context));
|
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
|
||||||
out = armorOut;
|
out = armorOut;
|
||||||
} else {
|
} else {
|
||||||
out = outStream;
|
out = mOutStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get keys for signature generation for later usage */
|
/* Get keys for signature generation for later usage */
|
||||||
@ -233,25 +212,25 @@ public class PgpSignEncrypt {
|
|||||||
PGPSecretKeyRing signingKeyRing = null;
|
PGPSecretKeyRing signingKeyRing = null;
|
||||||
PGPPrivateKey signaturePrivateKey = null;
|
PGPPrivateKey signaturePrivateKey = null;
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
|
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId);
|
||||||
signingKey = PgpKeyHelper.getSigningKey(context, signatureKeyId);
|
signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId);
|
||||||
if (signingKey == null) {
|
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(
|
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);
|
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
|
||||||
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
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);
|
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new PgpGeneralException(
|
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);
|
updateProgress(R.string.progress_preparing_streams, 5, 100);
|
||||||
@ -261,23 +240,23 @@ public class PgpSignEncrypt {
|
|||||||
if (enableEncryption) {
|
if (enableEncryption) {
|
||||||
// has Integrity packet enabled!
|
// has Integrity packet enabled!
|
||||||
JcePGPDataEncryptorBuilder encryptorBuilder =
|
JcePGPDataEncryptorBuilder encryptorBuilder =
|
||||||
new JcePGPDataEncryptorBuilder(symmetricEncryptionAlgorithm)
|
new JcePGPDataEncryptorBuilder(mSymmetricEncryptionAlgorithm)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
|
||||||
.setWithIntegrityPacket(true);
|
.setWithIntegrityPacket(true);
|
||||||
|
|
||||||
cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
|
cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
|
||||||
|
|
||||||
if (encryptionKeyIds.length == 0) {
|
if (mEncryptionKeyIds.length == 0) {
|
||||||
// Symmetric encryption
|
// Symmetric encryption
|
||||||
Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
|
Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
|
||||||
|
|
||||||
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
|
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
|
||||||
new JcePBEKeyEncryptionMethodGenerator(encryptionPassphrase.toCharArray());
|
new JcePBEKeyEncryptionMethodGenerator(mEncryptionPassphrase.toCharArray());
|
||||||
cPk.addMethod(symmetricEncryptionGenerator);
|
cPk.addMethod(symmetricEncryptionGenerator);
|
||||||
} else {
|
} else {
|
||||||
// Asymmetric encryption
|
// Asymmetric encryption
|
||||||
for (long id : encryptionKeyIds) {
|
for (long id : mEncryptionKeyIds) {
|
||||||
PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(context, id);
|
PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(mContext, id);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator =
|
JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator =
|
||||||
new JcePublicKeyKeyEncryptionMethodGenerator(key);
|
new JcePublicKeyKeyEncryptionMethodGenerator(key);
|
||||||
@ -295,10 +274,10 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
// content signer based on signing key algorithm and chosen hash algorithm
|
// content signer based on signing key algorithm and chosen hash algorithm
|
||||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||||
signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
|
signingKey.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
||||||
signatureV3Generator.init(signatureType, signaturePrivateKey);
|
signatureV3Generator.init(signatureType, signaturePrivateKey);
|
||||||
} else {
|
} else {
|
||||||
@ -322,14 +301,14 @@ public class PgpSignEncrypt {
|
|||||||
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
||||||
|
|
||||||
if (enableCompression) {
|
if (enableCompression) {
|
||||||
compressGen = new PGPCompressedDataGenerator(compressionId);
|
compressGen = new PGPCompressedDataGenerator(mCompressionId);
|
||||||
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
|
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
|
||||||
} else {
|
} else {
|
||||||
bcpgOut = new BCPGOutputStream(encryptionOut);
|
bcpgOut = new BCPGOutputStream(encryptionOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
|
signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
|
signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
|
||||||
@ -345,13 +324,13 @@ public class PgpSignEncrypt {
|
|||||||
long progress = 0;
|
long progress = 0;
|
||||||
int n;
|
int n;
|
||||||
byte[] buffer = new byte[1 << 16];
|
byte[] buffer = new byte[1 << 16];
|
||||||
InputStream in = data.getInputStream();
|
InputStream in = mData.getInputStream();
|
||||||
while ((n = in.read(buffer)) > 0) {
|
while ((n = in.read(buffer)) > 0) {
|
||||||
pOut.write(buffer, 0, n);
|
pOut.write(buffer, 0, n);
|
||||||
|
|
||||||
// update signature buffer if signature is requested
|
// update signature buffer if signature is requested
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.update(buffer, 0, n);
|
signatureV3Generator.update(buffer, 0, n);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator.update(buffer, 0, n);
|
signatureGenerator.update(buffer, 0, n);
|
||||||
@ -359,26 +338,26 @@ public class PgpSignEncrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress += n;
|
progress += n;
|
||||||
if (data.getSize() != 0) {
|
if (mData.getSize() != 0) {
|
||||||
updateProgress((int) (20 + (95 - 20) * progress / data.getSize()), 100);
|
updateProgress((int) (20 + (95 - 20) * progress / mData.getSize()), 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
literalGen.close();
|
literalGen.close();
|
||||||
} else if (enableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
} else if (mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||||
/* sign-only of ascii text */
|
/* sign-only of ascii text */
|
||||||
|
|
||||||
updateProgress(R.string.progress_signing, 40, 100);
|
updateProgress(R.string.progress_signing, 40, 100);
|
||||||
|
|
||||||
// write directly on armor output stream
|
// 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 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
|
||||||
final byte[] newline = "\r\n".getBytes("UTF-8");
|
final byte[] newline = "\r\n".getBytes("UTF-8");
|
||||||
|
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
processLine(reader.readLine(), armorOut, signatureV3Generator);
|
processLine(reader.readLine(), armorOut, signatureV3Generator);
|
||||||
} else {
|
} else {
|
||||||
processLine(reader.readLine(), armorOut, signatureGenerator);
|
processLine(reader.readLine(), armorOut, signatureGenerator);
|
||||||
@ -395,7 +374,7 @@ public class PgpSignEncrypt {
|
|||||||
armorOut.write(newline);
|
armorOut.write(newline);
|
||||||
|
|
||||||
// update signature buffer with input line
|
// update signature buffer with input line
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.update(newline);
|
signatureV3Generator.update(newline);
|
||||||
processLine(line, armorOut, signatureV3Generator);
|
processLine(line, armorOut, signatureV3Generator);
|
||||||
} else {
|
} else {
|
||||||
@ -415,7 +394,7 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
updateProgress(R.string.progress_generating_signature, 95, 100);
|
updateProgress(R.string.progress_generating_signature, 95, 100);
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.generate().encode(pOut);
|
signatureV3Generator.generate().encode(pOut);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator.generate().encode(pOut);
|
signatureGenerator.generate().encode(pOut);
|
||||||
@ -432,12 +411,12 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
encryptionOut.close();
|
encryptionOut.close();
|
||||||
}
|
}
|
||||||
if (enableAsciiArmorOutput) {
|
if (mEnableAsciiArmorOutput) {
|
||||||
armorOut.close();
|
armorOut.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
outStream.close();
|
mOutStream.close();
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
@ -449,35 +428,36 @@ public class PgpSignEncrypt {
|
|||||||
SignatureException {
|
SignatureException {
|
||||||
|
|
||||||
OutputStream out;
|
OutputStream out;
|
||||||
if (enableAsciiArmorOutput) {
|
if (mEnableAsciiArmorOutput) {
|
||||||
// Ascii Armor (Radix-64)
|
// Ascii Armor (Radix-64)
|
||||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
|
ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
|
||||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(context));
|
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
|
||||||
out = armorOut;
|
out = armorOut;
|
||||||
} else {
|
} else {
|
||||||
out = outStream;
|
out = mOutStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signatureKeyId == 0) {
|
if (mSignatureKeyId == 0) {
|
||||||
throw new PgpGeneralException(context.getString(R.string.error_no_signature_key));
|
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSecretKeyRing signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
|
PGPSecretKeyRing signingKeyRing =
|
||||||
PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(context, signatureKeyId);
|
ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, mSignatureKeyId);
|
||||||
|
PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(mContext, mSignatureKeyId);
|
||||||
if (signingKey == null) {
|
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));
|
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_passphrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
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);
|
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new PgpGeneralException(
|
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);
|
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
|
// content signer based on signing key algorithm and chosen hash algorithm
|
||||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
|
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
|
||||||
.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
|
.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
|
||||||
PGPSignatureGenerator signatureGenerator = null;
|
PGPSignatureGenerator signatureGenerator = null;
|
||||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
PGPV3SignatureGenerator signatureV3Generator = null;
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
||||||
signatureV3Generator.init(type, signaturePrivateKey);
|
signatureV3Generator.init(type, signaturePrivateKey);
|
||||||
} else {
|
} else {
|
||||||
@ -510,7 +490,7 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
updateProgress(R.string.progress_signing, 40, 100);
|
updateProgress(R.string.progress_signing, 40, 100);
|
||||||
|
|
||||||
InputStream inStream = data.getInputStream();
|
InputStream inStream = mData.getInputStream();
|
||||||
// if (binary) {
|
// if (binary) {
|
||||||
// byte[] buffer = new byte[1 << 16];
|
// byte[] buffer = new byte[1 << 16];
|
||||||
// int n = 0;
|
// int n = 0;
|
||||||
@ -527,7 +507,7 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
processLine(line, null, signatureV3Generator);
|
processLine(line, null, signatureV3Generator);
|
||||||
signatureV3Generator.update(newline);
|
signatureV3Generator.update(newline);
|
||||||
} else {
|
} else {
|
||||||
@ -538,13 +518,13 @@ public class PgpSignEncrypt {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
BCPGOutputStream bOut = new BCPGOutputStream(out);
|
BCPGOutputStream bOut = new BCPGOutputStream(out);
|
||||||
if (signatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.generate().encode(bOut);
|
signatureV3Generator.generate().encode(bOut);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator.generate().encode(bOut);
|
signatureGenerator.generate().encode(bOut);
|
||||||
}
|
}
|
||||||
out.close();
|
out.close();
|
||||||
outStream.close();
|
mOutStream.close();
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
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;
|
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.DERObjectIdentifier;
|
||||||
import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
|
import org.spongycastle.asn1.x509.*;
|
||||||
import org.spongycastle.asn1.x509.BasicConstraints;
|
|
||||||
import org.spongycastle.asn1.x509.GeneralName;
|
|
||||||
import org.spongycastle.asn1.x509.GeneralNames;
|
|
||||||
import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
|
|
||||||
import org.spongycastle.asn1.x509.X509Extensions;
|
|
||||||
import org.spongycastle.asn1.x509.X509Name;
|
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
@ -38,30 +29,38 @@ import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure;
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import javax.security.auth.callback.Callback;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.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 class PgpToX509 {
|
||||||
public final static String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";
|
public static final 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_OU = "OpenPGP Keychain cert";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a self-signed certificate from a public and private key. The (critical) key-usage
|
* Creates a self-signed certificate from a public and private key. The (critical) key-usage
|
||||||
* extension is set up with: digital signature, non-repudiation, key-encipherment, key-agreement
|
* extension is set up with: digital signature, non-repudiation, key-encipherment, key-agreement
|
||||||
* and certificate-signing. The (non-critical) Netscape extension is set up with: SSL client and
|
* 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.
|
* S/MIME. A URI subjectAltName may also be set up.
|
||||||
*
|
*
|
||||||
* @param pubKey
|
* @param pubKey public key
|
||||||
* public key
|
* @param privKey private key
|
||||||
* @param privKey
|
* @param subject subject (and issuer) DN for this certificate, RFC 2253 format preferred.
|
||||||
* private key
|
* @param startDate date from which the certificate will be valid (defaults to current date and time
|
||||||
* @param subject
|
* if null)
|
||||||
* subject (and issuer) DN for this certificate, RFC 2253 format preferred.
|
* @param endDate date until which the certificate will be valid (defaults to current date and time
|
||||||
* @param startDate
|
* if null) *
|
||||||
* date from which the certificate will be valid (defaults to current date and time
|
* @param subjAltNameURI URI to be placed in subjectAltName
|
||||||
* if null)
|
|
||||||
* @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
|
|
||||||
* @return self-signed certificate
|
* @return self-signed certificate
|
||||||
* @throws InvalidKeyException
|
* @throws InvalidKeyException
|
||||||
* @throws SignatureException
|
* @throws SignatureException
|
||||||
@ -70,11 +69,10 @@ public class PgpToX509 {
|
|||||||
* @throws NoSuchProviderException
|
* @throws NoSuchProviderException
|
||||||
* @throws CertificateException
|
* @throws CertificateException
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*
|
|
||||||
* @author Bruno Harbulot
|
* @author Bruno Harbulot
|
||||||
*/
|
*/
|
||||||
public static X509Certificate createSelfSignedCert(PublicKey pubKey, PrivateKey privKey,
|
public static X509Certificate createSelfSignedCert(PublicKey pubKey, PrivateKey privKey,
|
||||||
X509Name subject, Date startDate, Date endDate, String subjAltNameURI)
|
X509Name subject, Date startDate, Date endDate, String subjAltNameURI)
|
||||||
throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException,
|
throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException,
|
||||||
SignatureException, CertificateException, NoSuchProviderException {
|
SignatureException, CertificateException, NoSuchProviderException {
|
||||||
|
|
||||||
@ -171,15 +169,12 @@ public class PgpToX509 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a self-signed certificate from a PGP Secret Key.
|
* Creates a self-signed certificate from a PGP Secret Key.
|
||||||
*
|
*
|
||||||
* @param pgpSecKey
|
* @param pgpSecKey PGP Secret Key (from which one can extract the public and private keys and other
|
||||||
* PGP Secret Key (from which one can extract the public and private keys and other
|
* attributes).
|
||||||
* attributes).
|
* @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks should be done
|
||||||
* @param pgpPrivKey
|
* before calling this method)
|
||||||
* PGP Private Key corresponding to the Secret Key (password callbacks should be done
|
* @param subjAltNameURI optional URI to embed in the subject alternative-name
|
||||||
* before calling this method)
|
|
||||||
* @param subjAltNameURI
|
|
||||||
* optional URI to embed in the subject alternative-name
|
|
||||||
* @return self-signed certificate
|
* @return self-signed certificate
|
||||||
* @throws PGPException
|
* @throws PGPException
|
||||||
* @throws NoSuchProviderException
|
* @throws NoSuchProviderException
|
||||||
@ -187,11 +182,10 @@ public class PgpToX509 {
|
|||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
* @throws SignatureException
|
* @throws SignatureException
|
||||||
* @throws CertificateException
|
* @throws CertificateException
|
||||||
*
|
|
||||||
* @author Bruno Harbulot
|
* @author Bruno Harbulot
|
||||||
*/
|
*/
|
||||||
public static X509Certificate createSelfSignedCert(PGPSecretKey pgpSecKey,
|
public static X509Certificate createSelfSignedCert(PGPSecretKey pgpSecKey,
|
||||||
PGPPrivateKey pgpPrivKey, String subjAltNameURI) throws PGPException,
|
PGPPrivateKey pgpPrivKey, String subjAltNameURI) throws PGPException,
|
||||||
NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException,
|
NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException,
|
||||||
SignatureException, CertificateException {
|
SignatureException, CertificateException {
|
||||||
// get public key from secret key
|
// get public key from secret key
|
||||||
@ -213,7 +207,7 @@ public class PgpToX509 {
|
|||||||
x509NameValues.add(DN_COMMON_PART_OU);
|
x509NameValues.add(DN_COMMON_PART_OU);
|
||||||
|
|
||||||
for (@SuppressWarnings("unchecked")
|
for (@SuppressWarnings("unchecked")
|
||||||
Iterator<Object> it = (Iterator<Object>) pgpSecKey.getUserIDs(); it.hasNext();) {
|
Iterator<Object> it = (Iterator<Object>) pgpSecKey.getUserIDs(); it.hasNext(); ) {
|
||||||
Object attrib = it.next();
|
Object attrib = it.next();
|
||||||
x509NameOids.add(X509Name.CN);
|
x509NameOids.add(X509Name.CN);
|
||||||
x509NameValues.add("CryptoCall");
|
x509NameValues.add("CryptoCall");
|
||||||
@ -225,7 +219,7 @@ public class PgpToX509 {
|
|||||||
*/
|
*/
|
||||||
Log.d(Constants.TAG, "User attributes: ");
|
Log.d(Constants.TAG, "User attributes: ");
|
||||||
for (@SuppressWarnings("unchecked")
|
for (@SuppressWarnings("unchecked")
|
||||||
Iterator<Object> it = (Iterator<Object>) pgpSecKey.getUserAttributes(); it.hasNext();) {
|
Iterator<Object> it = (Iterator<Object>) pgpSecKey.getUserAttributes(); it.hasNext(); ) {
|
||||||
Object attrib = it.next();
|
Object attrib = it.next();
|
||||||
Log.d(Constants.TAG, " - " + attrib + " -- " + attrib.getClass());
|
Log.d(Constants.TAG, " - " + attrib + " -- " + attrib.getClass());
|
||||||
}
|
}
|
||||||
@ -261,14 +255,13 @@ public class PgpToX509 {
|
|||||||
* This is a password callback handler that will fill in a password automatically. Useful to
|
* This is a password callback handler that will fill in a password automatically. Useful to
|
||||||
* configure passwords in advance, but should be used with caution depending on how much you
|
* configure passwords in advance, but should be used with caution depending on how much you
|
||||||
* allow passwords to be stored within your application.
|
* allow passwords to be stored within your application.
|
||||||
*
|
*
|
||||||
* @author Bruno Harbulot.
|
* @author Bruno Harbulot.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public final static class PredefinedPasswordCallbackHandler implements CallbackHandler {
|
public static final class PredefinedPasswordCallbackHandler implements CallbackHandler {
|
||||||
|
|
||||||
private char[] password;
|
private char[] mPassword;
|
||||||
private String prompt;
|
private String mPrompt;
|
||||||
|
|
||||||
public PredefinedPasswordCallbackHandler(String password) {
|
public PredefinedPasswordCallbackHandler(String password) {
|
||||||
this(password == null ? null : password.toCharArray(), null);
|
this(password == null ? null : password.toCharArray(), null);
|
||||||
@ -283,16 +276,16 @@ public class PgpToX509 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PredefinedPasswordCallbackHandler(char[] password, String prompt) {
|
public PredefinedPasswordCallbackHandler(char[] password, String prompt) {
|
||||||
this.password = password;
|
this.mPassword = password;
|
||||||
this.prompt = prompt;
|
this.mPrompt = prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||||
for (Callback callback : callbacks) {
|
for (Callback callback : callbacks) {
|
||||||
if (callback instanceof PasswordCallback) {
|
if (callback instanceof PasswordCallback) {
|
||||||
PasswordCallback pwCallback = (PasswordCallback) callback;
|
PasswordCallback pwCallback = (PasswordCallback) callback;
|
||||||
if ((this.prompt == null) || (this.prompt.equals(pwCallback.getPrompt()))) {
|
if ((this.mPrompt == null) || (this.mPrompt.equals(pwCallback.getPrompt()))) {
|
||||||
pwCallback.setPassword(this.password);
|
pwCallback.setPassword(this.mPassword);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCallbackException(callback, "Unrecognised callback.");
|
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;
|
package org.sufficientlysecure.keychain.pgp.exception;
|
||||||
|
|
||||||
public class NoAsymmetricEncryptionException extends Exception {
|
public class NoAsymmetricEncryptionException extends Exception {
|
||||||
@ -6,4 +23,4 @@ public class NoAsymmetricEncryptionException extends Exception {
|
|||||||
public NoAsymmetricEncryptionException() {
|
public NoAsymmetricEncryptionException() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
package org.sufficientlysecure.keychain.pgp.exception;
|
||||||
|
|
||||||
public class PgpGeneralException extends Exception {
|
public class PgpGeneralException extends Exception {
|
||||||
@ -6,4 +23,4 @@ public class PgpGeneralException extends Exception {
|
|||||||
public PgpGeneralException(String message) {
|
public PgpGeneralException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,9 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
package org.sufficientlysecure.keychain.provider;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
|
||||||
public class KeychainContract {
|
public class KeychainContract {
|
||||||
|
|
||||||
@ -88,7 +87,6 @@ public class KeychainContract {
|
|||||||
|
|
||||||
public static final String PATH_PUBLIC = "public";
|
public static final String PATH_PUBLIC = "public";
|
||||||
public static final String PATH_SECRET = "secret";
|
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_MASTER_KEY_ID = "master_key_id";
|
||||||
public static final String PATH_BY_KEY_ID = "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()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_KEY_RINGS).build();
|
.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";
|
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 final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key_ring";
|
||||||
|
|
||||||
public static Uri buildUnifiedKeyRingsUri() {
|
public static Uri buildUnifiedKeyRingsUri() {
|
||||||
return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build();
|
return CONTENT_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri buildPublicKeyRingsUri() {
|
public static Uri buildPublicKeyRingsUri() {
|
||||||
@ -180,10 +182,14 @@ public class KeychainContract {
|
|||||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_KEY_RINGS).build();
|
.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";
|
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 final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key";
|
||||||
|
|
||||||
public static Uri buildPublicKeysUri(String keyRingRowId) {
|
public static Uri buildPublicKeysUri(String keyRingRowId) {
|
||||||
@ -219,10 +225,14 @@ public class KeychainContract {
|
|||||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_KEY_RINGS).build();
|
.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";
|
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 final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.user_id";
|
||||||
|
|
||||||
public static Uri buildPublicUserIdsUri(String keyRingRowId) {
|
public static Uri buildPublicUserIdsUri(String keyRingRowId) {
|
||||||
@ -258,10 +268,14 @@ public class KeychainContract {
|
|||||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_API_APPS).build();
|
.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";
|
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 final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps";
|
||||||
|
|
||||||
public static Uri buildIdUri(String rowId) {
|
public static Uri buildIdUri(String rowId) {
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
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.Constants;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
|
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.provider.KeychainContract.CertsColumns;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 {
|
public class KeychainDatabase extends SQLiteOpenHelper {
|
||||||
private static final String DATABASE_NAME = "apg.db";
|
private static final String DATABASE_NAME = "apg.db";
|
||||||
private static final int DATABASE_VERSION = 8;
|
private static final int DATABASE_VERSION = 8;
|
||||||
@ -94,7 +93,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
|||||||
+ CertsColumns.KEY_ID_CERTIFIER + " INTEGER, " // certifying key
|
+ CertsColumns.KEY_ID_CERTIFIER + " INTEGER, " // certifying key
|
||||||
+ CertsColumns.CREATION + " INTEGER, "
|
+ CertsColumns.CREATION + " INTEGER, "
|
||||||
+ CertsColumns.VERIFIED + " INTEGER, "
|
+ CertsColumns.VERIFIED + " INTEGER, "
|
||||||
+ CertsColumns.KEY_DATA+ " BLOB)";
|
+ CertsColumns.KEY_DATA + " BLOB)";
|
||||||
|
|
||||||
|
|
||||||
KeychainDatabase(Context context) {
|
KeychainDatabase(Context context) {
|
||||||
|
@ -17,22 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
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.ContentProvider;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.UriMatcher;
|
import android.content.UriMatcher;
|
||||||
@ -44,6 +28,13 @@ import android.database.sqlite.SQLiteQueryBuilder;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
import android.text.TextUtils;
|
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 class KeychainProvider extends ContentProvider {
|
||||||
// public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME
|
// 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;
|
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
|
* public key rings
|
||||||
*
|
*
|
||||||
@ -237,20 +237,11 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
+ KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME);
|
+ 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
|
* certifications
|
||||||
* <pre>
|
|
||||||
*
|
*
|
||||||
* key_rings/unified
|
* <pre>
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
matcher.addURI(authority, KeychainContract.BASE_CERTS, CERTS);
|
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(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
|
||||||
projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "."
|
projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "."
|
||||||
+ KeyRingsColumns.KEY_RING_DATA);
|
+ 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
|
// TODO: deprecated master key id
|
||||||
//projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.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);
|
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;
|
return projectionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,9 +433,11 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
* Builds default query for keyRings: KeyRings table is joined with UserIds and Keys
|
* Builds default query for keyRings: KeyRings table is joined with UserIds and Keys
|
||||||
*/
|
*/
|
||||||
private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match) {
|
private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match) {
|
||||||
// public or secret keyring
|
if (match != UNIFIED_KEY_RING) {
|
||||||
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
|
// public or secret keyring
|
||||||
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
|
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = ");
|
||||||
|
qb.appendWhereEscapeString(Integer.toString(getKeyType(match)));
|
||||||
|
}
|
||||||
|
|
||||||
// join keyrings with keys and userIds
|
// join keyrings with keys and userIds
|
||||||
// Only get user id and key with rank 0 (main user id and main key)
|
// 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();
|
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||||
SQLiteDatabase db = mApgDatabase.getReadableDatabase();
|
SQLiteDatabase db = mApgDatabase.getReadableDatabase();
|
||||||
|
|
||||||
String groupBy = null;
|
|
||||||
|
|
||||||
int match = mUriMatcher.match(uri);
|
int match = mUriMatcher.match(uri);
|
||||||
|
|
||||||
// screw that switch
|
// all query() parameters, for good measure
|
||||||
if(match == UNIFIED_KEY_RING) {
|
String groupBy = null, having = null;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean all = false;
|
boolean all = false;
|
||||||
|
|
||||||
switch (match) {
|
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 PUBLIC_KEY_RING:
|
||||||
case SECRET_KEY_RING:
|
case SECRET_KEY_RING:
|
||||||
qb = buildKeyRingQuery(qb, match);
|
qb = buildKeyRingQuery(qb, match);
|
||||||
@ -740,8 +689,7 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
+ Tables.KEYS + "." + Keys.KEY_RING_ROW_ID + " = "
|
+ Tables.KEYS + "." + Keys.KEY_RING_ROW_ID + " = "
|
||||||
+ "signer." + UserIds.KEY_RING_ROW_ID
|
+ "signer." + UserIds.KEY_RING_ROW_ID
|
||||||
+ " AND "
|
+ " AND "
|
||||||
+ Tables.KEYS + "." + Keys.RANK + " = "
|
+ "signer." + Keys.RANK + " = 0"
|
||||||
+ "signer." + UserIds.RANK
|
|
||||||
+ ")");
|
+ ")");
|
||||||
|
|
||||||
// groupBy = Tables.USER_IDS + "." + UserIds.RANK;
|
// groupBy = Tables.USER_IDS + "." + UserIds.RANK;
|
||||||
@ -801,7 +749,7 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
orderBy = sortOrder;
|
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
|
// Tell the cursor what uri to watch, so it knows when its source data changes
|
||||||
c.setNotificationUri(getContext().getContentResolver(), uri);
|
c.setNotificationUri(getContext().getContentResolver(), uri);
|
||||||
|
@ -17,10 +17,9 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
package org.sufficientlysecure.keychain.provider;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
|
||||||
public class KeychainServiceBlobContract {
|
public class KeychainServiceBlobContract {
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import android.content.Context;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
|
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
|
||||||
|
|
||||||
public class KeychainServiceBlobDatabase extends SQLiteOpenHelper {
|
public class KeychainServiceBlobDatabase extends SQLiteOpenHelper {
|
||||||
|
@ -18,11 +18,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
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.ContentProvider;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
@ -31,7 +26,10 @@ import android.database.sqlite.SQLiteDatabase;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.provider.BaseColumns;
|
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.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -40,7 +38,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class KeychainServiceBlobProvider extends ContentProvider {
|
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;
|
private KeychainServiceBlobDatabase mBlobDatabase = null;
|
||||||
|
|
||||||
@ -55,7 +53,9 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(Uri uri, ContentValues ignored) {
|
public Uri insert(Uri uri, ContentValues ignored) {
|
||||||
// ContentValues are actually ignored, because we want to store a blob with no more
|
// 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);
|
return Uri.withAppendedPath(insertedUri, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException,
|
public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException,
|
||||||
FileNotFoundException {
|
FileNotFoundException {
|
||||||
@ -91,9 +93,9 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
|||||||
|
|
||||||
// get the data
|
// get the data
|
||||||
SQLiteDatabase db = mBlobDatabase.getReadableDatabase();
|
SQLiteDatabase db = mBlobDatabase.getReadableDatabase();
|
||||||
Cursor result = db.query(KeychainServiceBlobDatabase.TABLE, new String[] { BaseColumns._ID },
|
Cursor result = db.query(KeychainServiceBlobDatabase.TABLE, new String[]{BaseColumns._ID},
|
||||||
BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?",
|
BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?",
|
||||||
new String[] { id, key }, null, null, null);
|
new String[]{id, key}, null, null, null);
|
||||||
|
|
||||||
if (result.getCount() == 0) {
|
if (result.getCount() == 0) {
|
||||||
// either the key is wrong or no id exists
|
// either the key is wrong or no id exists
|
||||||
@ -124,26 +126,34 @@ public class KeychainServiceBlobProvider extends ContentProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getType(Uri uri) {
|
public String getType(Uri uri) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||||
String sortOrder) {
|
String sortOrder) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -17,24 +17,17 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.provider;
|
package org.sufficientlysecure.keychain.provider;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SignatureException;
|
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.ArmoredOutputStream;
|
||||||
import org.spongycastle.bcpg.UserAttributePacket;
|
import org.spongycastle.bcpg.UserAttributePacket;
|
||||||
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import android.content.*;
|
||||||
import org.spongycastle.openpgp.PGPKeyRing;
|
import android.database.Cursor;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import android.database.DatabaseUtils;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import android.net.Uri;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import android.os.RemoteException;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.*;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
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.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import android.content.ContentProviderOperation;
|
import java.io.ByteArrayOutputStream;
|
||||||
import android.content.ContentResolver;
|
import java.io.IOException;
|
||||||
import android.content.ContentValues;
|
import java.util.ArrayList;
|
||||||
import android.content.Context;
|
import java.util.Date;
|
||||||
import android.content.OperationApplicationException;
|
import java.util.HashMap;
|
||||||
import android.database.Cursor;
|
import java.util.Map;
|
||||||
import android.database.DatabaseUtils;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
public class ProviderHelper {
|
public class ProviderHelper {
|
||||||
|
|
||||||
@ -124,7 +115,7 @@ public class ProviderHelper {
|
|||||||
public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) {
|
public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) {
|
||||||
PGPPublicKeyRing keyRing = getPGPPublicKeyRingByKeyId(context, keyId);
|
PGPPublicKeyRing keyRing = getPGPPublicKeyRingByKeyId(context, keyId);
|
||||||
|
|
||||||
return (keyRing == null)? null : keyRing.getPublicKey(keyId);
|
return (keyRing == null) ? null : keyRing.getPublicKey(keyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,7 +166,8 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
// get current _ID of key
|
// get current _ID of key
|
||||||
long currentRowId = -1;
|
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()) {
|
if (oldQuery != null && oldQuery.moveToFirst()) {
|
||||||
currentRowId = oldQuery.getLong(0);
|
currentRowId = oldQuery.getLong(0);
|
||||||
} else {
|
} else {
|
||||||
@ -191,10 +183,12 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
// use exactly the same _ID again to replace key in-place.
|
// 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
|
// 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._ID, currentRowId);
|
||||||
|
}
|
||||||
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
||||||
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
||||||
|
|
||||||
@ -279,7 +273,8 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
// get current _ID of key
|
// get current _ID of key
|
||||||
long currentRowId = -1;
|
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()) {
|
if (oldQuery != null && oldQuery.moveToFirst()) {
|
||||||
currentRowId = oldQuery.getLong(0);
|
currentRowId = oldQuery.getLong(0);
|
||||||
} else {
|
} else {
|
||||||
@ -295,10 +290,12 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
// use exactly the same _ID again to replace key in-place.
|
// 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
|
// 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._ID, currentRowId);
|
||||||
|
}
|
||||||
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
|
||||||
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
|
||||||
|
|
||||||
@ -335,7 +332,7 @@ public class ProviderHelper {
|
|||||||
* Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing
|
* Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing
|
||||||
*/
|
*/
|
||||||
private static ContentProviderOperation buildPublicKeyOperations(Context context,
|
private static ContentProviderOperation buildPublicKeyOperations(Context context,
|
||||||
long keyRingRowId, PGPPublicKey key, int rank) throws IOException {
|
long keyRingRowId, PGPPublicKey key, int rank) throws IOException {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(Keys.KEY_ID, key.getKeyID());
|
values.put(Keys.KEY_ID, key.getKeyID());
|
||||||
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
|
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
|
||||||
@ -387,7 +384,7 @@ public class ProviderHelper {
|
|||||||
* Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing
|
* Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing
|
||||||
*/
|
*/
|
||||||
private static ContentProviderOperation buildPublicUserIdOperations(Context context,
|
private static ContentProviderOperation buildPublicUserIdOperations(Context context,
|
||||||
long keyRingRowId, String userId, int rank) {
|
long keyRingRowId, String userId, int rank) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId);
|
values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId);
|
||||||
values.put(UserIds.USER_ID, userId);
|
values.put(UserIds.USER_ID, userId);
|
||||||
@ -402,7 +399,7 @@ public class ProviderHelper {
|
|||||||
* Build ContentProviderOperation to add PGPSecretKey to database corresponding to a keyRing
|
* Build ContentProviderOperation to add PGPSecretKey to database corresponding to a keyRing
|
||||||
*/
|
*/
|
||||||
private static ContentProviderOperation buildSecretKeyOperations(Context context,
|
private static ContentProviderOperation buildSecretKeyOperations(Context context,
|
||||||
long keyRingRowId, PGPSecretKey key, int rank) throws IOException {
|
long keyRingRowId, PGPSecretKey key, int rank) throws IOException {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
boolean hasPrivate = true;
|
boolean hasPrivate = true;
|
||||||
@ -439,7 +436,7 @@ public class ProviderHelper {
|
|||||||
* Build ContentProviderOperation to add SecretUserIds to database corresponding to a keyRing
|
* Build ContentProviderOperation to add SecretUserIds to database corresponding to a keyRing
|
||||||
*/
|
*/
|
||||||
private static ContentProviderOperation buildSecretUserIdOperations(Context context,
|
private static ContentProviderOperation buildSecretUserIdOperations(Context context,
|
||||||
long keyRingRowId, String userId, int rank) {
|
long keyRingRowId, String userId, int rank) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId);
|
values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId);
|
||||||
values.put(UserIds.USER_ID, userId);
|
values.put(UserIds.USER_ID, userId);
|
||||||
@ -483,10 +480,10 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
ArrayList<Long> rowIds = new ArrayList<Long>();
|
ArrayList<Long> rowIds = new ArrayList<Long>();
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
int IdCol = cursor.getColumnIndex(KeyRings._ID);
|
int idCol = cursor.getColumnIndex(KeyRings._ID);
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
rowIds.add(cursor.getLong(IdCol));
|
rowIds.add(cursor.getLong(idCol));
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,7 +563,7 @@ public class ProviderHelper {
|
|||||||
+ " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
|
+ " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
|
||||||
+ KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
|
+ KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
|
||||||
+ " AND sign_keys." + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY
|
+ " AND sign_keys." + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY
|
||||||
+ " = 1) AS sign",};
|
+ " = 1) AS sign", };
|
||||||
|
|
||||||
ContentResolver cr = context.getContentResolver();
|
ContentResolver cr = context.getContentResolver();
|
||||||
Cursor cursor = cr.query(queryUri, projection, null, null, null);
|
Cursor cursor = cr.query(queryUri, projection, null, null, null);
|
||||||
|
@ -17,48 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service;
|
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.app.IntentService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -67,13 +25,32 @@ import android.os.Bundle;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.os.RemoteException;
|
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
|
* 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
|
* data from the activities or other apps, queues these intents, executes them, and stops itself
|
||||||
* after doing them.
|
* 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 */
|
/* extras that can be given by intent */
|
||||||
public static final String EXTRA_MESSENGER = "messenger";
|
public static final String EXTRA_MESSENGER = "messenger";
|
||||||
@ -331,8 +308,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||||
.signatureKeyId(secretKeyId)
|
.signatureKeyId(secretKeyId)
|
||||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
.signatureHashAlgorithm(
|
||||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||||
|
.signaturePassphrase(
|
||||||
|
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||||
|
|
||||||
builder.build().generateSignature();
|
builder.build().generateSignature();
|
||||||
} else if (signOnly) {
|
} else if (signOnly) {
|
||||||
@ -340,21 +319,26 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||||
.signatureKeyId(secretKeyId)
|
.signatureKeyId(secretKeyId)
|
||||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
.signatureHashAlgorithm(
|
||||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||||
|
.signaturePassphrase(
|
||||||
|
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||||
|
|
||||||
builder.build().execute();
|
builder.build().execute();
|
||||||
} else {
|
} else {
|
||||||
Log.d(Constants.TAG, "encrypt...");
|
Log.d(Constants.TAG, "encrypt...");
|
||||||
builder.enableAsciiArmorOutput(useAsciiArmor)
|
builder.enableAsciiArmorOutput(useAsciiArmor)
|
||||||
.compressionId(compressionId)
|
.compressionId(compressionId)
|
||||||
.symmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
|
.symmetricEncryptionAlgorithm(
|
||||||
|
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
|
||||||
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
.signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
|
||||||
.encryptionKeyIds(encryptionKeyIds)
|
.encryptionKeyIds(encryptionKeyIds)
|
||||||
.encryptionPassphrase(encryptionPassphrase)
|
.encryptionPassphrase(encryptionPassphrase)
|
||||||
.signatureKeyId(secretKeyId)
|
.signatureKeyId(secretKeyId)
|
||||||
.signatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
.signatureHashAlgorithm(
|
||||||
.signaturePassphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
Preferences.getPreferences(this).getDefaultHashAlgorithm())
|
||||||
|
.signaturePassphrase(
|
||||||
|
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
|
||||||
|
|
||||||
builder.build().execute();
|
builder.build().execute();
|
||||||
}
|
}
|
||||||
@ -546,7 +530,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
ArrayList<PGPSecretKey> keys = PgpConversionHelper.BytesToPGPSecretKeyList(data
|
ArrayList<PGPSecretKey> keys = PgpConversionHelper.BytesToPGPSecretKeyList(data
|
||||||
.getByteArray(SAVE_KEYRING_KEYS));
|
.getByteArray(SAVE_KEYRING_KEYS));
|
||||||
ArrayList<Integer> keysUsages = data.getIntegerArrayList(SAVE_KEYRING_KEYS_USAGES);
|
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);
|
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
|
||||||
|
|
||||||
@ -601,7 +586,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
int keysTotal = 2;
|
int keysTotal = 2;
|
||||||
int keysCreated = 0;
|
int keysCreated = 0;
|
||||||
setProgress(
|
setProgress(
|
||||||
getApplicationContext().getResources().getQuantityString(R.plurals.progress_generating, keysTotal),
|
getApplicationContext().getResources().
|
||||||
|
getQuantityString(R.plurals.progress_generating, keysTotal),
|
||||||
keysCreated,
|
keysCreated,
|
||||||
keysTotal);
|
keysTotal);
|
||||||
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
|
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
|
||||||
@ -705,17 +691,22 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
keyRingRowIds = ProviderHelper.getSecretKeyRingsRowIds(this);
|
keyRingRowIds = ProviderHelper.getSecretKeyRingsRowIds(this);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(long rowId : rowIds) {
|
for (long rowId : rowIds) {
|
||||||
keyRingRowIds.add(rowId);
|
keyRingRowIds.add(rowId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bundle resultData;
|
Bundle resultData;
|
||||||
|
|
||||||
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
|
PgpImportExport pgpImportExport = new PgpImportExport(this, this, this);
|
||||||
|
|
||||||
resultData = pgpImportExport
|
resultData = pgpImportExport
|
||||||
.exportKeyRings(keyRingRowIds, keyType, outStream);
|
.exportKeyRings(keyRingRowIds, keyType, outStream);
|
||||||
|
|
||||||
|
if (mIsCanceled) {
|
||||||
|
boolean isDeleted = new File(outputFile).delete();
|
||||||
|
}
|
||||||
|
|
||||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sendErrorToHandler(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
|
// 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
|
// PGPObject chunks after the first one, e.g. files with several consecutive ASCII
|
||||||
// armor blocks
|
// armor blocks
|
||||||
BufferedInputStream bufferedInput = new BufferedInputStream(new ByteArrayInputStream(downloadedKey));
|
BufferedInputStream bufferedInput =
|
||||||
|
new BufferedInputStream(new ByteArrayInputStream(downloadedKey));
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// read all available blocks... (asc files can contain many blocks with BEGIN END)
|
// 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) {
|
private void sendErrorToHandler(Exception e) {
|
||||||
// Service was canceled. Do not send error to handler.
|
// Service was canceled. Do not send error to handler.
|
||||||
if (this.mIsCanceled)
|
if (this.mIsCanceled) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
Log.e(Constants.TAG, "ApgService Exception: ", e);
|
Log.e(Constants.TAG, "ApgService Exception: ", e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
@ -850,9 +842,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
|
|
||||||
private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) {
|
private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) {
|
||||||
// Service was canceled. Do not send message to handler.
|
// Service was canceled. Do not send message to handler.
|
||||||
if (this.mIsCanceled)
|
if (this.mIsCanceled) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
Message msg = Message.obtain();
|
Message msg = Message.obtain();
|
||||||
msg.arg1 = arg1;
|
msg.arg1 = arg1;
|
||||||
if (arg2 != null) {
|
if (arg2 != null) {
|
||||||
@ -903,4 +895,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
public void setProgress(int progress, int max) {
|
public void setProgress(int progress, int max) {
|
||||||
setProgress(null, progress, max);
|
setProgress(null, progress, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasServiceStopped() {
|
||||||
|
return mIsCanceled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service;
|
package org.sufficientlysecure.keychain.service;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.DialogInterface.OnCancelListener;
|
import android.content.DialogInterface.OnCancelListener;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -28,6 +25,8 @@ import android.os.Message;
|
|||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||||
|
|
||||||
public class KeychainIntentServiceHandler extends Handler {
|
public class KeychainIntentServiceHandler extends Handler {
|
||||||
|
|
||||||
@ -73,7 +72,8 @@ public class KeychainIntentServiceHandler extends Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showProgressDialog(FragmentActivity activity) {
|
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();
|
final FragmentManager manager = activity.getSupportFragmentManager();
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
|
@ -17,10 +17,15 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service;
|
package org.sufficientlysecure.keychain.service;
|
||||||
|
|
||||||
import java.util.Date;
|
import android.app.AlarmManager;
|
||||||
import java.util.HashMap;
|
import android.app.PendingIntent;
|
||||||
import java.util.Iterator;
|
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 android.util.LongSparseArray;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
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.pgp.PgpKeyHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import java.util.Date;
|
||||||
import android.app.PendingIntent;
|
import java.util.Iterator;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This service runs in its own process, but is available to all other processes as the main
|
* 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
|
* passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for
|
||||||
* convenience.
|
* convenience.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class PassphraseCacheService extends Service {
|
public class PassphraseCacheService extends Service {
|
||||||
public static final String TAG = Constants.TAG + ": PassphraseCacheService";
|
public static final String TAG = Constants.TAG + ": PassphraseCacheService";
|
||||||
@ -86,7 +76,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
* This caches a new passphrase in memory by sending a new command to the service. An android
|
* This caches a new passphrase in memory by sending a new command to the service. An android
|
||||||
* service is only run once. Thus, when the service is already started, new commands just add
|
* service is only run once. Thus, when the service is already started, new commands just add
|
||||||
* new events to the alarm manager for new passphrases to let them timeout in the future.
|
* new events to the alarm manager for new passphrases to let them timeout in the future.
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param keyId
|
* @param keyId
|
||||||
* @param passphrase
|
* @param passphrase
|
||||||
@ -106,7 +96,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
/**
|
/**
|
||||||
* Gets a cached passphrase from memory by sending an intent to the service. This method is
|
* Gets a cached passphrase from memory by sending an intent to the service. This method is
|
||||||
* designed to wait until the service returns the passphrase.
|
* designed to wait until the service returns the passphrase.
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param keyId
|
* @param keyId
|
||||||
* @return passphrase or null (if no passphrase is cached for this keyId)
|
* @return passphrase or null (if no passphrase is cached for this keyId)
|
||||||
@ -161,7 +151,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal implementation to get cached passphrase.
|
* Internal implementation to get cached passphrase.
|
||||||
*
|
*
|
||||||
* @param keyId
|
* @param keyId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -205,7 +195,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if key has a passphrase.
|
* Checks if key has a passphrase.
|
||||||
*
|
*
|
||||||
* @param secretKeyId
|
* @param secretKeyId
|
||||||
* @return true if it has a passphrase
|
* @return true if it has a passphrase
|
||||||
*/
|
*/
|
||||||
@ -216,17 +206,17 @@ public class PassphraseCacheService extends Service {
|
|||||||
.getPGPSecretKeyRingByKeyId(context, secretKeyId);
|
.getPGPSecretKeyRingByKeyId(context, secretKeyId);
|
||||||
PGPSecretKey secretKey = null;
|
PGPSecretKey secretKey = null;
|
||||||
boolean foundValidKey = false;
|
boolean foundValidKey = false;
|
||||||
for (Iterator keys = secRing.getSecretKeys(); keys.hasNext();) {
|
for (Iterator keys = secRing.getSecretKeys(); keys.hasNext(); ) {
|
||||||
secretKey = (PGPSecretKey)keys.next();
|
secretKey = (PGPSecretKey) keys.next();
|
||||||
if (!secretKey.isPrivateKeyEmpty()) {
|
if (!secretKey.isPrivateKeyEmpty()) {
|
||||||
foundValidKey = true;
|
foundValidKey = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundValidKey)
|
if (!foundValidKey) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
"SC").build("".toCharArray());
|
"SC").build("".toCharArray());
|
||||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
|
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||||
@ -269,7 +259,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build pending intent that is executed by alarm manager to time out a specific passphrase
|
* Build pending intent that is executed by alarm manager to time out a specific passphrase
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param keyId
|
* @param keyId
|
||||||
* @return
|
* @return
|
||||||
@ -337,7 +327,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when one specific passphrase for keyId timed out
|
* Called when one specific passphrase for keyId timed out
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param keyId
|
* @param keyId
|
||||||
*/
|
*/
|
||||||
|
@ -22,12 +22,12 @@ import org.spongycastle.openpgp.PGPEncryptedData;
|
|||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
|
|
||||||
public class AppSettings {
|
public class AppSettings {
|
||||||
private String packageName;
|
private String mPackageName;
|
||||||
private byte[] packageSignature;
|
private byte[] mPackageSignature;
|
||||||
private long keyId = Id.key.none;
|
private long mKeyId = Id.key.none;
|
||||||
private int encryptionAlgorithm;
|
private int mEncryptionAlgorithm;
|
||||||
private int hashAlgorithm;
|
private int mHashAlgorithm;
|
||||||
private int compression;
|
private int mCompression;
|
||||||
|
|
||||||
public AppSettings() {
|
public AppSettings() {
|
||||||
|
|
||||||
@ -35,60 +35,60 @@ public class AppSettings {
|
|||||||
|
|
||||||
public AppSettings(String packageName, byte[] packageSignature) {
|
public AppSettings(String packageName, byte[] packageSignature) {
|
||||||
super();
|
super();
|
||||||
this.packageName = packageName;
|
this.mPackageName = packageName;
|
||||||
this.packageSignature = packageSignature;
|
this.mPackageSignature = packageSignature;
|
||||||
// defaults:
|
// defaults:
|
||||||
this.encryptionAlgorithm = PGPEncryptedData.AES_256;
|
this.mEncryptionAlgorithm = PGPEncryptedData.AES_256;
|
||||||
this.hashAlgorithm = HashAlgorithmTags.SHA512;
|
this.mHashAlgorithm = HashAlgorithmTags.SHA512;
|
||||||
this.compression = Id.choice.compression.zlib;
|
this.mCompression = Id.choice.compression.zlib;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return packageName;
|
return mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPackageName(String packageName) {
|
public void setPackageName(String packageName) {
|
||||||
this.packageName = packageName;
|
this.mPackageName = packageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPackageSignature() {
|
public byte[] getPackageSignature() {
|
||||||
return packageSignature;
|
return mPackageSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPackageSignature(byte[] packageSignature) {
|
public void setPackageSignature(byte[] packageSignature) {
|
||||||
this.packageSignature = packageSignature;
|
this.mPackageSignature = packageSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getKeyId() {
|
public long getKeyId() {
|
||||||
return keyId;
|
return mKeyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyId(long scretKeyId) {
|
public void setKeyId(long scretKeyId) {
|
||||||
this.keyId = scretKeyId;
|
this.mKeyId = scretKeyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEncryptionAlgorithm() {
|
public int getEncryptionAlgorithm() {
|
||||||
return encryptionAlgorithm;
|
return mEncryptionAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEncryptionAlgorithm(int encryptionAlgorithm) {
|
public void setEncryptionAlgorithm(int encryptionAlgorithm) {
|
||||||
this.encryptionAlgorithm = encryptionAlgorithm;
|
this.mEncryptionAlgorithm = encryptionAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHashAlgorithm() {
|
public int getHashAlgorithm() {
|
||||||
return hashAlgorithm;
|
return mHashAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashAlgorithm(int hashAlgorithm) {
|
public void setHashAlgorithm(int hashAlgorithm) {
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
this.mHashAlgorithm = hashAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCompression() {
|
public int getCompression() {
|
||||||
return compression;
|
return mCompression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCompression(int compression) {
|
public void setCompression(int compression) {
|
||||||
this.compression = compression;
|
this.mCompression = compression;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
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.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -30,6 +24,11 @@ import android.support.v7.app.ActionBarActivity;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
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 {
|
public class AppSettingsActivity extends ActionBarActivity {
|
||||||
private Uri mAppUri;
|
private Uri mAppUri;
|
||||||
@ -41,7 +40,8 @@ public class AppSettingsActivity extends ActionBarActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// Inflate a "Done" custom action bar
|
// 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() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -77,12 +77,12 @@ public class AppSettingsActivity extends ActionBarActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_api_settings_revoke:
|
case R.id.menu_api_settings_revoke:
|
||||||
revokeAccess();
|
revokeAccess();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_api_settings_cancel:
|
case R.id.menu_api_settings_cancel:
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
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.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
@ -40,20 +29,25 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.AlphaAnimation;
|
import android.view.animation.AlphaAnimation;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.widget.AdapterView;
|
import android.widget.*;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
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 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
|
public class AppSettingsFragment extends Fragment implements
|
||||||
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
|
SelectSecretKeyLayoutFragment.SelectSecretKeyCallback {
|
||||||
|
|
||||||
// model
|
// model
|
||||||
private AppSettings appSettings;
|
private AppSettings mAppSettings;
|
||||||
|
|
||||||
// view
|
// view
|
||||||
private LinearLayout mAdvancedSettingsContainer;
|
private LinearLayout mAdvancedSettingsContainer;
|
||||||
@ -68,16 +62,16 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
|
|
||||||
private SelectSecretKeyLayoutFragment mSelectKeyFragment;
|
private SelectSecretKeyLayoutFragment mSelectKeyFragment;
|
||||||
|
|
||||||
KeyValueSpinnerAdapter encryptionAdapter;
|
KeyValueSpinnerAdapter mEncryptionAdapter;
|
||||||
KeyValueSpinnerAdapter hashAdapter;
|
KeyValueSpinnerAdapter mHashAdapter;
|
||||||
KeyValueSpinnerAdapter compressionAdapter;
|
KeyValueSpinnerAdapter mCompressionAdapter;
|
||||||
|
|
||||||
public AppSettings getAppSettings() {
|
public AppSettings getAppSettings() {
|
||||||
return appSettings;
|
return mAppSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAppSettings(AppSettings appSettings) {
|
public void setAppSettings(AppSettings appSettings) {
|
||||||
this.appSettings = appSettings;
|
this.mAppSettings = appSettings;
|
||||||
setPackage(appSettings.getPackageName());
|
setPackage(appSettings.getPackageName());
|
||||||
mPackageName.setText(appSettings.getPackageName());
|
mPackageName.setText(appSettings.getPackageName());
|
||||||
|
|
||||||
@ -93,10 +87,10 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
mSelectKeyFragment.selectKey(appSettings.getKeyId());
|
mSelectKeyFragment.selectKey(appSettings.getKeyId());
|
||||||
mEncryptionAlgorithm.setSelection(encryptionAdapter.getPosition(appSettings
|
mEncryptionAlgorithm.setSelection(mEncryptionAdapter.getPosition(appSettings
|
||||||
.getEncryptionAlgorithm()));
|
.getEncryptionAlgorithm()));
|
||||||
mHashAlgorithm.setSelection(hashAdapter.getPosition(appSettings.getHashAlgorithm()));
|
mHashAlgorithm.setSelection(mHashAdapter.getPosition(appSettings.getHashAlgorithm()));
|
||||||
mCompression.setSelection(compressionAdapter.getPosition(appSettings.getCompression()));
|
mCompression.setSelection(mCompressionAdapter.getPosition(appSettings.getCompression()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,14 +133,14 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
|
|
||||||
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
|
AlgorithmNames algorithmNames = new AlgorithmNames(getActivity());
|
||||||
|
|
||||||
encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
mEncryptionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||||
algorithmNames.getEncryptionNames());
|
algorithmNames.getEncryptionNames());
|
||||||
mEncryptionAlgorithm.setAdapter(encryptionAdapter);
|
mEncryptionAlgorithm.setAdapter(mEncryptionAdapter);
|
||||||
mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
appSettings.setEncryptionAlgorithm((int) id);
|
mAppSettings.setEncryptionAlgorithm((int) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -154,13 +148,13 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
|
mHashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames());
|
||||||
mHashAlgorithm.setAdapter(hashAdapter);
|
mHashAlgorithm.setAdapter(mHashAdapter);
|
||||||
mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
appSettings.setHashAlgorithm((int) id);
|
mAppSettings.setHashAlgorithm((int) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,14 +162,14 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
compressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
mCompressionAdapter = new KeyValueSpinnerAdapter(getActivity(),
|
||||||
algorithmNames.getCompressionNames());
|
algorithmNames.getCompressionNames());
|
||||||
mCompression.setAdapter(compressionAdapter);
|
mCompression.setAdapter(mCompressionAdapter);
|
||||||
mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {
|
mCompression.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
appSettings.setCompression((int) id);
|
mAppSettings.setCompression((int) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -237,7 +231,7 @@ public class AppSettingsFragment extends Fragment implements
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onKeySelected(long secretKeyId) {
|
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.net.Uri;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import org.openintents.openpgp.IOpenPgpService;
|
import org.openintents.openpgp.IOpenPgpService;
|
||||||
import org.openintents.openpgp.OpenPgpError;
|
import org.openintents.openpgp.OpenPgpError;
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
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_DUBLICATE_USER_IDS, dublicateUserIds);
|
||||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
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
|
// return PendingIntent to be executed by client
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
@ -126,7 +126,8 @@ public class OpenPgpService extends RemoteService {
|
|||||||
intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
|
intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
|
||||||
// pass params through to activity that it can be returned again later to repeat pgp operation
|
// pass params through to activity that it can be returned again later to repeat pgp operation
|
||||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
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
|
// return PendingIntent to be executed by client
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
@ -208,7 +209,8 @@ public class OpenPgpService extends RemoteService {
|
|||||||
} else {
|
} else {
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra(OpenPgpApi.RESULT_ERROR,
|
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);
|
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -289,7 +291,8 @@ public class OpenPgpService extends RemoteService {
|
|||||||
|
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
|
||||||
builder.assumeSymmetric(false) // no support for symmetric encryption
|
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);
|
.passphrase(passphrase);
|
||||||
|
|
||||||
// TODO: currently does not support binary signed-only content
|
// 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!
|
// version code is required and needs to correspond to version code of service!
|
||||||
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != OpenPgpApi.API_VERSION) {
|
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != OpenPgpApi.API_VERSION) {
|
||||||
Intent result = new Intent();
|
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_ERROR, error);
|
||||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||||
return result;
|
return result;
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
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.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@ -31,17 +28,19 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||||
|
|
||||||
public class RegisteredAppsAdapter extends CursorAdapter {
|
public class RegisteredAppsAdapter extends CursorAdapter {
|
||||||
|
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
private PackageManager pm;
|
private PackageManager mPM;
|
||||||
|
|
||||||
public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
|
public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
|
||||||
super(context, c, flags);
|
super(context, c, flags);
|
||||||
|
|
||||||
mInflater = LayoutInflater.from(context);
|
mInflater = LayoutInflater.from(context);
|
||||||
pm = context.getApplicationContext().getPackageManager();
|
mPM = context.getApplicationContext().getPackageManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,10 +52,10 @@ public class RegisteredAppsAdapter extends CursorAdapter {
|
|||||||
if (packageName != null) {
|
if (packageName != null) {
|
||||||
// get application name
|
// get application name
|
||||||
try {
|
try {
|
||||||
ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
|
ApplicationInfo ai = mPM.getApplicationInfo(packageName, 0);
|
||||||
|
|
||||||
text.setText(pm.getApplicationLabel(ai));
|
text.setText(mPM.getApplicationLabel(ai));
|
||||||
icon.setImageDrawable(pm.getApplicationIcon(ai));
|
icon.setImageDrawable(mPM.getApplicationIcon(ai));
|
||||||
} catch (final NameNotFoundException e) {
|
} catch (final NameNotFoundException e) {
|
||||||
// fallback
|
// fallback
|
||||||
text.setText(packageName);
|
text.setText(packageName);
|
||||||
|
@ -17,11 +17,10 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
package org.sufficientlysecure.keychain.service.remote;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.ui.DrawerActivity;
|
import org.sufficientlysecure.keychain.ui.DrawerActivity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
public class RegisteredAppsListActivity extends DrawerActivity {
|
public class RegisteredAppsListActivity extends DrawerActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
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.ContentUris;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -33,6 +29,9 @@ import android.support.v4.content.Loader;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
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
|
public class RegisteredAppsListFragment extends ListFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@ -71,7 +70,7 @@ public class RegisteredAppsListFragment extends ListFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These are the Contacts rows that we will retrieve.
|
// These are the Contacts rows that we will retrieve.
|
||||||
static final String[] PROJECTION = new String[] { ApiApps._ID, ApiApps.PACKAGE_NAME };
|
static final String[] PROJECTION = new String[]{ApiApps._ID, ApiApps.PACKAGE_NAME};
|
||||||
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
// This is called when a new Loader needs to be created. This
|
// This is called when a new Loader needs to be created. This
|
||||||
@ -99,4 +98,4 @@ public class RegisteredAppsListFragment extends ListFragment implements
|
|||||||
mAdapter.swapCursor(null);
|
mAdapter.swapCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.service.remote;
|
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.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -38,6 +27,16 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
|||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
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.
|
* 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_PACKAGE_SIGNATURE, packageSignature);
|
||||||
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
|
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
|
// return PendingIntent to be executed by client
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
@ -98,10 +98,12 @@ public abstract class RemoteService extends Service {
|
|||||||
|
|
||||||
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
|
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
|
||||||
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
|
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);
|
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
|
// return PendingIntent to be executed by client
|
||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
@ -138,8 +140,9 @@ public abstract class RemoteService extends Service {
|
|||||||
|
|
||||||
AppSettings settings = ProviderHelper.getApiAppSettings(this, uri);
|
AppSettings settings = ProviderHelper.getApiAppSettings(this, uri);
|
||||||
|
|
||||||
if (settings != null)
|
if (settings != null) {
|
||||||
return settings;
|
return settings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -213,7 +216,7 @@ public abstract class RemoteService extends Service {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw new WrongPackageSignatureException(
|
throw new WrongPackageSignatureException(
|
||||||
"PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
|
"PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import android.os.Message;
|
|||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
@ -88,7 +87,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
|||||||
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
|
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
|
||||||
|
|
||||||
// Inflate a "Done"/"Cancel" custom action bar view
|
// 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() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -108,13 +108,14 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
|||||||
RemoteServiceActivity.this.finish();
|
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,
|
||||||
@Override
|
new View.OnClickListener() {
|
||||||
public void onClick(View v) {
|
@Override
|
||||||
// Disallow
|
public void onClick(View v) {
|
||||||
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
|
// Disallow
|
||||||
RemoteServiceActivity.this.finish();
|
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
|
||||||
}
|
RemoteServiceActivity.this.finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -161,7 +162,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inflate a "Done"/"Cancel" custom action bar view
|
// 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() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -214,7 +216,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
|
|||||||
String text = "<font color=\"red\">" + errorMessage + "</font>";
|
String text = "<font color=\"red\">" + errorMessage + "</font>";
|
||||||
|
|
||||||
// Inflate a "Done" custom action bar view
|
// 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() {
|
new View.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@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;
|
package org.sufficientlysecure.keychain.service.remote;
|
||||||
|
|
||||||
public class WrongPackageSignatureException extends Exception {
|
public class WrongPackageSignatureException extends Exception {
|
||||||
@ -7,4 +24,4 @@ public class WrongPackageSignatureException extends Exception {
|
|||||||
public WrongPackageSignatureException(String message) {
|
public WrongPackageSignatureException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,20 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
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.ui.dialog.PassphraseDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import java.util.Iterator;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs the specified public key with the specified secret master key
|
* Signs the specified public key with the specified secret master key
|
||||||
@ -87,7 +81,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements
|
|||||||
mSelectKeyserverSpinner = (Spinner) findViewById(R.id.sign_key_keyserver);
|
mSelectKeyserverSpinner = (Spinner) findViewById(R.id.sign_key_keyserver);
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
||||||
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
|
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
|
||||||
.getKeyServers());
|
.getKeyServers());
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
mSelectKeyserverSpinner.setAdapter(adapter);
|
mSelectKeyserverSpinner.setAdapter(adapter);
|
||||||
|
|
||||||
|
@ -17,37 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.annotation.SuppressLint;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -59,16 +28,34 @@ import android.os.Messenger;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.CheckBox;
|
import android.widget.*;
|
||||||
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 com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
import com.devspark.appmsg.AppMsg;
|
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")
|
@SuppressLint("NewApi")
|
||||||
public class DecryptActivity extends DrawerActivity {
|
public class DecryptActivity extends DrawerActivity {
|
||||||
@ -364,7 +351,7 @@ public class DecryptActivity extends DrawerActivity {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e(Constants.TAG,
|
Log.e(Constants.TAG,
|
||||||
"Direct binary data without actual file in filesystem is not supported. Please use the Remote Service API!");
|
"Direct binary data without actual file in filesystem is not supported. Please use the Remote Service API!");
|
||||||
Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
|
Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
// end activity
|
// end activity
|
||||||
@ -383,7 +370,7 @@ public class DecryptActivity extends DrawerActivity {
|
|||||||
if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) {
|
if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) {
|
||||||
filename = filename.substring(0, filename.length() - 4);
|
filename = filename.substring(0, filename.length() - 4);
|
||||||
}
|
}
|
||||||
mOutputFilename = Constants.path.APP_DIR + "/" + filename;
|
mOutputFilename = Constants.Path.APP_DIR + "/" + filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSource() {
|
private void updateSource() {
|
||||||
@ -532,8 +519,11 @@ public class DecryptActivity extends DrawerActivity {
|
|||||||
AppMsg.STYLE_ALERT).show();
|
AppMsg.STYLE_ALERT).show();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (inStream != null) inStream.close();
|
if (inStream != null) {
|
||||||
} catch (Exception e){ }
|
inStream.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inStream = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
|
inStream = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -30,17 +26,14 @@ import android.support.v4.app.ActionBarDrawerToggle;
|
|||||||
import android.support.v4.view.GravityCompat;
|
import android.support.v4.view.GravityCompat;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.*;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.FontAwesomeText;
|
import com.beardedhen.androidbootstrap.FontAwesomeText;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
|
||||||
|
|
||||||
public class DrawerActivity extends ActionBarActivity {
|
public class DrawerActivity extends ActionBarActivity {
|
||||||
private DrawerLayout mDrawerLayout;
|
private DrawerLayout mDrawerLayout;
|
||||||
@ -50,9 +43,9 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
private CharSequence mDrawerTitle;
|
private CharSequence mDrawerTitle;
|
||||||
private CharSequence mTitle;
|
private CharSequence mTitle;
|
||||||
|
|
||||||
private static Class[] mItemsClass = new Class[] { KeyListActivity.class,
|
private static Class[] mItemsClass = new Class[]{KeyListActivity.class,
|
||||||
EncryptActivity.class, DecryptActivity.class, ImportKeysActivity.class,
|
EncryptActivity.class, DecryptActivity.class, ImportKeysActivity.class,
|
||||||
RegisteredAppsListActivity.class };
|
RegisteredAppsListActivity.class};
|
||||||
private Class mSelectedItem;
|
private Class mSelectedItem;
|
||||||
|
|
||||||
private static final int MENU_ID_PREFERENCE = 222;
|
private static final int MENU_ID_PREFERENCE = 222;
|
||||||
@ -67,12 +60,12 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
// opens
|
// opens
|
||||||
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
|
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
|
||||||
|
|
||||||
NavItem mItemIconTexts[] = new NavItem[] {
|
NavItem mItemIconTexts[] = new NavItem[]{
|
||||||
new NavItem("fa-user", getString(R.string.nav_contacts)),
|
new NavItem("fa-user", getString(R.string.nav_contacts)),
|
||||||
new NavItem("fa-lock", getString(R.string.nav_encrypt)),
|
new NavItem("fa-lock", getString(R.string.nav_encrypt)),
|
||||||
new NavItem("fa-unlock", getString(R.string.nav_decrypt)),
|
new NavItem("fa-unlock", getString(R.string.nav_decrypt)),
|
||||||
new NavItem("fa-download", getString(R.string.nav_import)),
|
new NavItem("fa-download", getString(R.string.nav_import)),
|
||||||
new NavItem("fa-android", getString(R.string.nav_apps)) };
|
new NavItem("fa-android", getString(R.string.nav_apps))};
|
||||||
|
|
||||||
mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.drawer_list_item,
|
mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.drawer_list_item,
|
||||||
mItemIconTexts));
|
mItemIconTexts));
|
||||||
@ -86,10 +79,10 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
// ActionBarDrawerToggle ties together the the proper interactions
|
// ActionBarDrawerToggle ties together the the proper interactions
|
||||||
// between the sliding drawer and the action bar app icon
|
// between the sliding drawer and the action bar app icon
|
||||||
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
|
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
|
||||||
mDrawerLayout, /* DrawerLayout object */
|
mDrawerLayout, /* DrawerLayout object */
|
||||||
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
|
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
|
||||||
R.string.drawer_open, /* "open drawer" description for accessibility */
|
R.string.drawer_open, /* "open drawer" description for accessibility */
|
||||||
R.string.drawer_close /* "close drawer" description for accessibility */
|
R.string.drawer_close /* "close drawer" description for accessibility */
|
||||||
) {
|
) {
|
||||||
public void onDrawerClosed(View view) {
|
public void onDrawerClosed(View view) {
|
||||||
getSupportActionBar().setTitle(mTitle);
|
getSupportActionBar().setTitle(mTitle);
|
||||||
@ -97,7 +90,7 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
supportInvalidateOptionsMenu();
|
supportInvalidateOptionsMenu();
|
||||||
|
|
||||||
// call intent activity if selected
|
// call intent activity if selected
|
||||||
if(mSelectedItem != null) {
|
if (mSelectedItem != null) {
|
||||||
finish();
|
finish();
|
||||||
overridePendingTransition(0, 0);
|
overridePendingTransition(0, 0);
|
||||||
|
|
||||||
@ -149,18 +142,18 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case MENU_ID_PREFERENCE: {
|
case MENU_ID_PREFERENCE: {
|
||||||
Intent intent = new Intent(this, PreferencesActivity.class);
|
Intent intent = new Intent(this, PreferencesActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MENU_ID_HELP: {
|
case MENU_ID_HELP: {
|
||||||
Intent intent = new Intent(this, HelpActivity.class);
|
Intent intent = new Intent(this, HelpActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle action buttons
|
// Handle action buttons
|
||||||
@ -228,15 +221,15 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class NavigationDrawerAdapter extends ArrayAdapter<NavItem> {
|
private class NavigationDrawerAdapter extends ArrayAdapter<NavItem> {
|
||||||
Context context;
|
Context mContext;
|
||||||
int layoutResourceId;
|
int mLayoutResourceId;
|
||||||
NavItem data[] = null;
|
NavItem mData[] = null;
|
||||||
|
|
||||||
public NavigationDrawerAdapter(Context context, int layoutResourceId, NavItem[] data) {
|
public NavigationDrawerAdapter(Context context, int layoutResourceId, NavItem[] data) {
|
||||||
super(context, layoutResourceId, data);
|
super(context, layoutResourceId, data);
|
||||||
this.layoutResourceId = layoutResourceId;
|
this.mLayoutResourceId = layoutResourceId;
|
||||||
this.context = context;
|
this.mContext = context;
|
||||||
this.data = data;
|
this.mData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -245,21 +238,21 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
NavItemHolder holder = null;
|
NavItemHolder holder = null;
|
||||||
|
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
|
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
|
||||||
row = inflater.inflate(layoutResourceId, parent, false);
|
row = inflater.inflate(mLayoutResourceId, parent, false);
|
||||||
|
|
||||||
holder = new NavItemHolder();
|
holder = new NavItemHolder();
|
||||||
holder.img = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon);
|
holder.mImg = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon);
|
||||||
holder.txtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
|
holder.mTxtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
|
||||||
|
|
||||||
row.setTag(holder);
|
row.setTag(holder);
|
||||||
} else {
|
} else {
|
||||||
holder = (NavItemHolder) row.getTag();
|
holder = (NavItemHolder) row.getTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
NavItem item = data[position];
|
NavItem item = mData[position];
|
||||||
holder.txtTitle.setText(item.title);
|
holder.mTxtTitle.setText(item.title);
|
||||||
holder.img.setIcon(item.icon);
|
holder.mImg.setIcon(item.icon);
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
@ -267,8 +260,8 @@ public class DrawerActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class NavItemHolder {
|
static class NavItemHolder {
|
||||||
FontAwesomeText img;
|
FontAwesomeText mImg;
|
||||||
TextView txtTitle;
|
TextView mTxtTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,25 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import android.app.Activity;
|
||||||
import java.util.GregorianCalendar;
|
import android.app.ProgressDialog;
|
||||||
import java.util.Vector;
|
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.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
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.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import android.app.Activity;
|
import java.util.ArrayList;
|
||||||
import android.app.ProgressDialog;
|
import java.util.GregorianCalendar;
|
||||||
import android.content.Context;
|
import java.util.Vector;
|
||||||
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;
|
|
||||||
|
|
||||||
public class EditKeyActivity extends ActionBarActivity {
|
public class EditKeyActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@ -104,7 +98,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
Vector<String> mUserIds;
|
Vector<String> mUserIds;
|
||||||
Vector<PGPSecretKey> mKeys;
|
Vector<PGPSecretKey> mKeys;
|
||||||
Vector<Integer> mKeysUsages;
|
Vector<Integer> mKeysUsages;
|
||||||
boolean masterCanSign = true;
|
boolean mMasterCanSign = true;
|
||||||
|
|
||||||
ExportHelper mExportHelper;
|
ExportHelper mExportHelper;
|
||||||
|
|
||||||
@ -130,7 +124,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle intent action to create new key
|
* Handle intent action to create new key
|
||||||
*
|
*
|
||||||
* @param intent
|
* @param intent
|
||||||
*/
|
*/
|
||||||
private void handleActionCreateKey(Intent intent) {
|
private void handleActionCreateKey(Intent intent) {
|
||||||
@ -146,7 +140,8 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
cancelClicked();
|
cancelClicked();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Bundle extras = intent.getExtras();
|
Bundle extras = intent.getExtras();
|
||||||
|
|
||||||
@ -245,7 +240,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle intent action to edit existing key
|
* Handle intent action to edit existing key
|
||||||
*
|
*
|
||||||
* @param intent
|
* @param intent
|
||||||
*/
|
*/
|
||||||
private void handleActionEditKey(Intent intent) {
|
private void handleActionEditKey(Intent intent) {
|
||||||
@ -269,8 +264,8 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
// get master key id using row id
|
// get master key id using row id
|
||||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
||||||
|
|
||||||
masterCanSign = ProviderHelper.getMasterKeyCanSign(this, mDataUri);
|
mMasterCanSign = ProviderHelper.getMasterKeyCanSign(this, mDataUri);
|
||||||
finallyEdit(masterKeyId, masterCanSign);
|
finallyEdit(masterKeyId, mMasterCanSign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,28 +318,28 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_key_edit_cancel:
|
case R.id.menu_key_edit_cancel:
|
||||||
cancelClicked();
|
cancelClicked();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_key_edit_export_file:
|
case R.id.menu_key_edit_export_file:
|
||||||
long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
|
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;
|
return true;
|
||||||
case R.id.menu_key_edit_delete: {
|
case R.id.menu_key_edit_delete: {
|
||||||
// Message is received after key is deleted
|
// Message is received after key is deleted
|
||||||
Handler returnHandler = new Handler() {
|
Handler returnHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
|
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
|
||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
finish();
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
mExportHelper.deleteKey(mDataUri, Id.type.secret_key, returnHandler);
|
mExportHelper.deleteKey(mDataUri, Id.type.secret_key, returnHandler);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
@ -437,12 +432,12 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
|
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
|
||||||
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||||
mUserIdsView.setType(Id.type.user_id);
|
mUserIdsView.setType(Id.type.user_id);
|
||||||
mUserIdsView.setCanEdit(masterCanSign);
|
mUserIdsView.setCanEdit(mMasterCanSign);
|
||||||
mUserIdsView.setUserIds(mUserIds);
|
mUserIdsView.setUserIds(mUserIds);
|
||||||
container.addView(mUserIdsView);
|
container.addView(mUserIdsView);
|
||||||
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||||
mKeysView.setType(Id.type.key);
|
mKeysView.setType(Id.type.key);
|
||||||
mKeysView.setCanEdit(masterCanSign);
|
mKeysView.setCanEdit(mMasterCanSign);
|
||||||
mKeysView.setKeys(mKeys, mKeysUsages);
|
mKeysView.setKeys(mKeys, mKeysUsages);
|
||||||
container.addView(mKeysView);
|
container.addView(mKeysView);
|
||||||
|
|
||||||
@ -498,12 +493,13 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String passphrase = null;
|
String passphrase = null;
|
||||||
if (mIsPassPhraseSet)
|
if (mIsPassPhraseSet) {
|
||||||
passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
|
passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
|
||||||
else
|
} else {
|
||||||
passphrase = "";
|
passphrase = "";
|
||||||
|
}
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
showPassphraseDialog(masterKeyId, masterCanSign);
|
showPassphraseDialog(masterKeyId, mMasterCanSign);
|
||||||
} else {
|
} else {
|
||||||
mCurrentPassphrase = passphrase;
|
mCurrentPassphrase = passphrase;
|
||||||
finallySaveClicked();
|
finallySaveClicked();
|
||||||
@ -536,7 +532,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
data.putSerializable(KeychainIntentService.SAVE_KEYRING_KEYS_EXPIRY_DATES,
|
data.putSerializable(KeychainIntentService.SAVE_KEYRING_KEYS_EXPIRY_DATES,
|
||||||
getKeysExpiryDates(mKeysView));
|
getKeysExpiryDates(mKeysView));
|
||||||
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
|
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);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
|
|
||||||
@ -584,7 +580,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns user ids from the SectionView
|
* Returns user ids from the SectionView
|
||||||
*
|
*
|
||||||
* @param userIdsView
|
* @param userIdsView
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -604,8 +600,6 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
} catch (UserIdEditor.NoEmailException e) {
|
} catch (UserIdEditor.NoEmailException e) {
|
||||||
throw new PgpGeneralException(
|
throw new PgpGeneralException(
|
||||||
this.getString(R.string.error_user_id_needs_an_email_address));
|
this.getString(R.string.error_user_id_needs_an_email_address));
|
||||||
} catch (UserIdEditor.InvalidEmailException e) {
|
|
||||||
throw new PgpGeneralException(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId.equals("")) {
|
if (userId.equals("")) {
|
||||||
@ -633,7 +627,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns keys from the SectionView
|
* Returns keys from the SectionView
|
||||||
*
|
*
|
||||||
* @param keysView
|
* @param keysView
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -656,7 +650,7 @@ public class EditKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns usage selections of keys from the SectionView
|
* Returns usage selections of keys from the SectionView
|
||||||
*
|
*
|
||||||
* @param keysView
|
* @param keysView
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -17,9 +17,22 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import java.io.File;
|
import android.app.ProgressDialog;
|
||||||
import java.util.Vector;
|
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.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
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.Choice;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import java.io.File;
|
||||||
import android.content.Intent;
|
import java.util.Vector;
|
||||||
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;
|
|
||||||
|
|
||||||
public class EncryptActivity extends DrawerActivity {
|
public class EncryptActivity extends DrawerActivity {
|
||||||
|
|
||||||
@ -858,7 +848,7 @@ public class EncryptActivity extends DrawerActivity {
|
|||||||
new Choice(Id.choice.compression.zlib, "ZLIB ("
|
new Choice(Id.choice.compression.zlib, "ZLIB ("
|
||||||
+ getString(R.string.compression_fast) + ")"),
|
+ getString(R.string.compression_fast) + ")"),
|
||||||
new Choice(Id.choice.compression.bzip2, "BZIP2 ("
|
new Choice(Id.choice.compression.bzip2, "BZIP2 ("
|
||||||
+ getString(R.string.compression_very_slow) + ")"),};
|
+ getString(R.string.compression_very_slow) + ")"), };
|
||||||
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
|
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
|
||||||
android.R.layout.simple_spinner_item, choices);
|
android.R.layout.simple_spinner_item, choices);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
@ -31,6 +26,10 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
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 {
|
public class HelpAboutFragment extends Fragment {
|
||||||
@ -55,7 +54,7 @@ public class HelpAboutFragment extends Fragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current package version.
|
* Get the current package version.
|
||||||
*
|
*
|
||||||
* @return The current version.
|
* @return The current version.
|
||||||
*/
|
*/
|
||||||
private String getVersion() {
|
private String getVersion() {
|
||||||
@ -73,4 +72,4 @@ public class HelpAboutFragment extends Fragment {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -17,19 +17,16 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
|
||||||
|
|
||||||
public class HelpActivity extends ActionBarActivity {
|
public class HelpActivity extends ActionBarActivity {
|
||||||
public static final String EXTRA_SELECTED_TAB = "selectedTab";
|
public static final String EXTRA_SELECTED_TAB = "selected_tab";
|
||||||
|
|
||||||
ViewPager mViewPager;
|
ViewPager mViewPager;
|
||||||
TabsAdapter mTabsAdapter;
|
TabsAdapter mTabsAdapter;
|
||||||
@ -59,19 +56,24 @@ public class HelpActivity extends ActionBarActivity {
|
|||||||
Bundle startBundle = new Bundle();
|
Bundle startBundle = new Bundle();
|
||||||
startBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_start);
|
startBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_start);
|
||||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_start)),
|
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_start)),
|
||||||
HelpHtmlFragment.class, startBundle, (selectedTab == 0) );
|
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();
|
Bundle nfcBundle = new Bundle();
|
||||||
nfcBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_nfc_beam);
|
nfcBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_nfc_beam);
|
||||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_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();
|
Bundle changelogBundle = new Bundle();
|
||||||
changelogBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_changelog);
|
changelogBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_changelog);
|
||||||
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_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)),
|
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;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
@ -27,11 +25,12 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
|
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||||
|
|
||||||
public class HelpHtmlFragment extends Fragment {
|
public class HelpHtmlFragment extends Fragment {
|
||||||
private Activity mActivity;
|
private Activity mActivity;
|
||||||
|
|
||||||
private int htmlFile;
|
private int mHtmlFile;
|
||||||
|
|
||||||
public static final String ARG_HTML_FILE = "htmlFile";
|
public static final String ARG_HTML_FILE = "htmlFile";
|
||||||
|
|
||||||
@ -52,8 +51,8 @@ public class HelpHtmlFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
mActivity = getActivity();
|
mActivity = getActivity();
|
||||||
|
|
||||||
htmlFile = getArguments().getInt(ARG_HTML_FILE);
|
mHtmlFile = getArguments().getInt(ARG_HTML_FILE);
|
||||||
|
|
||||||
ScrollView scroller = new ScrollView(mActivity);
|
ScrollView scroller = new ScrollView(mActivity);
|
||||||
HtmlTextView text = new HtmlTextView(mActivity);
|
HtmlTextView text = new HtmlTextView(mActivity);
|
||||||
@ -66,11 +65,11 @@ public class HelpHtmlFragment extends Fragment {
|
|||||||
scroller.addView(text);
|
scroller.addView(text);
|
||||||
|
|
||||||
// load html from raw resource (Parsing handled by HtmlTextView library)
|
// 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
|
// no flickering when clicking textview for Android < 4
|
||||||
text.setTextColor(getResources().getColor(android.R.color.black));
|
text.setTextColor(getResources().getColor(android.R.color.black));
|
||||||
|
|
||||||
return scroller;
|
return scroller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,8 @@ import android.support.v7.app.ActionBar;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
import com.devspark.appmsg.AppMsg;
|
import com.devspark.appmsg.AppMsg;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
@ -169,7 +167,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
|
|||||||
query = "0x" + fingerprint;
|
query = "0x" + fingerprint;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +337,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
|
|||||||
// } else {
|
// } else {
|
||||||
// status.putString(
|
// status.putString(
|
||||||
// EXTRA_ERROR,
|
// EXTRA_ERROR,
|
||||||
// "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
|
// "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// } catch (QueryException e) {
|
// } catch (QueryException e) {
|
||||||
@ -400,7 +399,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
|
|||||||
AppMsg.makeText(ImportKeysActivity.this, toastMessage, AppMsg.STYLE_INFO)
|
AppMsg.makeText(ImportKeysActivity.this, toastMessage, AppMsg.STYLE_INFO)
|
||||||
.show();
|
.show();
|
||||||
if (bad > 0) {
|
if (bad > 0) {
|
||||||
BadImportKeyDialogFragment badImportKeyDialogFragment = BadImportKeyDialogFragment.newInstance(bad);
|
BadImportKeyDialogFragment badImportKeyDialogFragment =
|
||||||
|
BadImportKeyDialogFragment.newInstance(bad);
|
||||||
badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog");
|
badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,15 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||||
|
|
||||||
public class ImportKeysClipboardFragment extends Fragment {
|
public class ImportKeysClipboardFragment extends Fragment {
|
||||||
|
|
||||||
@ -60,8 +58,9 @@ public class ImportKeysClipboardFragment extends Fragment {
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
||||||
String sendText = "";
|
String sendText = "";
|
||||||
if (clipboardText != null)
|
if (clipboardText != null) {
|
||||||
sendText = clipboardText.toString();
|
sendText = clipboardText.toString();
|
||||||
|
}
|
||||||
mImportActivity.loadCallback(sendText.getBytes(), null, null, null);
|
mImportActivity.loadCallback(sendText.getBytes(), null, null, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -29,8 +24,11 @@ import android.support.v4.app.Fragment;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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 {
|
public class ImportKeysFileFragment extends Fragment {
|
||||||
private ImportKeysActivity mImportActivity;
|
private ImportKeysActivity mImportActivity;
|
||||||
@ -62,7 +60,7 @@ public class ImportKeysFileFragment extends Fragment {
|
|||||||
// open .asc or .gpg files
|
// open .asc or .gpg files
|
||||||
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
|
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
|
||||||
// or gpg types!
|
// or gpg types!
|
||||||
FileHelper.openFile(ImportKeysFileFragment.this, Constants.path.APP_DIR + "/",
|
FileHelper.openFile(ImportKeysFileFragment.this, Constants.Path.APP_DIR + "/",
|
||||||
"*/*", Id.request.filename);
|
"*/*", Id.request.filename);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -17,25 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.app.Activity;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -44,8 +25,21 @@ import android.support.v4.app.LoaderManager;
|
|||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import com.devspark.appmsg.AppMsg;
|
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
|
public class ImportKeysListFragment extends ListFragment implements
|
||||||
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||||
@ -184,7 +178,8 @@ public class ImportKeysListFragment extends ListFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) {
|
public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>>
|
||||||
|
onCreateLoader(int id, Bundle args) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case LOADER_ID_BYTES: {
|
case LOADER_ID_BYTES: {
|
||||||
InputData inputData = getInputData(mKeyBytes, mDataUri);
|
InputData inputData = getInputData(mKeyBytes, mDataUri);
|
||||||
@ -225,16 +220,16 @@ public class ImportKeysListFragment extends ListFragment implements
|
|||||||
switch (loader.getId()) {
|
switch (loader.getId()) {
|
||||||
case LOADER_ID_BYTES:
|
case LOADER_ID_BYTES:
|
||||||
|
|
||||||
if(error == null){
|
if (error == null) {
|
||||||
// No error
|
// No error
|
||||||
} else if(error instanceof ImportKeysListLoader.FileHasNoContent) {
|
} else if (error instanceof ImportKeysListLoader.FileHasNoContent) {
|
||||||
AppMsg.makeText(getActivity(), R.string.error_import_file_no_content,
|
AppMsg.makeText(getActivity(), R.string.error_import_file_no_content,
|
||||||
AppMsg.STYLE_ALERT).show();
|
AppMsg.STYLE_ALERT).show();
|
||||||
} else if(error instanceof ImportKeysListLoader.NonPgpPart) {
|
} else if (error instanceof ImportKeysListLoader.NonPgpPart) {
|
||||||
AppMsg.makeText(getActivity(),
|
AppMsg.makeText(getActivity(),
|
||||||
((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources().
|
((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources().
|
||||||
getQuantityString(R.plurals.error_import_non_pgp_part,
|
getQuantityString(R.plurals.error_import_non_pgp_part,
|
||||||
((ImportKeysListLoader.NonPgpPart) error).getCount()),
|
((ImportKeysListLoader.NonPgpPart) error).getCount()),
|
||||||
new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.confirm)).show();
|
new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.confirm)).show();
|
||||||
} else {
|
} else {
|
||||||
AppMsg.makeText(getActivity(), R.string.error_generic_report_bug,
|
AppMsg.makeText(getActivity(), R.string.error_generic_report_bug,
|
||||||
@ -244,19 +239,19 @@ public class ImportKeysListFragment extends ListFragment implements
|
|||||||
|
|
||||||
case LOADER_ID_SERVER_QUERY:
|
case LOADER_ID_SERVER_QUERY:
|
||||||
|
|
||||||
if(error == null) {
|
if (error == null) {
|
||||||
AppMsg.makeText(
|
AppMsg.makeText(
|
||||||
getActivity(), getResources().getQuantityString(R.plurals.keys_found,
|
getActivity(), getResources().getQuantityString(R.plurals.keys_found,
|
||||||
mAdapter.getCount(), mAdapter.getCount()),
|
mAdapter.getCount(), mAdapter.getCount()),
|
||||||
AppMsg.STYLE_INFO
|
AppMsg.STYLE_INFO
|
||||||
).show();
|
).show();
|
||||||
} else if(error instanceof KeyServer.InsufficientQuery) {
|
} else if (error instanceof KeyServer.InsufficientQuery) {
|
||||||
AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
|
AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
|
||||||
AppMsg.STYLE_ALERT).show();
|
AppMsg.STYLE_ALERT).show();
|
||||||
} else if(error instanceof KeyServer.QueryException) {
|
} else if (error instanceof KeyServer.QueryException) {
|
||||||
AppMsg.makeText(getActivity(), R.string.error_keyserver_query,
|
AppMsg.makeText(getActivity(), R.string.error_keyserver_query,
|
||||||
AppMsg.STYLE_ALERT).show();
|
AppMsg.STYLE_ALERT).show();
|
||||||
} else if(error instanceof KeyServer.TooManyResponses) {
|
} else if (error instanceof KeyServer.TooManyResponses) {
|
||||||
AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
|
AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
|
||||||
AppMsg.STYLE_ALERT).show();
|
AppMsg.STYLE_ALERT).show();
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
@ -26,8 +24,8 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
public class ImportKeysNFCFragment extends Fragment {
|
public class ImportKeysNFCFragment extends Fragment {
|
||||||
|
|
||||||
|
@ -17,14 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -36,9 +28,15 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
import com.google.zxing.integration.android.IntentResult;
|
import 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 {
|
public class ImportKeysQrCodeFragment extends Fragment {
|
||||||
|
|
||||||
@ -94,45 +92,45 @@ public class ImportKeysQrCodeFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
switch (requestCode & 0xFFFF) {
|
switch (requestCode & 0xFFFF) {
|
||||||
case IntentIntegratorSupportV4.REQUEST_CODE: {
|
case IntentIntegratorSupportV4.REQUEST_CODE: {
|
||||||
IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode,
|
IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode,
|
||||||
resultCode, data);
|
resultCode, data);
|
||||||
if (scanResult != null && scanResult.getFormatName() != null) {
|
if (scanResult != null && scanResult.getFormatName() != null) {
|
||||||
String scannedContent = scanResult.getContents();
|
String scannedContent = scanResult.getContents();
|
||||||
|
|
||||||
Log.d(Constants.TAG, "scannedContent: " + scannedContent);
|
Log.d(Constants.TAG, "scannedContent: " + scannedContent);
|
||||||
|
|
||||||
// look if it's fingerprint only
|
// look if it's fingerprint only
|
||||||
if (scannedContent.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
|
if (scannedContent.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
|
||||||
importFingerprint(Uri.parse(scanResult.getContents()));
|
importFingerprint(Uri.parse(scanResult.getContents()));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look if it is the whole key
|
||||||
|
String[] parts = scannedContent.split(",");
|
||||||
|
if (parts.length == 3) {
|
||||||
|
importParts(parts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is this a full key encoded as qr code?
|
||||||
|
if (scannedContent.startsWith("-----BEGIN PGP")) {
|
||||||
|
mImportActivity.loadCallback(scannedContent.getBytes(), null, null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail...
|
||||||
|
Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// look if it is the whole key
|
break;
|
||||||
String[] parts = scannedContent.split(",");
|
|
||||||
if (parts.length == 3) {
|
|
||||||
importParts(parts);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is this a full key encoded as qr code?
|
|
||||||
if (scannedContent.startsWith("-----BEGIN PGP")) {
|
|
||||||
mImportActivity.loadCallback(scannedContent.getBytes(), null, null, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail...
|
|
||||||
Toast.makeText(getActivity(), R.string.import_qr_code_wrong, Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
default:
|
||||||
}
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
default:
|
break;
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
@ -36,8 +31,11 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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 class ImportKeysServerFragment extends Fragment {
|
||||||
public static final String ARG_QUERY = "query";
|
public static final String ARG_QUERY = "query";
|
||||||
@ -96,7 +94,8 @@ public class ImportKeysServerFragment extends Fragment {
|
|||||||
search(query, keyServer);
|
search(query, keyServer);
|
||||||
|
|
||||||
// close keyboard after pressing search
|
// 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);
|
imm.hideSoftInputFromWindow(mQueryEditText.getWindowToken(), 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -110,7 +109,6 @@ public class ImportKeysServerFragment extends Fragment {
|
|||||||
search(query, keyServer);
|
search(query, keyServer);
|
||||||
|
|
||||||
// Don't return true to let the keyboard close itself after pressing search
|
// 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;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,15 +17,14 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.Id;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||||
|
|
||||||
public class KeyListActivity extends DrawerActivity {
|
public class KeyListActivity extends DrawerActivity {
|
||||||
|
|
||||||
@ -53,19 +52,45 @@ public class KeyListActivity extends DrawerActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_key_list_import:
|
case R.id.menu_key_list_import:
|
||||||
Intent intentImport = new Intent(this, ImportKeysActivity.class);
|
Intent intentImport = new Intent(this, ImportKeysActivity.class);
|
||||||
startActivityForResult(intentImport, 0);
|
startActivityForResult(intentImport, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_key_list_export:
|
case R.id.menu_key_list_export:
|
||||||
// TODO fix this for unified keylist
|
// 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;
|
return true;
|
||||||
default:
|
case R.id.menu_key_list_create:
|
||||||
return super.onOptionsItemSelected(item);
|
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:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -17,28 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -46,45 +24,47 @@ import android.content.Intent;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.*;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.Messenger;
|
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.support.v4.widget.CursorAdapter;
|
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.text.Spannable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.view.*;
|
||||||
import android.view.ActionMode;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.*;
|
||||||
import android.widget.AbsListView.MultiChoiceModeListener;
|
import android.widget.AbsListView.MultiChoiceModeListener;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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
|
* Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
|
||||||
* StickyListHeaders library which does not extend upon ListView.
|
* 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> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
private KeyListAdapter mAdapter;
|
private KeyListAdapter mAdapter;
|
||||||
@ -202,6 +182,23 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
showDeleteKeyDialog(mode, ids);
|
showDeleteKeyDialog(mode, ids);
|
||||||
break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -254,8 +251,15 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
};
|
};
|
||||||
|
|
||||||
static final int INDEX_TYPE = 1;
|
static final int INDEX_TYPE = 1;
|
||||||
static final int INDEX_UID = 3;
|
static final int INDEX_MASTER_KEY_ID = 2;
|
||||||
static final String SORT_ORDER = UserIds.USER_ID + " ASC";
|
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
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
@ -310,9 +314,10 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
} else {
|
} else {
|
||||||
viewIntent = new Intent(getActivity(), ViewKeyActivityJB.class);
|
viewIntent = new Intent(getActivity(), ViewKeyActivityJB.class);
|
||||||
}
|
}
|
||||||
viewIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsByMasterKeyIdUri(
|
viewIntent.setData(
|
||||||
Long.toString(mAdapter.getMasterKeyId(position)))
|
KeychainContract
|
||||||
);
|
.KeyRings.buildPublicKeyRingsByMasterKeyIdUri(
|
||||||
|
Long.toString(mAdapter.getMasterKeyId(position))));
|
||||||
startActivity(viewIntent);
|
startActivity(viewIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,8 +354,12 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
for (String userId : notDeleted) {
|
for (String userId : notDeleted) {
|
||||||
notDeletedMsg += userId + "\n";
|
notDeletedMsg += userId + "\n";
|
||||||
}
|
}
|
||||||
Toast.makeText(getActivity(), getString(R.string.error_can_not_delete_contacts, notDeletedMsg)
|
Toast.makeText(getActivity(),
|
||||||
+ getResources().getQuantityString(R.plurals.error_can_not_delete_info, notDeleted.size()),
|
getString(R.string.error_can_not_delete_contacts, notDeletedMsg)
|
||||||
|
+ getResources()
|
||||||
|
.getQuantityString(
|
||||||
|
R.plurals.error_can_not_delete_info,
|
||||||
|
notDeleted.size()),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
mode.finish();
|
mode.finish();
|
||||||
@ -452,45 +461,22 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
/**
|
/**
|
||||||
* Implements StickyListHeadersAdapter from library
|
* Implements StickyListHeadersAdapter from library
|
||||||
*/
|
*/
|
||||||
private class KeyListAdapter extends CursorAdapter implements StickyListHeadersAdapter {
|
private class KeyListAdapter extends HighlightQueryCursorAdapter implements StickyListHeadersAdapter {
|
||||||
private LayoutInflater mInflater;
|
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>();
|
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
|
||||||
|
|
||||||
public KeyListAdapter(Context context, Cursor c, int flags) {
|
public KeyListAdapter(Context context, Cursor c, int flags) {
|
||||||
super(context, c, flags);
|
super(context, c, flags);
|
||||||
|
|
||||||
mInflater = LayoutInflater.from(context);
|
mInflater = LayoutInflater.from(context);
|
||||||
initIndex(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor swapCursor(Cursor newCursor) {
|
public Cursor swapCursor(Cursor newCursor) {
|
||||||
initIndex(newCursor);
|
|
||||||
|
|
||||||
return super.swapCursor(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
|
* Bind cursor data to the item list view
|
||||||
* <p/>
|
* <p/>
|
||||||
@ -504,15 +490,15 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
|
||||||
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
|
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);
|
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
|
||||||
if (userIdSplit[0] != null) {
|
if (userIdSplit[0] != null) {
|
||||||
mainUserId.setText(highlightSearchQuery(userIdSplit[0]));
|
mainUserId.setText(highlightSearchQuery(userIdSplit[0]));
|
||||||
} else {
|
} else {
|
||||||
mainUserId.setText(R.string.user_id_no_name);
|
mainUserId.setText(R.string.user_id_no_name);
|
||||||
}
|
}
|
||||||
if (userIdSplit[1] != null) {
|
if (userIdSplit[1] != null) {
|
||||||
mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1]));
|
mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1]));
|
||||||
mainUserIdRest.setVisibility(View.VISIBLE);
|
mainUserIdRest.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mainUserIdRest.setVisibility(View.GONE);
|
mainUserIdRest.setVisibility(View.GONE);
|
||||||
@ -523,12 +509,12 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
Button button = (Button) view.findViewById(R.id.edit);
|
Button button = (Button) view.findViewById(R.id.edit);
|
||||||
TextView revoked = (TextView) view.findViewById(R.id.revoked);
|
TextView revoked = (TextView) view.findViewById(R.id.revoked);
|
||||||
|
|
||||||
if(cursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) {
|
if (cursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) {
|
||||||
// this is a secret key - show the edit button
|
// this is a secret key - show the edit button
|
||||||
revoked.setVisibility(View.GONE);
|
revoked.setVisibility(View.GONE);
|
||||||
button.setVisibility(View.VISIBLE);
|
button.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
final long id = cursor.getLong(mMasterKeyId);
|
final long id = cursor.getLong(INDEX_MASTER_KEY_ID);
|
||||||
button.setOnClickListener(new OnClickListener() {
|
button.setOnClickListener(new OnClickListener() {
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
|
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
|
// this is a public key - hide the edit button, show if it's revoked
|
||||||
button.setVisibility(View.GONE);
|
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);
|
revoked.setVisibility(isRevoked ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,23 +539,11 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getMasterKeyId(int id) {
|
public long getMasterKeyId(int id) {
|
||||||
|
|
||||||
if (!mCursor.moveToPosition(id)) {
|
if (!mCursor.moveToPosition(id)) {
|
||||||
throw new IllegalStateException("couldn't move cursor to position " + id);
|
throw new IllegalStateException("couldn't move cursor to position " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mCursor.getLong(mMasterKeyId);
|
return mCursor.getLong(INDEX_MASTER_KEY_ID);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -590,8 +564,8 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
holder = new HeaderViewHolder();
|
holder = new HeaderViewHolder();
|
||||||
convertView = mInflater.inflate(R.layout.key_list_header, parent, false);
|
convertView = mInflater.inflate(R.layout.key_list_header, parent, false);
|
||||||
holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
|
holder.mText = (TextView) convertView.findViewById(R.id.stickylist_header_text);
|
||||||
holder.count = (TextView) convertView.findViewById(R.id.contacts_num);
|
holder.mCount = (TextView) convertView.findViewById(R.id.contacts_num);
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
} else {
|
} else {
|
||||||
holder = (HeaderViewHolder) convertView.getTag();
|
holder = (HeaderViewHolder) convertView.getTag();
|
||||||
@ -607,26 +581,26 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
throw new IllegalStateException("couldn't move cursor to position " + position);
|
throw new IllegalStateException("couldn't move cursor to position " + position);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) {
|
if (mCursor.getInt(KeyListFragment.INDEX_TYPE) == KeyTypes.SECRET) {
|
||||||
{ // set contact count
|
{ // set contact count
|
||||||
int num = mCursor.getCount();
|
int num = mCursor.getCount();
|
||||||
String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num);
|
String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num);
|
||||||
holder.count.setText(contactsTotal);
|
holder.mCount.setText(contactsTotal);
|
||||||
holder.count.setVisibility(View.VISIBLE);
|
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;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set header text as first char in user id
|
// 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);
|
String headerText = convertView.getResources().getString(R.string.user_id_no_name);
|
||||||
if (userId != null && userId.length() > 0) {
|
if (userId != null && userId.length() > 0) {
|
||||||
headerText = "" + userId.subSequence(0, 1).charAt(0);
|
headerText = "" + userId.subSequence(0, 1).charAt(0);
|
||||||
}
|
}
|
||||||
holder.text.setText(headerText);
|
holder.mText.setText(headerText);
|
||||||
holder.count.setVisibility(View.GONE);
|
holder.mCount.setVisibility(View.GONE);
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,11 +620,11 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
}
|
}
|
||||||
|
|
||||||
// early breakout: all secret keys are assigned id 0
|
// 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;
|
return 1L;
|
||||||
|
}
|
||||||
// otherwise, return the first character of the name as ID
|
// 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) {
|
if (userId != null && userId.length() > 0) {
|
||||||
return userId.charAt(0);
|
return userId.charAt(0);
|
||||||
} else {
|
} else {
|
||||||
@ -659,8 +633,8 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HeaderViewHolder {
|
class HeaderViewHolder {
|
||||||
TextView text;
|
TextView mText;
|
||||||
TextView count;
|
TextView mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -675,8 +649,9 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
long[] ids = new long[mSelection.size()];
|
long[] ids = new long[mSelection.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// get master key ids
|
// get master key ids
|
||||||
for (int pos : mSelection.keySet())
|
for (int pos : mSelection.keySet()) {
|
||||||
ids[i++] = mAdapter.getMasterKeyId(pos);
|
ids[i++] = mAdapter.getMasterKeyId(pos);
|
||||||
|
}
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,43 +673,17 @@ public class KeyListFragment extends Fragment implements SearchView.OnQueryTextL
|
|||||||
/**
|
/**
|
||||||
* Change color for multi-selection
|
* Change color for multi-selection
|
||||||
*/
|
*/
|
||||||
// default color
|
|
||||||
v.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
if (mSelection.get(position) != null) {
|
if (mSelection.get(position) != null) {
|
||||||
// this is a selected position, change color!
|
// selected position color
|
||||||
v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
|
v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
|
||||||
|
} else {
|
||||||
|
// default color
|
||||||
|
v.setBackgroundColor(Color.TRANSPARENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
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;
|
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.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
@ -24,24 +29,13 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||||
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
public class PreferencesActivity extends PreferenceActivity {
|
public class PreferencesActivity extends PreferenceActivity {
|
||||||
|
|
||||||
public final static String ACTION_PREFS_GEN = "org.sufficientlysecure.keychain.ui.PREFS_GEN";
|
public static final 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_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
|
||||||
|
|
||||||
private PreferenceScreen mKeyServerPreference = null;
|
private PreferenceScreen mKeyServerPreference = null;
|
||||||
private static Preferences mPreferences;
|
private static Preferences mPreferences;
|
||||||
@ -62,9 +56,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
addPreferencesFromResource(R.xml.gen_preferences);
|
addPreferencesFromResource(R.xml.gen_preferences);
|
||||||
|
|
||||||
initializePassPassPhraceCacheTtl(
|
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();
|
String servers[] = mPreferences.getKeyServers();
|
||||||
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
||||||
servers.length, servers.length));
|
servers.length, servers.length));
|
||||||
@ -84,11 +78,11 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
addPreferencesFromResource(R.xml.adv_preferences);
|
addPreferencesFromResource(R.xml.adv_preferences);
|
||||||
|
|
||||||
initializeEncryptionAlgorithm(
|
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,
|
int[] valueIds = new int[]{Id.choice.compression.none, Id.choice.compression.zip,
|
||||||
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
||||||
String[] entries = new String[] {
|
String[] entries = new String[]{
|
||||||
getString(R.string.choice_none) + " (" + getString(R.string.compression_fast) + ")",
|
getString(R.string.choice_none) + " (" + getString(R.string.compression_fast) + ")",
|
||||||
"ZIP (" + getString(R.string.compression_fast) + ")",
|
"ZIP (" + getString(R.string.compression_fast) + ")",
|
||||||
"ZLIB (" + getString(R.string.compression_fast) + ")",
|
"ZLIB (" + getString(R.string.compression_fast) + ")",
|
||||||
@ -99,20 +93,22 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initializeHashAlgorithm(
|
initializeHashAlgorithm(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_HASH_ALGORITHM),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM),
|
||||||
valueIds, entries, values);
|
valueIds, entries, values);
|
||||||
|
|
||||||
initializeMessageCompression(
|
initializeMessageCompression(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_MESSAGE_COMPRESSION),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||||
valueIds, entries, values);
|
valueIds, entries, values);
|
||||||
|
|
||||||
initializeFileCompression(
|
initializeFileCompression(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_FILE_COMPRESSION),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
|
||||||
entries, values);
|
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) {
|
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||||
// Load the legacy preferences headers
|
// Load the legacy preferences headers
|
||||||
@ -149,7 +145,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
loadHeadersFromResource(R.xml.preference_headers, target);
|
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 {
|
public static class GeneralPrefsFragment extends PreferenceFragment {
|
||||||
|
|
||||||
private PreferenceScreen mKeyServerPreference = null;
|
private PreferenceScreen mKeyServerPreference = null;
|
||||||
@ -162,9 +160,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
addPreferencesFromResource(R.xml.gen_preferences);
|
addPreferencesFromResource(R.xml.gen_preferences);
|
||||||
|
|
||||||
initializePassPassPhraceCacheTtl(
|
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();
|
String servers[] = mPreferences.getKeyServers();
|
||||||
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
mKeyServerPreference.setSummary(getResources().getQuantityString(R.plurals.n_key_servers,
|
||||||
servers.length, servers.length));
|
servers.length, servers.length));
|
||||||
@ -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 {
|
public static class AdvancedPrefsFragment extends PreferenceFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -215,11 +215,11 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
addPreferencesFromResource(R.xml.adv_preferences);
|
addPreferencesFromResource(R.xml.adv_preferences);
|
||||||
|
|
||||||
initializeEncryptionAlgorithm(
|
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,
|
int[] valueIds = new int[]{Id.choice.compression.none, Id.choice.compression.zip,
|
||||||
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
Id.choice.compression.zlib, Id.choice.compression.bzip2, };
|
||||||
String[] entries = new String[] {
|
String[] entries = new String[]{
|
||||||
getString(R.string.choice_none) + " (" + getString(R.string.compression_fast) + ")",
|
getString(R.string.choice_none) + " (" + getString(R.string.compression_fast) + ")",
|
||||||
"ZIP (" + getString(R.string.compression_fast) + ")",
|
"ZIP (" + getString(R.string.compression_fast) + ")",
|
||||||
"ZLIB (" + getString(R.string.compression_fast) + ")",
|
"ZLIB (" + getString(R.string.compression_fast) + ")",
|
||||||
@ -230,24 +230,26 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initializeHashAlgorithm(
|
initializeHashAlgorithm(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_HASH_ALGORITHM),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM),
|
||||||
valueIds, entries, values);
|
valueIds, entries, values);
|
||||||
|
|
||||||
initializeMessageCompression(
|
initializeMessageCompression(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_MESSAGE_COMPRESSION),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
|
||||||
valueIds, entries, values);
|
valueIds, entries, values);
|
||||||
|
|
||||||
initializeFileCompression(
|
initializeFileCompression(
|
||||||
(IntegerListPreference) findPreference(Constants.pref.DEFAULT_FILE_COMPRESSION),
|
(IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
|
||||||
entries, values);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isValidFragment (String fragmentName) {
|
protected boolean isValidFragment(String fragmentName) {
|
||||||
return AdvancedPrefsFragment.class.getName().equals(fragmentName)
|
return AdvancedPrefsFragment.class.getName().equals(fragmentName)
|
||||||
|| GeneralPrefsFragment.class.getName().equals(fragmentName)
|
|| GeneralPrefsFragment.class.getName().equals(fragmentName)
|
||||||
|| super.isValidFragment(fragmentName);
|
|| super.isValidFragment(fragmentName);
|
||||||
@ -268,11 +270,11 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) {
|
private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) {
|
||||||
int valueIds[] = { PGPEncryptedData.AES_128, PGPEncryptedData.AES_192,
|
int valueIds[] = {PGPEncryptedData.AES_128, PGPEncryptedData.AES_192,
|
||||||
PGPEncryptedData.AES_256, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH,
|
PGPEncryptedData.AES_256, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH,
|
||||||
PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES,
|
PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES,
|
||||||
PGPEncryptedData.IDEA, };
|
PGPEncryptedData.IDEA, };
|
||||||
String entries[] = { "AES-128", "AES-192", "AES-256", "Blowfish", "Twofish", "CAST5",
|
String entries[] = {"AES-128", "AES-192", "AES-256", "Blowfish", "Twofish", "CAST5",
|
||||||
"DES", "Triple DES", "IDEA", };
|
"DES", "Triple DES", "IDEA", };
|
||||||
String values[] = new String[valueIds.length];
|
String values[] = new String[valueIds.length];
|
||||||
for (int i = 0; i < values.length; ++i) {
|
for (int i = 0; i < values.length; ++i) {
|
||||||
@ -296,10 +298,10 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
|
|
||||||
private static void initializeHashAlgorithm
|
private static void initializeHashAlgorithm
|
||||||
(final IntegerListPreference mHashAlgorithm, int[] valueIds, String[] entries, String[] values) {
|
(final IntegerListPreference mHashAlgorithm, int[] valueIds, String[] entries, String[] values) {
|
||||||
valueIds = new int[] { HashAlgorithmTags.MD5, HashAlgorithmTags.RIPEMD160,
|
valueIds = new int[]{HashAlgorithmTags.MD5, HashAlgorithmTags.RIPEMD160,
|
||||||
HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256,
|
HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256,
|
||||||
HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512, };
|
HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512, };
|
||||||
entries = new String[] { "MD5", "RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384",
|
entries = new String[]{"MD5", "RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384",
|
||||||
"SHA-512", };
|
"SHA-512", };
|
||||||
values = new String[valueIds.length];
|
values = new String[valueIds.length];
|
||||||
for (int i = 0; i < values.length; ++i) {
|
for (int i = 0; i < values.length; ++i) {
|
||||||
@ -319,8 +321,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initializeMessageCompression
|
private static void initializeMessageCompression(
|
||||||
(final IntegerListPreference mMessageCompression, int[] valueIds, String[] entries, String[] values) {
|
final IntegerListPreference mMessageCompression,
|
||||||
|
int[] valueIds, String[] entries, String[] values) {
|
||||||
mMessageCompression.setEntries(entries);
|
mMessageCompression.setEntries(entries);
|
||||||
mMessageCompression.setEntryValues(values);
|
mMessageCompression.setEntryValues(values);
|
||||||
mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression());
|
mMessageCompression.setValue("" + mPreferences.getDefaultMessageCompression());
|
||||||
@ -375,4 +378,4 @@ public class PreferencesActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -33,6 +25,13 @@ import android.view.View;
|
|||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
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,
|
public class PreferencesKeyServerActivity extends ActionBarActivity implements OnClickListener,
|
||||||
EditorListener {
|
EditorListener {
|
||||||
@ -63,7 +62,8 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
|
|||||||
// cancel
|
// cancel
|
||||||
cancelClicked();
|
cancelClicked();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
setContentView(R.layout.key_server_preference);
|
setContentView(R.layout.key_server_preference);
|
||||||
|
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.View;
|
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 {
|
public class SelectPublicKeyActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
SelectPublicKeyFragment mSelectFragment;
|
SelectPublicKeyFragment mSelectFragment;
|
||||||
|
|
||||||
long selectedMasterKeyIds[];
|
long mSelectedMasterKeyIds[];
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -59,7 +58,8 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
|||||||
// cancel
|
// cancel
|
||||||
cancelClicked();
|
cancelClicked();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
setContentView(R.layout.select_public_key_activity);
|
setContentView(R.layout.select_public_key_activity);
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create an instance of the fragment
|
// Create an instance of the fragment
|
||||||
mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
|
mSelectFragment = SelectPublicKeyFragment.newInstance(mSelectedMasterKeyIds);
|
||||||
|
|
||||||
// Add the fragment to the 'fragment_container' FrameLayout
|
// Add the fragment to the 'fragment_container' FrameLayout
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
@ -124,7 +124,7 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// preselected master keys
|
// preselected master keys
|
||||||
selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
|
mSelectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelClicked() {
|
private void cancelClicked() {
|
||||||
|
@ -17,19 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.DatabaseUtils;
|
import android.database.DatabaseUtils;
|
||||||
@ -45,12 +32,19 @@ import android.view.Gravity;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.*;
|
||||||
import android.widget.FrameLayout;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import android.widget.LinearLayout;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import android.widget.ListView;
|
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
|
||||||
import android.widget.ProgressBar;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import android.widget.TextView;
|
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,
|
public class SelectPublicKeyFragment extends ListFragmentWorkaround implements TextWatcher,
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@ -138,7 +132,8 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
mSearchView = new EditText(context);
|
mSearchView = new EditText(context);
|
||||||
mSearchView.setId(SEARCH_ID);
|
mSearchView.setId(SEARCH_ID);
|
||||||
mSearchView.setHint(R.string.menu_search);
|
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(
|
linearLayout.addView(mSearchView, new FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
@ -276,7 +271,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
|||||||
+ Keys.CAN_ENCRYPT + " = '1' AND valid_keys." + Keys.CREATION + " <= '"
|
+ Keys.CAN_ENCRYPT + " = '1' AND valid_keys." + Keys.CREATION + " <= '"
|
||||||
+ now + "' AND " + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys."
|
+ now + "' AND " + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys."
|
||||||
+ Keys.EXPIRY + " >= '" + now + "')) AS "
|
+ Keys.EXPIRY + " >= '" + now + "')) AS "
|
||||||
+ SelectKeyCursorAdapter.PROJECTION_ROW_VALID,};
|
+ SelectKeyCursorAdapter.PROJECTION_ROW_VALID, };
|
||||||
|
|
||||||
String inMasterKeyList = null;
|
String inMasterKeyList = null;
|
||||||
if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) {
|
if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) {
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
public class SelectSecretKeyActivity extends ActionBarActivity {
|
public class SelectSecretKeyActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ public class SelectSecretKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is executed by SelectSecretKeyFragment after clicking on an item
|
* This is executed by SelectSecretKeyFragment after clicking on an item
|
||||||
*
|
*
|
||||||
* @param masterKeyId
|
* @param masterKeyId
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
|
@ -17,17 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -39,6 +28,16 @@ import android.view.View;
|
|||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.ListView;
|
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
|
public class SelectSecretKeyFragment extends ListFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@ -46,9 +45,9 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
private SelectSecretKeyActivity mActivity;
|
private SelectSecretKeyActivity mActivity;
|
||||||
private SelectKeyCursorAdapter mAdapter;
|
private SelectKeyCursorAdapter mAdapter;
|
||||||
private ListView mListView;
|
private ListView mListView;
|
||||||
|
|
||||||
private boolean mFilterCertify;
|
private boolean mFilterCertify;
|
||||||
|
|
||||||
private static final String ARG_FILTER_CERTIFY = "filter_certify";
|
private static final String ARG_FILTER_CERTIFY = "filter_certify";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,7 +121,7 @@ public class SelectSecretKeyFragment extends ListFragment implements
|
|||||||
|
|
||||||
// These are the rows that we will retrieve.
|
// These are the rows that we will retrieve.
|
||||||
long now = new Date().getTime() / 1000;
|
long now = new Date().getTime() / 1000;
|
||||||
String[] projection = new String[] {
|
String[] projection = new String[]{
|
||||||
KeyRings._ID,
|
KeyRings._ID,
|
||||||
KeyRings.MASTER_KEY_ID,
|
KeyRings.MASTER_KEY_ID,
|
||||||
UserIds.USER_ID,
|
UserIds.USER_ID,
|
||||||
|
@ -17,6 +17,16 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
@ -24,21 +34,6 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
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 {
|
public class SelectSecretKeyLayoutFragment extends Fragment {
|
||||||
|
|
||||||
private TextView mKeyUserId;
|
private TextView mKeyUserId;
|
||||||
@ -106,7 +101,10 @@ public class SelectSecretKeyLayoutFragment extends Fragment {
|
|||||||
mKeyUserIdRest.setVisibility(View.GONE);
|
mKeyUserIdRest.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
mKeyUserId.setVisibility(View.GONE);
|
||||||
mKeyUserIdRest.setVisibility(View.GONE);
|
mKeyUserIdRest.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.app.ProgressDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -36,8 +29,13 @@ import android.view.View.OnClickListener;
|
|||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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
|
* Sends the selected public key to a keyserver
|
||||||
@ -59,7 +57,7 @@ public class UploadKeyActivity extends ActionBarActivity {
|
|||||||
|
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
||||||
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
|
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
|
||||||
.getKeyServers());
|
.getKeyServers());
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
mKeyServerSpinner.setAdapter(adapter);
|
mKeyServerSpinner.setAdapter(adapter);
|
||||||
if (adapter.getCount() > 0) {
|
if (adapter.getCount() > 0) {
|
||||||
|
@ -29,7 +29,6 @@ import android.support.v7.app.ActionBarActivity;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -88,7 +87,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
|||||||
// given valid /public/ query
|
// given valid /public/ query
|
||||||
long rowId = ProviderHelper.getRowId(this, getIntent().getData());
|
long rowId = ProviderHelper.getRowId(this, getIntent().getData());
|
||||||
// TODO: handle (rowId == 0) with something else than a crash
|
// TODO: handle (rowId == 0) with something else than a crash
|
||||||
mDataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)) ;
|
mDataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(rowId));
|
||||||
|
|
||||||
Bundle mainBundle = new Bundle();
|
Bundle mainBundle = new Bundle();
|
||||||
mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, mDataUri);
|
mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, mDataUri);
|
||||||
@ -124,7 +123,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
|||||||
return true;
|
return true;
|
||||||
case R.id.menu_key_view_export_file:
|
case R.id.menu_key_view_export_file:
|
||||||
long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
|
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;
|
return true;
|
||||||
case R.id.menu_key_view_share_default_fingerprint:
|
case R.id.menu_key_view_share_default_fingerprint:
|
||||||
shareKey(mDataUri, true);
|
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
|
// we delete only this key, so MESSAGE_NOT_DELETED will solely contain this key
|
||||||
Toast.makeText(ViewKeyActivity.this,
|
Toast.makeText(ViewKeyActivity.this,
|
||||||
getString(R.string.error_can_not_delete_contact)
|
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();
|
Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
|
@ -18,10 +18,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
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.annotation.TargetApi;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.nfc.NdefMessage;
|
import android.nfc.NdefMessage;
|
||||||
@ -35,6 +31,9 @@ import android.os.Bundle;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.widget.Toast;
|
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)
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
|
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
|
||||||
@ -66,7 +65,7 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
|
|||||||
// get public keyring as byte array
|
// get public keyring as byte array
|
||||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
|
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
|
||||||
mSharedKeyringBytes = ProviderHelper.getKeyRingsAsByteArray(this, dataUri,
|
mSharedKeyringBytes = ProviderHelper.getKeyRingsAsByteArray(this, dataUri,
|
||||||
new long[] { masterKeyId });
|
new long[]{masterKeyId});
|
||||||
|
|
||||||
// Register callback to set NDEF message
|
// Register callback to set NDEF message
|
||||||
mNfcAdapter.setNdefPushMessageCallback(this, this);
|
mNfcAdapter.setNdefPushMessageCallback(this, this);
|
||||||
@ -109,10 +108,10 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case NFC_SENT:
|
case NFC_SENT:
|
||||||
Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG)
|
Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
|
||||||
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
|
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
|
||||||
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
||||||
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
|
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
|
||||||
@ -313,4 +315,4 @@ public class ViewKeyCertsFragment extends Fragment
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,10 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||||
@ -52,7 +51,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
|
|
||||||
public class ViewKeyMainFragment extends Fragment implements
|
public class ViewKeyMainFragment extends Fragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor>{
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
public static final String ARG_DATA_URI = "uri";
|
public static final String ARG_DATA_URI = "uri";
|
||||||
|
|
||||||
@ -129,7 +128,7 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
|
|
||||||
{ // label whether secret key is available, and edit button if it is
|
{ // label whether secret key is available, and edit button if it is
|
||||||
final long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), mDataUri);
|
final long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), mDataUri);
|
||||||
if(ProviderHelper.hasSecretKeyByMasterKeyId(getActivity(), masterKeyId)) {
|
if (ProviderHelper.hasSecretKeyByMasterKeyId(getActivity(), masterKeyId)) {
|
||||||
// set this attribute. this is a LITTLE unclean, but we have the info available
|
// set this attribute. this is a LITTLE unclean, but we have the info available
|
||||||
// right here, so why not.
|
// right here, so why not.
|
||||||
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
|
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
|
||||||
@ -143,7 +142,10 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
mActionEdit.setOnClickListener(new View.OnClickListener() {
|
mActionEdit.setOnClickListener(new View.OnClickListener() {
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
|
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);
|
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
|
||||||
startActivityForResult(editIntent, 0);
|
startActivityForResult(editIntent, 0);
|
||||||
}
|
}
|
||||||
@ -188,21 +190,29 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
|
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};
|
KeychainContract.UserIds.USER_ID};
|
||||||
static final int KEYRING_INDEX_ID = 0;
|
static final int KEYRING_INDEX_ID = 0;
|
||||||
static final int KEYRING_INDEX_MASTER_KEY_ID = 1;
|
static final int KEYRING_INDEX_MASTER_KEY_ID = 1;
|
||||||
static final int KEYRING_INDEX_USER_ID = 2;
|
static final int KEYRING_INDEX_USER_ID = 2;
|
||||||
|
|
||||||
static final String[] USER_IDS_PROJECTION = new String[]{ KeychainContract.UserIds._ID, KeychainContract.UserIds.USER_ID,
|
static final String[] USER_IDS_PROJECTION =
|
||||||
KeychainContract.UserIds.RANK, "verified" };
|
new String[]{KeychainContract.UserIds._ID, KeychainContract.UserIds.USER_ID,
|
||||||
|
KeychainContract.UserIds.RANK, };
|
||||||
// not the main user id
|
// not the main user id
|
||||||
static final String USER_IDS_SELECTION = KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " > 0 ";
|
static final String USER_IDS_SELECTION =
|
||||||
static final String USER_IDS_SORT_ORDER = KeychainContract.UserIds.USER_ID + " COLLATE LOCALIZED ASC";
|
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,
|
static final String[] KEYS_PROJECTION =
|
||||||
KeychainContract.Keys.IS_MASTER_KEY, KeychainContract.Keys.ALGORITHM, KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY, KeychainContract.Keys.CAN_SIGN,
|
new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
|
||||||
KeychainContract.Keys.CAN_ENCRYPT, KeychainContract.Keys.CREATION, KeychainContract.Keys.EXPIRY, KeychainContract.Keys.FINGERPRINT};
|
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 String KEYS_SORT_ORDER = KeychainContract.Keys.RANK + " ASC";
|
||||||
static final int KEYS_INDEX_ID = 0;
|
static final int KEYS_INDEX_ID = 0;
|
||||||
static final int KEYS_INDEX_KEY_ID = 1;
|
static final int KEYS_INDEX_KEY_ID = 1;
|
||||||
@ -285,7 +295,8 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
} else {
|
} else {
|
||||||
Date creationDate = new Date(data.getLong(KEYS_INDEX_CREATION) * 1000);
|
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));
|
creationDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +306,8 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
} else {
|
} else {
|
||||||
Date expiryDate = new Date(data.getLong(KEYS_INDEX_EXPIRY) * 1000);
|
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));
|
expiryDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,18 +335,56 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
|
|
||||||
private SpannableStringBuilder colorizeFingerprint(String fingerprint) {
|
private SpannableStringBuilder colorizeFingerprint(String fingerprint) {
|
||||||
SpannableStringBuilder sb = new SpannableStringBuilder(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 spanEnd = Math.min(i + 4, fingerprint.length());
|
||||||
|
String fourChars = fingerprint.substring(i, spanEnd);
|
||||||
|
|
||||||
// for each 4 characters of the fingerprint + 1 space
|
int raw = Integer.parseInt(fourChars, 16);
|
||||||
for (int i = 0; i < fingerprint.length(); i += 5) {
|
byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)};
|
||||||
int minFingLength = Math.min(i + 4, fingerprint.length());
|
int[] color = OtherHelper.getRgbForData(bytes);
|
||||||
String fourChars = fingerprint.substring(i, minFingLength);
|
int r = color[0];
|
||||||
|
int g = color[1];
|
||||||
|
int b = color[2];
|
||||||
|
|
||||||
// Create a foreground color by converting the 4 fingerprint chars to an int hashcode
|
// we cannot change black by multiplication, so adjust it to an almost-black grey,
|
||||||
// and then converting that int to hex to use as a color
|
// which will then be brightened to the minimal brightness level
|
||||||
fcs = new ForegroundColorSpan(
|
if (r == 0 && g == 0 && b == 0) {
|
||||||
Color.parseColor(String.format("#%06X", (0xFFFFFF & fourChars.hashCode()))));
|
r = 1;
|
||||||
sb.setSpan(fcs, i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
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
|
||||||
|
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;
|
return sb;
|
||||||
@ -377,5 +427,4 @@ public class ViewKeyMainFragment extends Fragment implements
|
|||||||
startActivity(signIntent);
|
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.
|
* You can pass the result and an exception in it if an error occurred.
|
||||||
* Concept found at:
|
* Concept found at:
|
||||||
* https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader
|
* https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader
|
||||||
|
*
|
||||||
* @param <T> - Typ of the result which is wrapped
|
* @param <T> - Typ of the result which is wrapped
|
||||||
*/
|
*/
|
||||||
public class AsyncTaskResultWrapper <T>{
|
public class AsyncTaskResultWrapper<T> {
|
||||||
|
|
||||||
private final T result;
|
private final T mResult;
|
||||||
private final Exception error;
|
private final Exception mError;
|
||||||
|
|
||||||
public AsyncTaskResultWrapper(T result, Exception error){
|
public AsyncTaskResultWrapper(T result, Exception error) {
|
||||||
this.result = result;
|
this.mResult = result;
|
||||||
this.error = error;
|
this.mError = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T getResult() {
|
public T getResult() {
|
||||||
return result;
|
return mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Exception getError() {
|
public Exception getError() {
|
||||||
return error;
|
return mError;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import android.database.Cursor;
|
|||||||
import android.support.v4.widget.CursorAdapter;
|
import android.support.v4.widget.CursorAdapter;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.adapter;
|
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.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -36,21 +30,28 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.LinearLayout.LayoutParams;
|
import android.widget.LinearLayout.LayoutParams;
|
||||||
import android.widget.TextView;
|
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> {
|
public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||||
protected LayoutInflater mInflater;
|
protected LayoutInflater mInflater;
|
||||||
protected Activity mActivity;
|
protected Activity mActivity;
|
||||||
|
|
||||||
protected List<ImportKeysListEntry> data;
|
protected List<ImportKeysListEntry> mData;
|
||||||
static class ViewHolder{
|
|
||||||
private TextView mainUserId;
|
static class ViewHolder {
|
||||||
private TextView mainUserIdRest;
|
private TextView mMainUserId;
|
||||||
private TextView keyId;
|
private TextView mMainUserIdRest;
|
||||||
private TextView fingerprint;
|
private TextView mKeyId;
|
||||||
private TextView algorithm;
|
private TextView mFingerprint;
|
||||||
private TextView status;
|
private TextView mAlgorithm;
|
||||||
|
private TextView mStatus;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportKeysAdapter(Activity activity) {
|
public ImportKeysAdapter(Activity activity) {
|
||||||
super(activity, -1);
|
super(activity, -1);
|
||||||
mActivity = activity;
|
mActivity = activity;
|
||||||
@ -61,7 +62,7 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
|||||||
public void setData(List<ImportKeysListEntry> data) {
|
public void setData(List<ImportKeysListEntry> data) {
|
||||||
clear();
|
clear();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
this.data = data;
|
this.mData = data;
|
||||||
|
|
||||||
// add data to extended ArrayAdapter
|
// add data to extended ArrayAdapter
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
@ -75,14 +76,15 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportKeysListEntry> getData() {
|
public List<ImportKeysListEntry> getData() {
|
||||||
return data;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<ImportKeysListEntry> getSelectedData() {
|
public ArrayList<ImportKeysListEntry> getSelectedData() {
|
||||||
ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>();
|
ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>();
|
||||||
for (ImportKeysListEntry entry : data) {
|
for (ImportKeysListEntry entry : mData) {
|
||||||
if (entry.isSelected())
|
if (entry.isSelected()) {
|
||||||
selectedData.add(entry);
|
selectedData.add(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return selectedData;
|
return selectedData;
|
||||||
}
|
}
|
||||||
@ -93,21 +95,20 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
ImportKeysListEntry entry = data.get(position);
|
ImportKeysListEntry entry = mData.get(position);
|
||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
if(convertView == null) {
|
if (convertView == null) {
|
||||||
holder = new ViewHolder();
|
holder = new ViewHolder();
|
||||||
convertView = mInflater.inflate(R.layout.import_keys_list_entry, null);
|
convertView = mInflater.inflate(R.layout.import_keys_list_entry, null);
|
||||||
holder.mainUserId = (TextView) convertView.findViewById(R.id.mainUserId);
|
holder.mMainUserId = (TextView) convertView.findViewById(R.id.mainUserId);
|
||||||
holder.mainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest);
|
holder.mMainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest);
|
||||||
holder.keyId = (TextView) convertView.findViewById(R.id.keyId);
|
holder.mKeyId = (TextView) convertView.findViewById(R.id.keyId);
|
||||||
holder.fingerprint = (TextView) convertView.findViewById(R.id.fingerprint);
|
holder.mFingerprint = (TextView) convertView.findViewById(R.id.fingerprint);
|
||||||
holder.algorithm = (TextView) convertView.findViewById(R.id.algorithm);
|
holder.mAlgorithm = (TextView) convertView.findViewById(R.id.algorithm);
|
||||||
holder.status = (TextView) convertView.findViewById(R.id.status);
|
holder.mStatus = (TextView) convertView.findViewById(R.id.status);
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
}
|
} else {
|
||||||
else{
|
holder = (ViewHolder) convertView.getTag();
|
||||||
holder = (ViewHolder)convertView.getTag();
|
|
||||||
}
|
}
|
||||||
// main user id
|
// main user id
|
||||||
String userId = entry.userIds.get(0);
|
String userId = entry.userIds.get(0);
|
||||||
@ -118,39 +119,40 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
|||||||
// show red user id if it is a secret key
|
// show red user id if it is a secret key
|
||||||
if (entry.secretKey) {
|
if (entry.secretKey) {
|
||||||
userIdSplit[0] = mActivity.getString(R.string.secret_key) + " " + userIdSplit[0];
|
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 {
|
} else {
|
||||||
holder.mainUserId.setText(R.string.user_id_no_name);
|
holder.mMainUserId.setText(R.string.user_id_no_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// email
|
// email
|
||||||
if (userIdSplit[1] != null) {
|
if (userIdSplit[1] != null) {
|
||||||
holder.mainUserIdRest.setText(userIdSplit[1]);
|
holder.mMainUserIdRest.setText(userIdSplit[1]);
|
||||||
holder.mainUserIdRest.setVisibility(View.VISIBLE);
|
holder.mMainUserIdRest.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} 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) {
|
if (entry.fingerPrint != null) {
|
||||||
holder.fingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
|
holder.mFingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
|
||||||
holder.fingerprint.setVisibility(View.VISIBLE);
|
holder.mFingerprint.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} 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) {
|
if (entry.revoked) {
|
||||||
holder.status.setText(R.string.revoked);
|
holder.mStatus.setText(R.string.revoked);
|
||||||
} else {
|
} else {
|
||||||
holder.status.setVisibility(View.GONE);
|
holder.mStatus.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearLayout ll = (LinearLayout) convertView.findViewById(R.id.list);
|
LinearLayout ll = (LinearLayout) convertView.findViewById(R.id.list);
|
||||||
|
ll.removeAllViews();
|
||||||
if (entry.userIds.size() == 1) {
|
if (entry.userIds.size() == 1) {
|
||||||
ll.setVisibility(View.GONE);
|
ll.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,12 +19,6 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
|||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
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.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
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.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 {
|
public class ImportKeysListEntry implements Serializable, Parcelable {
|
||||||
private static final long serialVersionUID = -7797972103284992662L;
|
private static final long serialVersionUID = -7797972103284992662L;
|
||||||
public ArrayList<String> userIds;
|
public ArrayList<String> userIds;
|
||||||
@ -46,9 +45,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
public String algorithm;
|
public String algorithm;
|
||||||
public boolean secretKey;
|
public boolean secretKey;
|
||||||
|
|
||||||
private boolean selected;
|
private boolean mSelected;
|
||||||
|
|
||||||
private byte[] bytes = new byte[]{};
|
private byte[] mBytes = new byte[]{};
|
||||||
|
|
||||||
public ImportKeysListEntry(ImportKeysListEntry b) {
|
public ImportKeysListEntry(ImportKeysListEntry b) {
|
||||||
this.userIds = b.userIds;
|
this.userIds = b.userIds;
|
||||||
@ -60,8 +59,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
this.bitStrength = b.bitStrength;
|
this.bitStrength = b.bitStrength;
|
||||||
this.algorithm = b.algorithm;
|
this.algorithm = b.algorithm;
|
||||||
this.secretKey = b.secretKey;
|
this.secretKey = b.secretKey;
|
||||||
this.selected = b.selected;
|
this.mSelected = b.mSelected;
|
||||||
this.bytes = b.bytes;
|
this.mBytes = b.mBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
@ -79,9 +78,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
dest.writeInt(bitStrength);
|
dest.writeInt(bitStrength);
|
||||||
dest.writeString(algorithm);
|
dest.writeString(algorithm);
|
||||||
dest.writeByte((byte) (secretKey ? 1 : 0));
|
dest.writeByte((byte) (secretKey ? 1 : 0));
|
||||||
dest.writeByte((byte) (selected ? 1 : 0));
|
dest.writeByte((byte) (mSelected ? 1 : 0));
|
||||||
dest.writeInt(bytes.length);
|
dest.writeInt(mBytes.length);
|
||||||
dest.writeByteArray(bytes);
|
dest.writeByteArray(mBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() {
|
public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() {
|
||||||
@ -97,9 +96,9 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
vr.bitStrength = source.readInt();
|
vr.bitStrength = source.readInt();
|
||||||
vr.algorithm = source.readString();
|
vr.algorithm = source.readString();
|
||||||
vr.secretKey = source.readByte() == 1;
|
vr.secretKey = source.readByte() == 1;
|
||||||
vr.selected = source.readByte() == 1;
|
vr.mSelected = source.readByte() == 1;
|
||||||
vr.bytes = new byte[source.readInt()];
|
vr.mBytes = new byte[source.readInt()];
|
||||||
source.readByteArray(vr.bytes);
|
source.readByteArray(vr.mBytes);
|
||||||
|
|
||||||
return vr;
|
return vr;
|
||||||
}
|
}
|
||||||
@ -114,11 +113,11 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
return bytes;
|
return mBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBytes(byte[] bytes) {
|
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
|
// keys from keyserver are always public keys
|
||||||
secretKey = false;
|
secretKey = false;
|
||||||
// do not select by default
|
// do not select by default
|
||||||
selected = false;
|
mSelected = false;
|
||||||
userIds = new ArrayList<String>();
|
userIds = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSelected() {
|
public boolean isSelected() {
|
||||||
return selected;
|
return mSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelected(boolean selected) {
|
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) {
|
public ImportKeysListEntry(PGPKeyRing pgpKeyRing) {
|
||||||
// save actual key object into entry, used to import it later
|
// save actual key object into entry, used to import it later
|
||||||
try {
|
try {
|
||||||
this.bytes = pgpKeyRing.getEncoded();
|
this.mBytes = pgpKeyRing.getEncoded();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e);
|
Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// selected is default
|
// selected is default
|
||||||
this.selected = true;
|
this.mSelected = true;
|
||||||
|
|
||||||
if (pgpKeyRing instanceof PGPSecretKeyRing) {
|
if (pgpKeyRing instanceof PGPSecretKeyRing) {
|
||||||
secretKey = true;
|
secretKey = true;
|
||||||
@ -188,4 +187,4 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
|
|||||||
this.algorithm = "unknown";
|
this.algorithm = "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.adapter;
|
package org.sufficientlysecure.keychain.ui.adapter;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import android.content.Context;
|
||||||
import java.io.InputStream;
|
import android.support.v4.content.AsyncTaskLoader;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.spongycastle.openpgp.PGPKeyRing;
|
import org.spongycastle.openpgp.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
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.Log;
|
||||||
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
||||||
|
|
||||||
import android.content.Context;
|
import java.io.BufferedInputStream;
|
||||||
import android.support.v4.content.AsyncTaskLoader;
|
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 FileHasNoContent extends Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NonPgpPart extends Exception {
|
public static class NonPgpPart extends Exception {
|
||||||
private int count;
|
private int mCount;
|
||||||
|
|
||||||
public NonPgpPart(int count) {
|
public NonPgpPart(int count) {
|
||||||
this.count = count;
|
this.mCount = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return count;
|
return mCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +54,8 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
|||||||
|
|
||||||
InputData mInputData;
|
InputData mInputData;
|
||||||
|
|
||||||
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
|
ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>();
|
||||||
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
|
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
|
||||||
|
|
||||||
public ImportKeysListLoader(Context context, InputData inputData) {
|
public ImportKeysListLoader(Context context, InputData inputData) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -64,16 +66,16 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
|||||||
@Override
|
@Override
|
||||||
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
||||||
|
|
||||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, null);
|
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, null);
|
||||||
|
|
||||||
if (mInputData == null) {
|
if (mInputData == null) {
|
||||||
Log.e(Constants.TAG, "Input data is null!");
|
Log.e(Constants.TAG, "Input data is null!");
|
||||||
return entryListWrapper;
|
return mEntryListWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateListOfKeyrings(mInputData);
|
generateListOfKeyrings(mInputData);
|
||||||
|
|
||||||
return entryListWrapper;
|
return mEntryListWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,7 +103,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads all PGPKeyRing objects from input
|
* Reads all PGPKeyRing objects from input
|
||||||
*
|
*
|
||||||
* @param inputData
|
* @param inputData
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -141,25 +143,25 @@ public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(Constants.TAG, "Exception on parsing key file!", 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;
|
nonPgpCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isEmpty) {
|
if (isEmpty) {
|
||||||
Log.e(Constants.TAG, "File has no content!", new FileHasNoContent());
|
Log.e(Constants.TAG, "File has no content!", new FileHasNoContent());
|
||||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||||
(data, new FileHasNoContent());
|
(mData, new FileHasNoContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nonPgpCounter > 0) {
|
if (nonPgpCounter > 0) {
|
||||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
|
||||||
(data, new NonPgpPart(nonPgpCounter));
|
(mData, new NonPgpPart(nonPgpCounter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToData(PGPKeyRing keyring) {
|
private void addToData(PGPKeyRing keyring) {
|
||||||
ImportKeysListEntry item = new ImportKeysListEntry(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.content.Context;
|
||||||
import android.support.v4.content.AsyncTaskLoader;
|
import android.support.v4.content.AsyncTaskLoader;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
import org.sufficientlysecure.keychain.util.HkpKeyServer;
|
||||||
import org.sufficientlysecure.keychain.util.KeyServer;
|
import org.sufficientlysecure.keychain.util.KeyServer;
|
||||||
@ -27,14 +26,15 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
public class ImportKeysListServerLoader
|
||||||
|
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
String mServerQuery;
|
String mServerQuery;
|
||||||
String mKeyServer;
|
String mKeyServer;
|
||||||
|
|
||||||
private ArrayList<ImportKeysListEntry> entryList = new ArrayList<ImportKeysListEntry>();
|
private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<ImportKeysListEntry>();
|
||||||
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
|
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
|
||||||
|
|
||||||
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
|
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -46,16 +46,16 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultW
|
|||||||
@Override
|
@Override
|
||||||
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
|
||||||
|
|
||||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
|
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
|
||||||
|
|
||||||
if (mServerQuery == null) {
|
if (mServerQuery == null) {
|
||||||
Log.e(Constants.TAG, "mServerQuery is null!");
|
Log.e(Constants.TAG, "mServerQuery is null!");
|
||||||
return entryListWrapper;
|
return mEntryListWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
queryServer(mServerQuery, mKeyServer);
|
queryServer(mServerQuery, mKeyServer);
|
||||||
|
|
||||||
return entryListWrapper;
|
return mEntryListWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,18 +89,19 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultW
|
|||||||
try {
|
try {
|
||||||
ArrayList<ImportKeysListEntry> searchResult = server.search(query);
|
ArrayList<ImportKeysListEntry> searchResult = server.search(query);
|
||||||
|
|
||||||
|
mEntryList.clear();
|
||||||
// add result to data
|
// add result to data
|
||||||
entryList.addAll(searchResult);
|
mEntryList.addAll(searchResult);
|
||||||
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
|
mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
|
||||||
} catch (KeyServer.InsufficientQuery e) {
|
} catch (KeyServer.InsufficientQuery e) {
|
||||||
Log.e(Constants.TAG, "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) {
|
} catch (KeyServer.QueryException e) {
|
||||||
Log.e(Constants.TAG, "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) {
|
} catch (KeyServer.TooManyResponses e) {
|
||||||
Log.e(Constants.TAG, "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;
|
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.content.Context;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
|
public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
|
||||||
private final HashMap<Integer, String> mData;
|
private final HashMap<Integer, String> mData;
|
||||||
private final int[] mKeys;
|
private final int[] mKeys;
|
||||||
@ -98,4 +94,4 @@ public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.adapter;
|
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.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -31,7 +25,11 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
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 {
|
public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
||||||
@ -46,11 +44,11 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
|||||||
private int mIndexProjectionValid;
|
private int mIndexProjectionValid;
|
||||||
private int mIndexProjectionAvailable;
|
private int mIndexProjectionAvailable;
|
||||||
|
|
||||||
public final static String PROJECTION_ROW_AVAILABLE = "available";
|
public static final String PROJECTION_ROW_AVAILABLE = "available";
|
||||||
public final static String PROJECTION_ROW_VALID = "valid";
|
public static final String PROJECTION_ROW_VALID = "valid";
|
||||||
|
|
||||||
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
|
public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
|
||||||
int keyType) {
|
int keyType) {
|
||||||
super(context, c, flags);
|
super(context, c, flags);
|
||||||
|
|
||||||
mInflater = LayoutInflater.from(context);
|
mInflater = LayoutInflater.from(context);
|
||||||
@ -69,7 +67,7 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter {
|
|||||||
/**
|
/**
|
||||||
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
||||||
* performance comparison see http://stackoverflow.com/a/17999582
|
* performance comparison see http://stackoverflow.com/a/17999582
|
||||||
*
|
*
|
||||||
* @param cursor
|
* @param cursor
|
||||||
*/
|
*/
|
||||||
private void initIndex(Cursor cursor) {
|
private void initIndex(Cursor cursor) {
|
||||||
|
@ -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;
|
package org.sufficientlysecure.keychain.ui.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -19,12 +36,12 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
|
|||||||
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
|
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
|
||||||
|
|
||||||
static final class TabInfo {
|
static final class TabInfo {
|
||||||
private final Class<?> clss;
|
private final Class<?> mClss;
|
||||||
private final Bundle args;
|
private final Bundle mArgs;
|
||||||
|
|
||||||
TabInfo(Class<?> _class, Bundle _args) {
|
TabInfo(Class<?> mClss, Bundle mArgs) {
|
||||||
clss = _class;
|
this.mClss = mClss;
|
||||||
args = _args;
|
this.mArgs = mArgs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +71,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
|
|||||||
@Override
|
@Override
|
||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
TabInfo info = mTabs.get(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) {
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||||
@ -81,4 +98,4 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
|
|||||||
|
|
||||||
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.adapter;
|
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.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.v4.widget.CursorAdapter;
|
import android.support.v4.widget.CursorAdapter;
|
||||||
@ -29,6 +25,9 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
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 {
|
public class ViewKeyKeysAdapter extends CursorAdapter {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
@ -59,7 +58,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter {
|
|||||||
/**
|
/**
|
||||||
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
||||||
* performance comparison see http://stackoverflow.com/a/17999582
|
* performance comparison see http://stackoverflow.com/a/17999582
|
||||||
*
|
*
|
||||||
* @param cursor
|
* @param cursor
|
||||||
*/
|
*/
|
||||||
private void initIndex(Cursor cursor) {
|
private void initIndex(Cursor cursor) {
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.adapter;
|
package org.sufficientlysecure.keychain.ui.adapter;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.v4.widget.CursorAdapter;
|
import android.support.v4.widget.CursorAdapter;
|
||||||
@ -27,6 +24,8 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||||
|
|
||||||
public class ViewKeyUserIdsAdapter extends CursorAdapter {
|
public class ViewKeyUserIdsAdapter extends CursorAdapter {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
@ -52,7 +51,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
|
|||||||
/**
|
/**
|
||||||
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
|
||||||
* performance comparison see http://stackoverflow.com/a/17999582
|
* performance comparison see http://stackoverflow.com/a/17999582
|
||||||
*
|
*
|
||||||
* @param cursor
|
* @param cursor
|
||||||
*/
|
*/
|
||||||
private void initIndex(Cursor cursor) {
|
private void initIndex(Cursor cursor) {
|
||||||
|
@ -23,7 +23,6 @@ import android.content.DialogInterface;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
public class BadImportKeyDialogFragment extends DialogFragment {
|
public class BadImportKeyDialogFragment extends DialogFragment {
|
||||||
|
@ -27,13 +27,11 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.util.Choice;
|
import org.sufficientlysecure.keychain.util.Choice;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
public class CreateKeyDialogFragment extends DialogFragment {
|
public class CreateKeyDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@ -150,4 +148,4 @@ public class CreateKeyDialogFragment extends DialogFragment {
|
|||||||
return dialog.create();
|
return dialog.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
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.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
@ -32,6 +28,9 @@ import android.os.Messenger;
|
|||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.widget.Toast;
|
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 {
|
public class DeleteFileDialogFragment extends DialogFragment {
|
||||||
private static final String ARG_DELETE_FILE = "delete_file";
|
private static final String ARG_DELETE_FILE = "delete_file";
|
||||||
@ -89,7 +88,8 @@ public class DeleteFileDialogFragment extends DialogFragment {
|
|||||||
null);
|
null);
|
||||||
|
|
||||||
// Message is received after deleting is done in ApgService
|
// 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) {
|
public void handleMessage(Message message) {
|
||||||
// handle messages by standard ApgHandler first
|
// handle messages by standard ApgHandler first
|
||||||
super.handleMessage(message);
|
super.handleMessage(message);
|
||||||
@ -121,4 +121,4 @@ public class DeleteFileDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import android.os.Messenger;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -118,8 +117,9 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
|||||||
String selectionIDs = "";
|
String selectionIDs = "";
|
||||||
for (int i = 0; i < keyRingRowIds.length; i++) {
|
for (int i = 0; i < keyRingRowIds.length; i++) {
|
||||||
selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'";
|
selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'";
|
||||||
if (i+1 < keyRingRowIds.length)
|
if (i + 1 < keyRingRowIds.length) {
|
||||||
selectionIDs += ",";
|
selectionIDs += ",";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
selection += selectionIDs + ")";
|
selection += selectionIDs + ")";
|
||||||
|
|
||||||
@ -140,7 +140,9 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
// check if a corresponding secret key exists...
|
// check if a corresponding secret key exists...
|
||||||
Cursor secretCursor = activity.getContentResolver().query(
|
Cursor secretCursor = activity.getContentResolver().query(
|
||||||
KeychainContract.KeyRings.buildSecretKeyRingsByMasterKeyIdUri(String.valueOf(masterKeyId)),
|
KeychainContract.KeyRings
|
||||||
|
.buildSecretKeyRingsByMasterKeyIdUri(
|
||||||
|
String.valueOf(masterKeyId)),
|
||||||
null, null, null, null
|
null, null, null, null
|
||||||
);
|
);
|
||||||
if (secretCursor != null && secretCursor.getCount() > 0) {
|
if (secretCursor != null && secretCursor.getCount() > 0) {
|
||||||
@ -205,4 +207,4 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
|||||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
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.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -38,8 +33,11 @@ import android.view.View;
|
|||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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 {
|
public class FileDialogFragment extends DialogFragment {
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
@ -66,7 +64,7 @@ public class FileDialogFragment extends DialogFragment {
|
|||||||
* Creates new instance of this file dialog fragment
|
* Creates new instance of this file dialog fragment
|
||||||
*/
|
*/
|
||||||
public static FileDialogFragment newInstance(Messenger messenger, String title, String message,
|
public static FileDialogFragment newInstance(Messenger messenger, String title, String message,
|
||||||
String defaultFile, String checkboxText) {
|
String defaultFile, String checkboxText) {
|
||||||
FileDialogFragment frag = new FileDialogFragment();
|
FileDialogFragment frag = new FileDialogFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putParcelable(ARG_MESSENGER, messenger);
|
args.putParcelable(ARG_MESSENGER, messenger);
|
||||||
@ -176,34 +174,33 @@ public class FileDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
switch (requestCode & 0xFFFF) {
|
switch (requestCode & 0xFFFF) {
|
||||||
case REQUEST_CODE: {
|
case REQUEST_CODE: {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
try {
|
try {
|
||||||
String path = data.getData().getPath();
|
String path = data.getData().getPath();
|
||||||
Log.d(Constants.TAG, "path=" + path);
|
Log.d(Constants.TAG, "path=" + path);
|
||||||
|
|
||||||
// set filename used in export/import dialogs
|
// set filename used in export/import dialogs
|
||||||
setFilename(path);
|
setFilename(path);
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
|
Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
default:
|
||||||
}
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
default:
|
break;
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message back to handler which is initialized in a activity
|
* Send message back to handler which is initialized in a activity
|
||||||
*
|
*
|
||||||
* @param what
|
* @param what Message integer you want to send
|
||||||
* Message integer you want to send
|
|
||||||
*/
|
*/
|
||||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||||
Message msg = Message.obtain();
|
Message msg = Message.obtain();
|
||||||
|
@ -17,20 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
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.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -52,6 +38,19 @@ import android.widget.EditText;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
import android.widget.Toast;
|
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 {
|
public class PassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
@ -62,20 +61,18 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
|
|
||||||
private Messenger mMessenger;
|
private Messenger mMessenger;
|
||||||
private EditText mPassphraseEditText;
|
private EditText mPassphraseEditText;
|
||||||
private boolean canKB;
|
private boolean mCanKB;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this dialog fragment
|
* Creates new instance of this dialog fragment
|
||||||
*
|
*
|
||||||
* @param secretKeyId
|
* @param secretKeyId secret key id you want to use
|
||||||
* secret key id you want to use
|
* @param messenger to communicate back after caching the passphrase
|
||||||
* @param messenger
|
|
||||||
* to communicate back after caching the passphrase
|
|
||||||
* @return
|
* @return
|
||||||
* @throws PgpGeneralException
|
* @throws PgpGeneralException
|
||||||
*/
|
*/
|
||||||
public static PassphraseDialogFragment newInstance(Context context, Messenger messenger,
|
public static PassphraseDialogFragment newInstance(Context context, Messenger messenger,
|
||||||
long secretKeyId) throws PgpGeneralException {
|
long secretKeyId) throws PgpGeneralException {
|
||||||
// check if secret key has a passphrase
|
// check if secret key has a passphrase
|
||||||
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
|
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
|
||||||
if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
|
if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
|
||||||
@ -131,7 +128,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
alert.setCancelable(false);
|
alert.setCancelable(false);
|
||||||
canKB = false;
|
mCanKB = false;
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
String userId = PgpKeyHelper.getMainUserIdSafe(activity, secretKey);
|
String userId = PgpKeyHelper.getMainUserIdSafe(activity, secretKey);
|
||||||
@ -171,7 +168,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
Toast.makeText(activity,
|
Toast.makeText(activity,
|
||||||
R.string.error_could_not_extract_private_key,
|
R.string.error_could_not_extract_private_key,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_CANCEL);
|
sendMessageToHandler(MESSAGE_CANCEL);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -187,14 +184,14 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
Toast.makeText(activity, R.string.wrong_passphrase,
|
Toast.makeText(activity, R.string.wrong_passphrase,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_CANCEL);
|
sendMessageToHandler(MESSAGE_CANCEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, R.string.error_could_not_extract_private_key,
|
Toast.makeText(activity, R.string.error_could_not_extract_private_key,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_CANCEL);
|
sendMessageToHandler(MESSAGE_CANCEL);
|
||||||
return; // ran out of keys to try
|
return; // ran out of keys to try
|
||||||
}
|
}
|
||||||
@ -207,7 +204,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
// cache the new passphrase
|
// cache the new passphrase
|
||||||
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
||||||
PassphraseCacheService.addCachedPassphrase(activity, keyId, passphrase);
|
PassphraseCacheService.addCachedPassphrase(activity, keyId, passphrase);
|
||||||
if ( !keyOK && clickSecretKey.getKeyID() != keyId) {
|
if (!keyOK && clickSecretKey.getKeyID() != keyId) {
|
||||||
PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(),
|
PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(),
|
||||||
passphrase);
|
passphrase);
|
||||||
}
|
}
|
||||||
@ -224,14 +221,14 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
canKB = true;
|
mCanKB = true;
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle arg0) {
|
public void onActivityCreated(Bundle arg0) {
|
||||||
super.onActivityCreated(arg0);
|
super.onActivityCreated(arg0);
|
||||||
if (canKB) {
|
if (mCanKB) {
|
||||||
// request focus and open soft keyboard
|
// request focus and open soft keyboard
|
||||||
mPassphraseEditText.requestFocus();
|
mPassphraseEditText.requestFocus();
|
||||||
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
@ -265,9 +262,8 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message back to handler which is initialized in a activity
|
* Send message back to handler which is initialized in a activity
|
||||||
*
|
*
|
||||||
* @param what
|
* @param what Message integer you want to send
|
||||||
* Message integer you want to send
|
|
||||||
*/
|
*/
|
||||||
private void sendMessageToHandler(Integer what) {
|
private void sendMessageToHandler(Integer what) {
|
||||||
Message msg = Message.obtain();
|
Message msg = Message.obtain();
|
||||||
|
@ -26,7 +26,6 @@ import android.content.DialogInterface.OnKeyListener;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
public class ProgressDialogFragment extends DialogFragment {
|
public class ProgressDialogFragment extends DialogFragment {
|
||||||
@ -101,8 +100,9 @@ public class ProgressDialogFragment extends DialogFragment {
|
|||||||
public void onCancel(DialogInterface dialog) {
|
public void onCancel(DialogInterface dialog) {
|
||||||
super.onCancel(dialog);
|
super.onCancel(dialog);
|
||||||
|
|
||||||
if (this.mOnCancelListener != null)
|
if (this.mOnCancelListener != null) {
|
||||||
this.mOnCancelListener.onCancel(dialog);
|
this.mOnCancelListener.onCancel(dialog);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,4 +151,4 @@ public class ProgressDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
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.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -40,6 +36,9 @@ import android.widget.EditText;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
import android.widget.Toast;
|
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 {
|
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
@ -55,11 +54,9 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this dialog fragment
|
* Creates new instance of this dialog fragment
|
||||||
*
|
*
|
||||||
* @param title
|
* @param title title of dialog
|
||||||
* title of dialog
|
* @param messenger to communicate back after setting the passphrase
|
||||||
* @param messenger
|
|
||||||
* to communicate back after setting the passphrase
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
|
public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
|
||||||
@ -96,7 +93,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
||||||
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
@ -130,7 +127,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
});
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
@ -168,9 +165,8 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message back to handler which is initialized in a activity
|
* Send message back to handler which is initialized in a activity
|
||||||
*
|
*
|
||||||
* @param what
|
* @param what Message integer you want to send
|
||||||
* Message integer you want to send
|
|
||||||
*/
|
*/
|
||||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||||
Message msg = Message.obtain();
|
Message msg = Message.obtain();
|
||||||
@ -187,4 +183,4 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.dialog;
|
package org.sufficientlysecure.keychain.ui.dialog;
|
||||||
|
|
||||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -31,6 +28,8 @@ import android.os.Bundle;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
public class ShareNfcDialogFragment extends DialogFragment {
|
public class ShareNfcDialogFragment extends DialogFragment {
|
||||||
@ -97,4 +96,4 @@ public class ShareNfcDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import android.view.View;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
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
|
* Automatically calculate height of ListView based on contained items. This enables to put this
|
||||||
* ListView into a ScrollView without messing up.
|
* ListView into a ScrollView without messing up.
|
||||||
*
|
* <p/>
|
||||||
* from
|
* from
|
||||||
* http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview-
|
* http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview-
|
||||||
* or-has-the-scrollview-dis
|
* or-has-the-scrollview-dis
|
||||||
@ -52,4 +52,4 @@ public class FixedListView extends ListView {
|
|||||||
super.onMeasure(widthMeasureSpec, expandSpec);
|
super.onMeasure(widthMeasureSpec, expandSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import android.util.AttributeSet;
|
|||||||
* values should use {@link android.content.SharedPreferences#getInt}. When using XML-declared
|
* values should use {@link android.content.SharedPreferences#getInt}. When using XML-declared
|
||||||
* arrays for entry values, the arrays should be regular string arrays containing valid integer
|
* arrays for entry values, the arrays should be regular string arrays containing valid integer
|
||||||
* values.
|
* values.
|
||||||
*
|
*
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class IntegerListPreference extends ListPreference {
|
public class IntegerListPreference extends ListPreference {
|
||||||
|
@ -16,20 +16,7 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.widget;
|
package org.sufficientlysecure.keychain.ui.widget;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import android.annotation.TargetApi;
|
||||||
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.app.DatePickerDialog;
|
import android.app.DatePickerDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -39,13 +26,17 @@ import android.util.AttributeSet;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.*;
|
||||||
import android.widget.DatePicker;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
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 {
|
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
||||||
private PGPSecretKey mKey;
|
private PGPSecretKey mKey;
|
||||||
@ -63,7 +54,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
|||||||
GregorianCalendar mExpiryDate;
|
GregorianCalendar mExpiryDate;
|
||||||
|
|
||||||
private int mDatePickerResultCount = 0;
|
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) {
|
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
|
||||||
// Note: Ignore results after the first one - android sends multiples.
|
// Note: Ignore results after the first one - android sends multiples.
|
||||||
if (mDatePickerResultCount++ == 0) {
|
if (mDatePickerResultCount++ == 0) {
|
||||||
@ -110,6 +102,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
|||||||
setExpiryDate(null);
|
setExpiryDate(null);
|
||||||
|
|
||||||
mExpiryDateButton.setOnClickListener(new OnClickListener() {
|
mExpiryDateButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@TargetApi(11)
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
GregorianCalendar date = mExpiryDate;
|
GregorianCalendar date = mExpiryDate;
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
@ -137,16 +130,18 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// setCalendarViewShown() is supported from API 11 onwards.
|
// 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.
|
// Hide calendarView in tablets because of the unix warparound bug.
|
||||||
dialog.getDatePicker().setCalendarViewShown(false);
|
dialog.getDatePicker().setCalendarViewShown(false);
|
||||||
|
}
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||||
if ( dialog != null && mCreatedDate != null ) {
|
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 {
|
} else {
|
||||||
//When created date isn't available
|
//When created date isn't available
|
||||||
dialog.getDatePicker().setMinDate(date.getTime().getTime()+ DateUtils.DAY_IN_MILLIS);
|
dialog.getDatePicker().setMinDate(date.getTime().getTime() + DateUtils.DAY_IN_MILLIS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,9 +280,11 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
|||||||
|
|
||||||
class ExpiryDatePickerDialog extends DatePickerDialog {
|
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);
|
super(context, callBack, year, monthOfYear, dayOfMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set permanent title.
|
//Set permanent title.
|
||||||
public void setTitle(CharSequence title) {
|
public void setTitle(CharSequence title) {
|
||||||
super.setTitle(getContext().getString(R.string.expiry_date_dialog_title));
|
super.setTitle(getContext().getString(R.string.expiry_date_dialog_title));
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.widget;
|
package org.sufficientlysecure.keychain.ui.widget;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -25,8 +23,8 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener {
|
public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener {
|
||||||
private EditorListener mEditorListener = null;
|
private EditorListener mEditorListener = null;
|
||||||
|
@ -31,9 +31,7 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
@ -57,7 +55,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
|
|
||||||
private Choice mNewKeyAlgorithmChoice;
|
private Choice mNewKeyAlgorithmChoice;
|
||||||
private int mNewKeySize;
|
private int mNewKeySize;
|
||||||
private boolean canEdit = true;
|
private boolean mCanEdit = true;
|
||||||
|
|
||||||
private ActionBarActivity mActivity;
|
private ActionBarActivity mActivity;
|
||||||
|
|
||||||
@ -97,8 +95,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCanEdit(boolean bCanEdit) {
|
public void setCanEdit(boolean bCanEdit) {
|
||||||
canEdit = bCanEdit;
|
mCanEdit = bCanEdit;
|
||||||
if (!canEdit) {
|
if (!mCanEdit) {
|
||||||
mPlusButton.setVisibility(View.INVISIBLE);
|
mPlusButton.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +137,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (canEdit) {
|
if (mCanEdit) {
|
||||||
switch (mType) {
|
switch (mType) {
|
||||||
case Id.type.user_id: {
|
case Id.type.user_id: {
|
||||||
UserIdEditor view = (UserIdEditor) mInflater.inflate(
|
UserIdEditor view = (UserIdEditor) mInflater.inflate(
|
||||||
@ -153,15 +151,18 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Id.type.key: {
|
case Id.type.key: {
|
||||||
CreateKeyDialogFragment mCreateKeyDialogFragment = CreateKeyDialogFragment.newInstance(mEditors.getChildCount());
|
CreateKeyDialogFragment mCreateKeyDialogFragment =
|
||||||
mCreateKeyDialogFragment.setOnAlgorithmSelectedListener(new CreateKeyDialogFragment.OnAlgorithmSelectedListener() {
|
CreateKeyDialogFragment.newInstance(mEditors.getChildCount());
|
||||||
@Override
|
mCreateKeyDialogFragment
|
||||||
public void onAlgorithmSelected(Choice algorithmChoice, int keySize) {
|
.setOnAlgorithmSelectedListener(
|
||||||
mNewKeyAlgorithmChoice = algorithmChoice;
|
new CreateKeyDialogFragment.OnAlgorithmSelectedListener() {
|
||||||
mNewKeySize = keySize;
|
@Override
|
||||||
createKey();
|
public void onAlgorithmSelected(Choice algorithmChoice, int keySize) {
|
||||||
}
|
mNewKeyAlgorithmChoice = algorithmChoice;
|
||||||
});
|
mNewKeySize = keySize;
|
||||||
|
createKey();
|
||||||
|
}
|
||||||
|
});
|
||||||
mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog");
|
mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -188,7 +189,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
if (mEditors.getChildCount() == 0) {
|
if (mEditors.getChildCount() == 0) {
|
||||||
view.setIsMainUserId(true);
|
view.setIsMainUserId(true);
|
||||||
}
|
}
|
||||||
view.setCanEdit(canEdit);
|
view.setCanEdit(mCanEdit);
|
||||||
mEditors.addView(view);
|
mEditors.addView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +210,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
view.setEditorListener(this);
|
view.setEditorListener(this);
|
||||||
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
||||||
view.setValue(list.get(i), isMasterKey, usages.get(i));
|
view.setValue(list.get(i), isMasterKey, usages.get(i));
|
||||||
view.setCanEdit(canEdit);
|
view.setCanEdit(mCanEdit);
|
||||||
mEditors.addView(view);
|
mEditors.addView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Copied from StickyListHeaders lib example
|
* Copied from StickyListHeaders lib example
|
||||||
*
|
*
|
||||||
* @author Eric Frohnhoefer
|
* @author Eric Frohnhoefer
|
||||||
*/
|
*/
|
||||||
public class UnderlineTextView extends TextView {
|
public class UnderlineTextView extends TextView {
|
||||||
|
@ -16,21 +16,22 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui.widget;
|
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.content.Context;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Patterns;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.*;
|
||||||
import com.beardedhen.androidbootstrap.BootstrapButton;
|
import com.beardedhen.androidbootstrap.BootstrapButton;
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.helper.ContactHelper;
|
import org.sufficientlysecure.keychain.helper.ContactHelper;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
|
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
|
||||||
private EditorListener mEditorListener = null;
|
private EditorListener mEditorListener = null;
|
||||||
|
|
||||||
@ -40,14 +41,6 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
|
|||||||
private AutoCompleteTextView mEmail;
|
private AutoCompleteTextView mEmail;
|
||||||
private EditText mComment;
|
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 {
|
public static class NoNameException extends Exception {
|
||||||
static final long serialVersionUID = 0xf812773343L;
|
static final long serialVersionUID = 0xf812773343L;
|
||||||
|
|
||||||
@ -109,8 +102,33 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
|
|||||||
mEmail.setAdapter(
|
mEmail.setAdapter(
|
||||||
new ArrayAdapter<String>
|
new ArrayAdapter<String>
|
||||||
(this.getContext(), android.R.layout.simple_dropdown_item_1line,
|
(this.getContext(), android.R.layout.simple_dropdown_item_1line,
|
||||||
ContactHelper.getMailAccounts(getContext())
|
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();
|
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 name = ("" + mName.getText()).trim();
|
||||||
String email = ("" + mEmail.getText()).trim();
|
String email = ("" + mEmail.getText()).trim();
|
||||||
String comment = ("" + mComment.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;
|
String userId = name;
|
||||||
if (comment.length() > 0) {
|
if (comment.length() > 0) {
|
||||||
userId += " (" + comment + ")";
|
userId += " (" + comment + ")";
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.util;
|
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.bcpg.HashAlgorithmTags;
|
||||||
import org.spongycastle.openpgp.PGPEncryptedData;
|
import org.spongycastle.openpgp.PGPEncryptedData;
|
||||||
import org.sufficientlysecure.keychain.Id;
|
import org.sufficientlysecure.keychain.Id;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@SuppressLint("UseSparseArrays")
|
@SuppressLint("UseSparseArrays")
|
||||||
public class AlgorithmNames {
|
public class AlgorithmNames {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user