aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hammann <github@honnel.de>2014-03-12 20:44:33 +0100
committerDaniel Hammann <github@honnel.de>2014-03-12 20:44:33 +0100
commit6ca58dd2116dd8c0e23826fc3361c251da530df8 (patch)
tree66e0c22d4c980bf5e9ee29e74a76d5da8132479c
parent77ebfd08758ddd0383b2d235916284640f9f0aa9 (diff)
parenta9e5619a14f5cef4e0211d56c000b0e853120f1d (diff)
downloadopen-keychain-6ca58dd2116dd8c0e23826fc3361c251da530df8.tar.gz
open-keychain-6ca58dd2116dd8c0e23826fc3361c251da530df8.tar.bz2
open-keychain-6ca58dd2116dd8c0e23826fc3361c251da530df8.zip
Merge branch 'master' of https://github.com/openpgp-keychain/openpgp-keychain
-rw-r--r--OpenPGP-Keychain/src/main/AndroidManifest.xml1
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java106
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java41
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java16
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java8
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java3
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java68
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java40
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java24
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java5
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java10
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java14
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java3
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java12
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java3
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java11
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java8
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java78
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java4
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java5
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java1
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java3
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java17
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java2
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save.xml27
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save_cancel.xml29
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/actionbar_include_save_button.xml36
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_app_error_message.xml1
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/api_app_select_pub_keys_activity.xml1
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/edit_key_user_id_item.xml2
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/key_server_export.xml1
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/select_secret_key_layout_fragment.xml23
-rw-r--r--OpenPGP-Keychain/src/main/res/menu/key_list_public_multi.xml4
-rw-r--r--OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml4
-rw-r--r--README.md8
-rwxr-xr-xtools/checkstyle1
-rw-r--r--tools/checkstyle.xml356
44 files changed, 660 insertions, 336 deletions
diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml
index 10f112f23..4fabf7432 100644
--- a/OpenPGP-Keychain/src/main/AndroidManifest.xml
+++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml
@@ -50,6 +50,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.NFC" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! -->
<application
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index 4428c7133..34a3de8d5 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -43,6 +43,8 @@ public final class Constants {
public static final class path {
public static final String APP_DIR = Environment.getExternalStorageDirectory()
+ "/OpenPGP-Keychain";
+ public static final String APP_DIR_FILE_SEC = APP_DIR + "/secexport.asc";
+ public static final String APP_DIR_FILE_PUB = APP_DIR + "/pubexport.asc";
}
public static final class pref {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
index 6aa8e7d74..24e8ff4c7 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java
@@ -56,28 +56,33 @@ public class ActionBarHelper {
* Sets custom view on ActionBar for Done/Cancel activities
*
* @param actionBar
- * @param doneText
- * @param doneOnClickListener
- * @param cancelText
- * @param cancelOnClickListener
+ * @param firstText
+ * @param firstDrawableId
+ * @param firstOnClickListener
+ * @param secondText
+ * @param secondDrawableId
+ * @param secondOnClickListener
*/
- public static void setDoneCancelView(ActionBar actionBar, int doneText,
- OnClickListener doneOnClickListener, int cancelText,
- OnClickListener cancelOnClickListener) {
+ public static void setTwoButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
+ OnClickListener firstOnClickListener, int secondText, int secondDrawableId,
+ OnClickListener secondOnClickListener) {
- // Inflate a "Done"/"Cancel" custom action bar view
+ // Inflate the custom action bar view
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_cancel, null);
- ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)).setText(doneText);
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
+ firstTextView.setText(firstText);
+ firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- doneOnClickListener);
- ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text))
- .setText(cancelText);
+ firstOnClickListener);
+ TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text));
+ secondTextView.setText(secondText);
+ secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0);
customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
- cancelOnClickListener);
+ secondOnClickListener);
// Show the custom action bar view and hide the normal Home icon and title.
actionBar.setDisplayShowTitleEnabled(false);
@@ -91,20 +96,22 @@ public class ActionBarHelper {
* Sets custom view on ActionBar for Done activities
*
* @param actionBar
- * @param doneText
- * @param doneOnClickListener
+ * @param firstText
+ * @param firstOnClickListener
*/
- public static void setDoneView(ActionBar actionBar, int doneText,
- OnClickListener doneOnClickListener) {
+ public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
+ OnClickListener firstOnClickListener) {
// Inflate a "Done" custom action bar view to serve as the "Up" affordance.
final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View customActionBarView = inflater
.inflate(R.layout.actionbar_custom_view_done, null);
- ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)).setText(doneText);
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
+ firstTextView.setText(firstText);
+ firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- doneOnClickListener);
+ firstOnClickListener);
// Show the custom action bar view and hide the normal Home icon and title.
actionBar.setDisplayShowTitleEnabled(false);
@@ -112,65 +119,4 @@ public class ActionBarHelper {
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(customActionBarView);
}
-
- /**
- * Sets custom view on ActionBar for Save activities
- *
- * @param actionBar
- * @param saveText
- * @param saveOnClickListener
- */
- public static void setSaveView(ActionBar actionBar, int saveText,
- OnClickListener saveOnClickListener) {
- // Inflate a "Save" custom action bar view to serve as the "Up" affordance.
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater
- .inflate(R.layout.actionbar_custom_view_save, null);
-
- ((TextView) customActionBarView.findViewById(R.id.actionbar_save_text)).setText(saveText);
- customActionBarView.findViewById(R.id.actionbar_save).setOnClickListener(
- saveOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView);
- }
-
- /**
- * Sets custom view on ActionBar for Save/Cancel activities
- *
- * @param actionBar
- * @param saveText
- * @param saveOnClickListener
- * @param cancelText
- * @param cancelOnClickListener
- */
- public static void setSaveCancelView(ActionBar actionBar, int saveText,
- OnClickListener saveOnClickListener, int cancelText,
- OnClickListener cancelOnClickListener) {
-
- // Inflate a "Done"/"Cancel" custom action bar view
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater.inflate(
- R.layout.actionbar_custom_view_save_cancel, null);
-
- ((TextView) customActionBarView.findViewById(R.id.actionbar_save_text)).setText(saveText);
- customActionBarView.findViewById(R.id.actionbar_save).setOnClickListener(
- saveOnClickListener);
- ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text))
- .setText(cancelText);
- customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
- cancelOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- }
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java
new file mode 100644
index 000000000..f8ed21816
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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.helper;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.util.Patterns;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ContactHelper {
+
+ public static final List<String> getMailAccounts(Context context) {
+ final Account[] accounts = AccountManager.get(context).getAccounts();
+ final Set<String> emailSet = new HashSet<String>();
+ for (Account account : accounts) {
+ if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
+ emailSet.add(account.name);
+ }
+ }
+ return new ArrayList<String>(emailSet);
+ }
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
index 6aa28fec8..19dfccbde 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
@@ -20,7 +20,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
@@ -63,7 +62,7 @@ public class ExportHelper {
/**
* Show dialog where to export keys
*/
- public void showExportKeysDialog(final Uri dataUri, final int keyType,
+ public void showExportKeysDialog(final long[] rowIds, final int keyType,
final String exportFilename) {
mExportFilename = exportFilename;
@@ -75,7 +74,7 @@ public class ExportHelper {
Bundle data = message.getData();
mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
- exportKeys(dataUri, keyType);
+ exportKeys(rowIds, keyType);
}
}
};
@@ -86,7 +85,7 @@ public class ExportHelper {
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
public void run() {
String title = null;
- if (dataUri == null) {
+ if (rowIds == null) {
// export all keys
title = activity.getString(R.string.title_export_keys);
} else {
@@ -112,7 +111,7 @@ public class ExportHelper {
/**
* Export keys
*/
- public void exportKeys(Uri dataUri, int keyType) {
+ public void exportKeys(long[] rowIds, int keyType) {
Log.d(Constants.TAG, "exportKeys started");
// Send all information needed to service to export key in other thread
@@ -126,13 +125,10 @@ public class ExportHelper {
data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFilename);
data.putInt(KeychainIntentService.EXPORT_KEY_TYPE, keyType);
- if (dataUri == null) {
+ if (rowIds == null) {
data.putBoolean(KeychainIntentService.EXPORT_ALL, true);
} else {
- // TODO: put data uri into service???
- long keyRingMasterKeyId = ProviderHelper.getMasterKeyId(activity, dataUri);
-
- data.putLong(KeychainIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, keyRingMasterKeyId);
+ data.putLongArray(KeychainIntentService.EXPORT_KEY_RING_ROW_ID, rowIds);
}
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java
index 493f25707..f18a290b3 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java
@@ -144,8 +144,8 @@ public class Preferences {
Constants.defaults.KEY_SERVERS);
Vector<String> servers = new Vector<String>();
String chunks[] = rawData.split(",");
- for (int i = 0; i < chunks.length; ++i) {
- String tmp = chunks[i].trim();
+ for (String c : chunks) {
+ String tmp = c.trim();
if (tmp.length() > 0) {
servers.add(tmp);
}
@@ -156,8 +156,8 @@ public class Preferences {
public void setKeyServers(String[] value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
String rawData = "";
- for (int i = 0; i < value.length; ++i) {
- String tmp = value[i].trim();
+ for (String v : value) {
+ String tmp = v.trim();
if (tmp.length() == 0) {
continue;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
index 7ac904d89..1db4f98b1 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
@@ -193,11 +193,10 @@ public class PgpHelper {
* @param context
* @param progress
* @param file
- * @throws FileNotFoundException
* @throws IOException
*/
public static void deleteFileSecurely(Context context, ProgressDialogUpdater progress, File file)
- throws FileNotFoundException, IOException {
+ throws IOException {
long length = file.length();
SecureRandom random = new SecureRandom();
RandomAccessFile raf = new RandomAccessFile(file, "rws");
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
index 7c635a00b..138e54f71 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
@@ -79,8 +79,9 @@ public class PgpImportExport {
public boolean uploadKeyRingToServer(HkpKeyServer server, PGPPublicKeyRing keyring) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ArmoredOutputStream aos = new ArmoredOutputStream(bos);
+ ArmoredOutputStream aos = null;
try {
+ aos = new ArmoredOutputStream(bos);
aos.write(keyring.getEncoded());
aos.close();
@@ -95,7 +96,8 @@ public class PgpImportExport {
return false;
} finally {
try {
- bos.close();
+ if (aos != null) aos.close();
+ if (bos != null) bos.close();
} catch (IOException e) {
}
}
@@ -155,59 +157,53 @@ public class PgpImportExport {
return returnData;
}
- public Bundle exportKeyRings(ArrayList<Long> keyRingMasterKeyIds, int keyType,
- OutputStream outStream) throws PgpGeneralException, FileNotFoundException,
+ public Bundle exportKeyRings(ArrayList<Long> keyRingRowIds, int keyType,
+ OutputStream outStream) throws PgpGeneralException,
PGPException, IOException {
Bundle returnData = new Bundle();
+ int rowIdsSize = keyRingRowIds.size();
+
updateProgress(
mContext.getResources().getQuantityString(R.plurals.progress_exporting_key,
- keyRingMasterKeyIds.size()), 0, 100);
+ rowIdsSize), 0, 100);
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new PgpGeneralException(
mContext.getString(R.string.error_external_storage_not_ready));
}
-
- if (keyType == Id.type.secret_key) {
- ArmoredOutputStream outSec = new ArmoredOutputStream(outStream);
- outSec.setHeader("Version", PgpHelper.getFullVersion(mContext));
-
- for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
- updateProgress(i * 100 / keyRingMasterKeyIds.size() / 2, 100);
-
- PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
- mContext, keyRingMasterKeyIds.get(i));
+ // For each row id
+ for (int i = 0; i < rowIdsSize; ++i) {
+ // Create an output stream
+ ArmoredOutputStream arOutStream = new ArmoredOutputStream(outStream);
+ arOutStream.setHeader("Version", PgpHelper.getFullVersion(mContext));
+
+ // If the keyType is secret get the PGPSecretKeyRing
+ // based on the row id and encode it to the output
+ if (keyType == Id.type.secret_key) {
+ updateProgress(i * 100 / rowIdsSize / 2, 100);
+ PGPSecretKeyRing secretKeyRing =
+ ProviderHelper.getPGPSecretKeyRingByRowId(mContext, keyRingRowIds.get(i));
if (secretKeyRing != null) {
- secretKeyRing.encode(outSec);
- }
- }
- outSec.close();
- } else {
- // export public keyrings...
- ArmoredOutputStream outPub = new ArmoredOutputStream(outStream);
- outPub.setHeader("Version", PgpHelper.getFullVersion(mContext));
-
- for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
- // double the needed time if exporting both public and secret parts
- if (keyType == Id.type.secret_key) {
- updateProgress(i * 100 / keyRingMasterKeyIds.size() / 2, 100);
- } else {
- updateProgress(i * 100 / keyRingMasterKeyIds.size(), 100);
+ secretKeyRing.encode(arOutStream);
}
-
- PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(
- mContext, keyRingMasterKeyIds.get(i));
+ // Else if it's a public key get the PGPPublicKeyRing
+ // and encode that to the output
+ } else {
+ updateProgress(i * 100 / rowIdsSize, 100);
+ PGPPublicKeyRing publicKeyRing =
+ ProviderHelper.getPGPPublicKeyRingByRowId(mContext, keyRingRowIds.get(i));
if (publicKeyRing != null) {
- publicKeyRing.encode(outPub);
+ publicKeyRing.encode(arOutStream);
}
}
- outPub.close();
+
+ arOutStream.close();
}
- returnData.putInt(KeychainIntentService.RESULT_EXPORT, keyRingMasterKeyIds.size());
+ returnData.putInt(KeychainIntentService.RESULT_EXPORT, rowIdsSize);
updateProgress(R.string.progress_done, 100, 100);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index e1ca88fb0..5ebb53f20 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -190,7 +190,7 @@ public class PgpKeyOperation {
}
public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
- String newPassPhrase) throws IOException, PGPException, PGPException,
+ String newPassPhrase) throws IOException, PGPException,
NoSuchProviderException {
updateProgress(R.string.progress_building_key, 0, 100);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index ac0692213..dd538fbf4 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -405,6 +405,30 @@ public class ProviderHelper {
}
/**
+ * Private helper method
+ */
+ private static ArrayList<Long> getKeyRingsRowIds(Context context, Uri queryUri) {
+ Cursor cursor = context.getContentResolver().query(queryUri,
+ new String[]{KeyRings._ID}, null, null, null);
+
+ ArrayList<Long> rowIds = new ArrayList<Long>();
+ if (cursor != null) {
+ int IdCol = cursor.getColumnIndex(KeyRings._ID);
+ if (cursor.moveToFirst()) {
+ do {
+ rowIds.add(cursor.getLong(IdCol));
+ } while (cursor.moveToNext());
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return rowIds;
+ }
+
+ /**
* Retrieves ids of all SecretKeyRings
*/
public static ArrayList<Long> getSecretKeyRingsMasterKeyIds(Context context) {
@@ -420,6 +444,22 @@ public class ProviderHelper {
return getKeyRingsMasterKeyIds(context, queryUri);
}
+ /**
+ * Retrieves ids of all SecretKeyRings
+ */
+ public static ArrayList<Long> getSecretKeyRingsRowIds(Context context) {
+ Uri queryUri = KeyRings.buildSecretKeyRingsUri();
+ return getKeyRingsRowIds(context, queryUri);
+ }
+
+ /**
+ * Retrieves ids of all PublicKeyRings
+ */
+ public static ArrayList<Long> getPublicKeyRingsRowIds(Context context) {
+ Uri queryUri = KeyRings.buildPublicKeyRingsUri();
+ return getKeyRingsRowIds(context, queryUri);
+ }
+
public static void deletePublicKeyRing(Context context, long rowId) {
ContentResolver cr = context.getContentResolver();
cr.delete(KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)), null, null);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 902c66fe9..93238349d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -50,6 +50,7 @@ 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;
@@ -153,6 +154,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String EXPORT_KEY_TYPE = "export_key_type";
public static final String EXPORT_ALL = "export_all";
public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "export_key_ring_id";
+ public static final String EXPORT_KEY_RING_ROW_ID = "export_key_rind_row_id";
// upload key
public static final String UPLOAD_KEY_SERVER = "upload_key_server";
@@ -675,10 +677,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
String outputFile = data.getString(EXPORT_FILENAME);
+ long[] rowIds = new long[0];
+
+ // If not exporting all keys get the rowIds of the keys to export from the intent
boolean exportAll = data.getBoolean(EXPORT_ALL);
- long keyRingMasterKeyId = -1;
if (!exportAll) {
- keyRingMasterKeyId = data.getLong(EXPORT_KEY_RING_MASTER_KEY_ID);
+ rowIds = data.getLongArray(EXPORT_KEY_RING_ROW_ID);
}
/* Operation */
@@ -691,24 +695,26 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// OutputStream
FileOutputStream outStream = new FileOutputStream(outputFile);
- ArrayList<Long> keyRingMasterKeyIds = new ArrayList<Long>();
+ ArrayList<Long> keyRingRowIds = new ArrayList<Long>();
if (exportAll) {
- // get all key ring row ids based on export type
+ // get all key ring row ids based on export type
if (keyType == Id.type.public_key) {
- keyRingMasterKeyIds = ProviderHelper.getPublicKeyRingsMasterKeyIds(this);
+ keyRingRowIds = ProviderHelper.getPublicKeyRingsRowIds(this);
} else {
- keyRingMasterKeyIds = ProviderHelper.getSecretKeyRingsMasterKeyIds(this);
+ keyRingRowIds = ProviderHelper.getSecretKeyRingsRowIds(this);
}
} else {
- keyRingMasterKeyIds.add(keyRingMasterKeyId);
+ for(long rowId : rowIds) {
+ keyRingRowIds.add(rowId);
+ }
}
- Bundle resultData = new Bundle();
+ Bundle resultData;
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
resultData = pgpImportExport
- .exportKeyRings(keyRingMasterKeyIds, keyType, outStream);
+ .exportKeyRings(keyRingRowIds, keyType, outStream);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index abd2320e3..ce34d451d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -21,6 +21,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
+import android.util.LongSparseArray;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
@@ -77,7 +78,7 @@ public class PassphraseCacheService extends Service {
private BroadcastReceiver mIntentReceiver;
- private HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>();
+ private LongSparseArray<String> mPassphraseCache = new LongSparseArray<String>();
Context mContext;
@@ -347,7 +348,7 @@ public class PassphraseCacheService extends Service {
Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!");
// stop whole service if no cached passphrases remaining
- if (mPassphraseCache.isEmpty()) {
+ if (mPassphraseCache.size() == 0) {
Log.d(TAG, "No passphrases remaining in memory, stopping service!");
stopSelf();
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
index a7afc9698..178b2fc67 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java
@@ -41,7 +41,7 @@ public class AppSettingsActivity extends ActionBarActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setDoneView(getSupportActionBar(), R.string.api_settings_save,
+ ActionBarHelper.setOneButtonView(getSupportActionBar(), R.string.api_settings_save, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
index 11b3ee217..8fb562884 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
@@ -88,7 +88,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.api_register_allow,
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.api_register_allow, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -108,7 +108,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
RemoteServiceActivity.this.finish();
}
}
- }, R.string.api_register_disallow, new View.OnClickListener() {
+ }, R.string.api_register_disallow, R.drawable.ic_action_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
// Disallow
@@ -161,7 +161,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
}
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_okay,
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -173,7 +173,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
- }, R.string.btn_do_not_save, new View.OnClickListener() {
+ }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
@@ -214,7 +214,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
String text = "<font color=\"red\">" + errorMessage + "</font>";
// Inflate a "Done" custom action bar view
- ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_okay,
+ ActionBarHelper.setOneButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index 76acf15b0..38d763ce4 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -530,6 +530,10 @@ public class DecryptActivity extends DrawerActivity {
Log.e(Constants.TAG, "File not found!", e);
AppMsg.makeText(this, getString(R.string.error_file_not_found, e.getMessage()),
AppMsg.STYLE_ALERT).show();
+ } finally {
+ try {
+ if (inStream != null) inStream.close();
+ } catch (Exception e){ }
}
} else {
inStream = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 628f642d8..72dc97ccd 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -134,14 +134,14 @@ public class EditKeyActivity extends ActionBarActivity {
* @param intent
*/
private void handleActionCreateKey(Intent intent) {
- // Inflate a "Done"/"Cancel" custom action bar
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_save,
+ // Inflate a "Save"/"Cancel" custom action bar
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_save, R.drawable.ic_action_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
saveClicked();
}
- }, R.string.btn_do_not_save, new View.OnClickListener() {
+ }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
cancelClicked();
@@ -249,8 +249,8 @@ public class EditKeyActivity extends ActionBarActivity {
* @param intent
*/
private void handleActionEditKey(Intent intent) {
- // Inflate a "Done"/"Cancel" custom action bar
- ActionBarHelper.setSaveView(getSupportActionBar(), R.string.btn_save,
+ // Inflate a "Save"/"Cancel" custom action bar
+ ActionBarHelper.setOneButtonView(getSupportActionBar(), R.string.btn_save, R.drawable.ic_action_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -329,8 +329,8 @@ public class EditKeyActivity extends ActionBarActivity {
cancelClicked();
return true;
case R.id.menu_key_edit_export_file:
- mExportHelper.showExportKeysDialog(mDataUri, Id.type.secret_key, Constants.path.APP_DIR
- + "/secexport.asc");
+ long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
+ mExportHelper.showExportKeysDialog(ids, Id.type.secret_key, Constants.path.APP_DIR_FILE_SEC);
return true;
case R.id.menu_key_edit_delete: {
// Message is received after key is deleted
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
index 4521786f7..9bd9ee225 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
@@ -59,8 +59,7 @@ public class KeyListPublicActivity extends DrawerActivity {
return true;
case R.id.menu_key_list_public_export:
- mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.path.APP_DIR
- + "/pubexport.asc");
+ mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.path.APP_DIR_FILE_PUB);
return true;
default:
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
index 707001de9..de965daa5 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
@@ -18,10 +18,11 @@
package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
-import java.util.Set;
+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.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
@@ -47,6 +48,7 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.view.ActionMode;
@@ -179,6 +181,11 @@ public class KeyListPublicFragment extends Fragment implements SearchView.OnQuer
encrypt(mode, ids);
break;
}
+ case R.id.menu_key_list_public_multi_export: {
+ 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_public_multi_delete: {
showDeleteKeyDialog(mode, ids);
break;
@@ -367,7 +374,7 @@ public class KeyListPublicFragment extends Fragment implements SearchView.OnQuer
// Execute this when searching
mSearchView.setOnQueryTextListener(this);
- //Erase search result without focus
+ // Erase search result without focus
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
@@ -377,6 +384,7 @@ public class KeyListPublicFragment extends Fragment implements SearchView.OnQuer
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
mCurQuery = null;
+ mSearchView.setQuery("", true);
getLoaderManager().restartLoader(0, null, KeyListPublicFragment.this);
return true;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
index e58ebe819..cd3c8b4fd 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
@@ -62,8 +62,7 @@ public class KeyListSecretActivity extends DrawerActivity {
return true;
case R.id.menu_key_list_secret_export:
- mExportHelper.showExportKeysDialog(null, Id.type.secret_key, Constants.path.APP_DIR
- + "/secexport.asc");
+ mExportHelper.showExportKeysDialog(null, Id.type.secret_key, Constants.path.APP_DIR_FILE_SEC);
return true;
case R.id.menu_key_list_secret_import:
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
index 76212afc3..e84b2f4c8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
@@ -17,10 +17,10 @@
package org.sufficientlysecure.keychain.ui;
-import java.util.Set;
-
+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.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
@@ -41,6 +41,7 @@ import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
+import android.support.v7.app.ActionBarActivity;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
@@ -106,6 +107,12 @@ public class KeyListSecretFragment extends ListFragment implements
}
break;
}
+ case R.id.menu_key_list_public_multi_export: {
+ ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
+ mExportHelper.showExportKeysDialog(ids, Id.type.secret_key, Constants.path.APP_DIR_FILE_SEC);
+ break;
+ }
+
}
return true;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java
index b5ac739ae..50fec1ffc 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java
@@ -50,14 +50,14 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
super.onCreate(savedInstanceState);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_okay,
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// ok
okClicked();
}
- }, R.string.btn_do_not_save, new View.OnClickListener() {
+ }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
@@ -81,11 +81,11 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
Intent intent = getIntent();
String servers[] = intent.getStringArrayExtra(EXTRA_KEY_SERVERS);
if (servers != null) {
- for (int i = 0; i < servers.length; ++i) {
+ for (String serv : servers) {
KeyServerEditor view = (KeyServerEditor) mInflater.inflate(
R.layout.key_server_editor, mEditors, false);
view.setEditorListener(this);
- view.setValue(servers[i]);
+ view.setValue(serv);
mEditors.addView(view);
}
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
index 86ae0073f..3c63628f7 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
@@ -46,14 +46,14 @@ public class SelectPublicKeyActivity extends ActionBarActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_okay,
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// ok
okClicked();
}
- }, R.string.btn_do_not_save, new View.OnClickListener() {
+ }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
index c1c9aa705..d320af451 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
@@ -199,8 +199,8 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
if (masterKeyIds != null) {
for (int i = 0; i < getListView().getCount(); ++i) {
long keyId = mAdapter.getMasterKeyId(i);
- for (int j = 0; j < masterKeyIds.length; ++j) {
- if (keyId == masterKeyIds[j]) {
+ for (long masterKeyId : masterKeyIds) {
+ if (keyId == masterKeyId) {
getListView().setItemChecked(i, true);
break;
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java
index ca5d8b262..c9129285e 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java
@@ -71,50 +71,44 @@ public class SelectSecretKeyLayoutFragment extends Fragment {
mKeyUserIdRest.setVisibility(View.GONE);
} else {
- String uid = getResources().getString(R.string.user_id_no_name);
- String uidExtra = "";
- String masterkeyIdHex = "";
-
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
getActivity(), secretKeyId);
if (keyRing != null) {
PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
- masterkeyIdHex = PgpKeyHelper.convertKeyIdToHex(secretKeyId);
+ String masterkeyIdHex = PgpKeyHelper.convertKeyIdToHex(secretKeyId);
if (key != null) {
String userId = PgpKeyHelper.getMainUserIdSafe(getActivity(), key);
- /*String chunks[] = mUserId.split(" <", 2);
- uid = chunks[0];
- if (chunks.length > 1) {
- uidExtra = "<" + chunks[1];
- }*/
+
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
- String userName, userEmail;
+ String userName, userEmail;
- if (userIdSplit[0] != null) { userName = userIdSplit[0]; }
- else { userName = getActivity().getResources().getString(R.string.user_id_no_name); }
+ if (userIdSplit[0] != null) {
+ userName = userIdSplit[0];
+ } else {
+ userName = getActivity().getResources().getString(R.string.user_id_no_name);
+ }
- if (userIdSplit[1] != null) { userEmail = userIdSplit[1]; }
- else { userEmail = getActivity().getResources().getString(R.string.error_user_id_no_email); }
+ if (userIdSplit[1] != null) {
+ userEmail = userIdSplit[1];
+ } else {
+ userEmail = getActivity().getResources().getString(R.string.error_user_id_no_email);
+ }
mKeyMasterKeyIdHex.setText(masterkeyIdHex);
mKeyUserId.setText(userName);
mKeyUserIdRest.setText(userEmail);
mKeyUserId.setVisibility(View.VISIBLE);
mKeyUserIdRest.setVisibility(View.VISIBLE);
- }
- else{
+ } else {
mKeyMasterKeyIdHex.setText(getActivity().getResources().getString(R.string.no_key));
mKeyUserId.setVisibility(View.GONE);
mKeyUserIdRest.setVisibility(View.GONE);
-
}
-
- }
- else{
- mKeyMasterKeyIdHex.setText(getActivity().getResources().getString(R.string.no_keys_added_or_updated)+" for master id: "+secretKeyId);
- mKeyUserId.setVisibility(View.GONE);
- mKeyUserIdRest.setVisibility(View.GONE);
+ } else {
+ mKeyMasterKeyIdHex.setText(getActivity().getResources().getString(R.string.no_keys_added_or_updated) + " for master id: " + secretKeyId);
+ mKeyUserId.setVisibility(View.GONE);
+ mKeyUserIdRest.setVisibility(View.GONE);
}
}
@@ -154,31 +148,31 @@ public class SelectSecretKeyLayoutFragment extends Fragment {
startActivityForResult(intent, REQUEST_CODE_SELECT_KEY);
}
- //Select Secret Key Activity delivers the intent which was sent by it using interface to Select
+ // Select Secret Key Activity delivers the intent which was sent by it using interface to Select
// Secret Key Fragment.Intent contains Master Key Id, User Email, User Name, Master Key Id Hex.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode & 0xFFFF) {
- case REQUEST_CODE_SELECT_KEY: {
- long secretKeyId;
- if (resultCode == Activity.RESULT_OK) {
- Bundle bundle = data.getExtras();
- secretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID);
- selectKey(secretKeyId);
-
- // remove displayed errors
- mKeyUserId.setError(null);
-
- // give value back to callback
- mCallback.onKeySelected(secretKeyId);
+ case REQUEST_CODE_SELECT_KEY: {
+ long secretKeyId;
+ if (resultCode == Activity.RESULT_OK) {
+ Bundle bundle = data.getExtras();
+ secretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID);
+ selectKey(secretKeyId);
+
+ // remove displayed errors
+ mKeyUserId.setError(null);
+
+ // give value back to callback
+ mCallback.onKeySelected(secretKeyId);
+ }
+ break;
}
- break;
- }
- default:
- super.onActivityResult(requestCode, resultCode, data);
+ default:
+ super.onActivityResult(requestCode, resultCode, data);
- break;
+ break;
}
}
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 390de9ab9..4cc5e1b62 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -118,8 +118,8 @@ public class ViewKeyActivity extends ActionBarActivity {
uploadToKeyserver(mDataUri);
return true;
case R.id.menu_key_view_export_file:
- mExportHelper.showExportKeysDialog(mDataUri, Id.type.public_key, Constants.path.APP_DIR
- + "/pubexport.asc");
+ long[] ids = new long[]{Long.valueOf(mDataUri.getLastPathSegment())};
+ mExportHelper.showExportKeysDialog(ids, Id.type.public_key, Constants.path.APP_DIR_FILE_PUB);
return true;
case R.id.menu_key_view_share_default_fingerprint:
shareKey(mDataUri, true);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
index 65fe08484..adb06a068 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
@@ -280,13 +280,14 @@ public class ViewKeyMainFragment extends Fragment implements
// for each 4 characters of the fingerprint + 1 space
for (int i = 0; i < fingerprint.length(); i += 5) {
- String fourChars = fingerprint.substring(i, Math.min(i + 4, fingerprint.length()));
+ int minFingLength = Math.min(i + 4, fingerprint.length());
+ String fourChars = fingerprint.substring(i, minFingLength);
// Create a foreground color by converting the 4 fingerprint chars to an int hashcode
// and then converting that int to hex to use as a color
fcs = new ForegroundColorSpan(
Color.parseColor(String.format("#%06X", (0xFFFFFF & fourChars.hashCode()))));
- sb.setSpan(fcs, i, Math.min(i+4, fingerprint.length()), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ sb.setSpan(fcs, i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
return sb;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
index b8f60633e..d7bb62d01 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
@@ -18,8 +18,6 @@
package org.sufficientlysecure.keychain.ui.adapter;
import java.util.HashMap;
-import java.util.Set;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
index ca3a26066..0bffcaa19 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui.adapter;
import java.util.HashMap;
-import java.util.Set;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
index 98b677511..a47601c9b 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.Choice;
+import java.util.ArrayList;
import java.util.Vector;
public class CreateKeyDialogFragment extends DialogFragment {
@@ -78,7 +79,7 @@ public class CreateKeyDialogFragment extends DialogFragment {
boolean wouldBeMasterKey = (childCount == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
- Vector<Choice> choices = new Vector<Choice>();
+ ArrayList<Choice> choices = new ArrayList<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(
R.string.dsa)));
if (!wouldBeMasterKey) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
index 5428b626e..71cd89ae8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
@@ -19,6 +19,7 @@ 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;
@@ -26,11 +27,9 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.RadioButton;
import com.beardedhen.androidbootstrap.BootstrapButton;
+import org.sufficientlysecure.keychain.helper.ContactHelper;
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
@@ -38,7 +37,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
private BootstrapButton mDeleteButton;
private RadioButton mIsMainUserId;
private EditText mName;
- private EditText mEmail;
+ private AutoCompleteTextView mEmail;
private EditText mComment;
// see http://www.regular-expressions.info/email.html
@@ -102,9 +101,17 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
mIsMainUserId.setOnClickListener(this);
mName = (EditText) findViewById(R.id.name);
- mEmail = (EditText) findViewById(R.id.email);
+ mEmail = (AutoCompleteTextView) findViewById(R.id.email);
mComment = (EditText) findViewById(R.id.comment);
+
+ mEmail.setThreshold(1); // Start working from first character
+ mEmail.setAdapter(
+ new ArrayAdapter<String>
+ (this.getContext(), android.R.layout.simple_dropdown_item_1line,
+ ContactHelper.getMailAccounts(getContext())
+ ));
+
super.onFinishInflate();
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
index 0681847f4..32266839c 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
@@ -226,7 +226,7 @@ public class HkpKeyServer extends KeyServer {
HttpClient client = new DefaultHttpClient();
try {
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort
- + "/pks/lookup?op=get&search=0x" + PgpKeyHelper.convertKeyIdToHex(keyId));
+ + "/pks/lookup?op=get&search=" + PgpKeyHelper.convertKeyIdToHex(keyId));
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
diff --git a/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save.xml b/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save.xml
deleted file mode 100644
index f0dcf177c..000000000
--- a/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:dividerPadding="12dp"
- android:orientation="horizontal"
- android:divider="@drawable/abc_list_divider_holo_light"
- android:showDividers="end" >
-
- <include layout="@layout/actionbar_include_save_button" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save_cancel.xml b/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save_cancel.xml
deleted file mode 100644
index ba08a7714..000000000
--- a/OpenPGP-Keychain/src/main/res/layout/actionbar_custom_view_save_cancel.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:dividerPadding="12dp"
- android:divider="@drawable/abc_list_divider_holo_light"
- android:orientation="horizontal"
- android:showDividers="middle">
-
- <include layout="@layout/actionbar_include_cancel_button" />
-
- <include layout="@layout/actionbar_include_save_button" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/actionbar_include_save_button.xml b/OpenPGP-Keychain/src/main/res/layout/actionbar_include_save_button.xml
deleted file mode 100644
index 86c59dcc5..000000000
--- a/OpenPGP-Keychain/src/main/res/layout/actionbar_include_save_button.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/actionbar_save"
- style="@style/Widget.AppCompat.ActionButton"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <TextView
- android:id="@+id/actionbar_save_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:drawableLeft="@drawable/ic_action_save"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:paddingRight="20dp"
- style="@style/Widget.AppCompat.Light.ActionBar.TabText"
- android:text="Save (set in-code!)" />
-
-</FrameLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_app_error_message.xml b/OpenPGP-Keychain/src/main/res/layout/api_app_error_message.xml
index 5927dbf43..48aa89d4f 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_app_error_message.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_app_error_message.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
diff --git a/OpenPGP-Keychain/src/main/res/layout/api_app_select_pub_keys_activity.xml b/OpenPGP-Keychain/src/main/res/layout/api_app_select_pub_keys_activity.xml
index 877b4e74e..a10592607 100644
--- a/OpenPGP-Keychain/src/main/res/layout/api_app_select_pub_keys_activity.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/api_app_select_pub_keys_activity.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
diff --git a/OpenPGP-Keychain/src/main/res/layout/edit_key_user_id_item.xml b/OpenPGP-Keychain/src/main/res/layout/edit_key_user_id_item.xml
index 663949d8e..3030d6bae 100644
--- a/OpenPGP-Keychain/src/main/res/layout/edit_key_user_id_item.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/edit_key_user_id_item.xml
@@ -49,7 +49,7 @@
android:paddingRight="5dip"
android:text="@string/label_email" />
- <EditText
+ <AutoCompleteTextView
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/OpenPGP-Keychain/src/main/res/layout/key_server_export.xml b/OpenPGP-Keychain/src/main/res/layout/key_server_export.xml
index c162a6e28..6031bf7c7 100644
--- a/OpenPGP-Keychain/src/main/res/layout/key_server_export.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/key_server_export.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
diff --git a/OpenPGP-Keychain/src/main/res/layout/select_secret_key_layout_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/select_secret_key_layout_fragment.xml
index 9b92a373a..1141091a3 100644
--- a/OpenPGP-Keychain/src/main/res/layout/select_secret_key_layout_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/select_secret_key_layout_fragment.xml
@@ -3,7 +3,7 @@
xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical" >
+ android:orientation="horizontal">
<com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/select_secret_key_select_key_button"
@@ -25,19 +25,10 @@
android:layout_marginLeft="4dp"
android:layout_marginTop="4dp"
android:orientation="vertical"
- android:paddingLeft="16dp" >
+ android:paddingLeft="4dp">
<!-- Has been made focusable to display error messages with setError -->
<TextView
- android:id="@+id/select_secret_key_master_key_hex"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/api_settings_no_key"
- />
-
- <TextView
android:id="@+id/select_secret_key_user_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -47,6 +38,7 @@
android:focusableInTouchMode="true"
android:singleLine="true"
android:visibility="gone"
+ android:layout_marginRight="5dip"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall" />
@@ -57,10 +49,19 @@
android:layout_gravity="left"
android:ellipsize="end"
android:singleLine="true"
+ android:layout_marginRight="5dip"
android:text=""
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall" />
+ <TextView
+ android:id="@+id/select_secret_key_master_key_hex"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@string/api_settings_no_key"
+ android:layout_marginRight="5dip" />
</LinearLayout>
diff --git a/OpenPGP-Keychain/src/main/res/menu/key_list_public_multi.xml b/OpenPGP-Keychain/src/main/res/menu/key_list_public_multi.xml
index d30ee5e8f..9df17615e 100644
--- a/OpenPGP-Keychain/src/main/res/menu/key_list_public_multi.xml
+++ b/OpenPGP-Keychain/src/main/res/menu/key_list_public_multi.xml
@@ -6,6 +6,10 @@
android:icon="@drawable/ic_action_select_all"
android:title="@string/menu_select_all" />
<item
+ android:id="@+id/menu_key_list_public_multi_export"
+ android:icon="@drawable/ic_action_import_export"
+ android:title="@string/menu_export_key" />
+ <item
android:id="@+id/menu_key_list_public_multi_encrypt"
android:icon="@drawable/ic_action_secure"
android:title="@string/menu_encrypt_to" />
diff --git a/OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml b/OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml
index a3375c7e8..e7e46815e 100644
--- a/OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml
+++ b/OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml
@@ -6,6 +6,10 @@
android:icon="@drawable/ic_action_select_all"
android:title="@string/menu_select_all" />
<item
+ android:id="@+id/menu_key_list_public_multi_export"
+ android:icon="@drawable/ic_action_import_export"
+ android:title="@string/menu_export_key" />
+ <item
android:id="@+id/menu_key_list_public_multi_delete"
android:icon="@drawable/ic_action_discard"
android:title="@string/menu_delete_key" />
diff --git a/README.md b/README.md
index 14a9055e9..4b997c59f 100644
--- a/README.md
+++ b/README.md
@@ -155,6 +155,14 @@ See http://source.android.com/source/code-style.html
See http://www.androidpolice.com/2009/11/04/auto-formatting-android-xml-files-with-eclipse/
+### Automated syntax check with CheckStyle
+* Paste the tools/checkstyle.xml file to ~/.AndroidStudioPreview/config/codestyles/ (in Linux/Unix)
+ or ~/Library/Preferences/AndroidStudioPreview/codestyles (in Mac OSX)
+* Go to Settings (or Preferences in Mac OS X) > Code Style > Java, select OpenPgpChecker,
+ as well as Code Style > XML and select OpenPgpChecker again.
+* Start code inspection and see the results by selecting Analyze > Inspect Code from Android-Studio
+ or you can directly run checkstyle via cli with .tools/checkstyle. Make sure it's executable first.
+
## Licenses
OpenPGP Kechain is licensed under GPLv3+.
Some parts (older parts and some libraries are Apache License v2, MIT X11 License)
diff --git a/tools/checkstyle b/tools/checkstyle
new file mode 100755
index 000000000..27aabced2
--- /dev/null
+++ b/tools/checkstyle
@@ -0,0 +1 @@
+checkstyle -c tools/checkstyle.xml -r OpenPGP-Keychain/src/main/java 2>&1 | egrep -v 'log4j'
diff --git a/tools/checkstyle.xml b/tools/checkstyle.xml
new file mode 100644
index 000000000..95ef07a90
--- /dev/null
+++ b/tools/checkstyle.xml
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!-- This is a checkstyle configuration file. For descriptions of
+what the following rules do, please see the checkstyle configuration
+page at http://checkstyle.sourceforge.net/config.html -->
+
+<module name="OpenPgpChecker">
+
+ <module name="SuppressionFilter">
+ <property name="file" value="tools/suppressions.xml"/>
+ </module>
+
+ <module name="RegexpSingleline">
+ <!-- Requires a copyright notice in each file.
+ Code intended to be open-sourced may have a multi-line copyright
+ notice, so that this required text appears on the second line:
+ <pre>
+ /*
+ * Copyright 2008 Google Inc.
+ *
+ * (details of open-source license...)
+ </pre>
+ -->
+ <property name="format"
+ value="^(//| \*) Copyright (\([cC]\) )?[\d]{4}(\-[\d]{4})? .*$"/>
+ <property name="minimum" value="1"/>
+ <property name="maximum" value="10"/>
+ <property name="message" value="Copyright is missing or malformed."/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="FileTabCharacter">
+ <!-- Checks that there are no tab characters in the file.
+ -->
+ </module>
+
+ <module name="NewlineAtEndOfFile">
+ <property name="lineSeparator" value="lf"/>
+ </module>
+
+ <module name="RegexpSingleline">
+ <!-- Checks that FIXME is not used in comments. TODO is preferred.
+ -->
+ <property name="format" value="((//.*)|(\*.*))FIXME"/>
+ <property name="message" value='TODO is preferred to FIXME. e.g. "TODO(johndoe): Refactor when v2 is released."'/>
+ </module>
+
+ <!--
+ <module name="RegexpSingleline">
+ <property name="format" value="((//.*)|(\*.*))TODO[^(]"/>
+ <property name="message" value='All TODOs should be named. e.g. "TODO(johndoe): Refactor when v2 is released."'/>
+ </module>
+ -->
+
+ <!-- All Java AST specific tests live under TreeWalker module. -->
+ <module name="TreeWalker">
+
+ <!--
+
+ IMPORT CHECKS
+
+ -->
+
+ <module name="RedundantImport">
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="UnusedImports">
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="ImportOrder">
+ <!-- Checks for out of order import statements. -->
+
+ <property name="severity" value="warning"/>
+ <property name="groups" value="com.google,android,junit,com,net,org,se,java,javax"/>
+ <!-- This ensures that static imports go first. -->
+ <property name="option" value="top"/>
+ <property name="tokens" value="STATIC_IMPORT, IMPORT"/>
+ </module>
+
+ <!--
+
+ JAVADOC CHECKS
+
+ -->
+
+ <!-- Checks for Javadoc comments. -->
+ <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+ <!--
+ <module name="JavadocMethod">
+ <property name="scope" value="protected"/>
+ <property name="severity" value="warning"/>
+ <property name="allowMissingJavadoc" value="true"/>
+ <property name="allowMissingParamTags" value="true"/>
+ <property name="allowMissingReturnTag" value="true"/>
+ <property name="allowMissingThrowsTags" value="true"/>
+ <property name="allowThrowsTagsForSubclasses" value="true"/>
+ <property name="allowUndeclaredRTE" value="true"/>
+ </module>
+
+ <module name="JavadocType">
+ <property name="scope" value="protected"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="JavadocStyle">
+ <property name="severity" value="warning"/>
+ </module>
+ -->
+
+ <!--
+
+ NAMING CHECKS
+
+ -->
+
+ <!-- Item 38 - Adhere to generally accepted naming conventions -->
+
+ <module name="PackageName">
+ <!-- Validates identifiers for package names against the
+ supplied expression. -->
+ <!-- Here the default checkstyle rule restricts package name parts to
+ seven characters, this is not in line with common practice at Google.
+ -->
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="TypeNameCheck">
+ <!-- Validates static, final fields against the
+ expression "^[A-Z][a-zA-Z0-9]*$". -->
+ <metadata name="altname" value="TypeName"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="ConstantNameCheck">
+ <!-- Validates non-private, static, final fields against the supplied
+ public/package final fields "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$". -->
+ <metadata name="altname" value="ConstantName"/>
+ <property name="applyToPublic" value="true"/>
+ <property name="applyToProtected" value="true"/>
+ <property name="applyToPackage" value="true"/>
+ <property name="applyToPrivate" value="false"/>
+ <property name="format" value="^([A-Z_][A-Z0-9]*(_[A-Z0-9]+)*|FLAG_.*)$"/>
+ <message key="name.invalidPattern"
+ value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)."/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="StaticVariableNameCheck">
+ <!-- Validates static, non-final fields against the supplied
+ expression "^[a-z][a-zA-Z0-9]*_?$". -->
+ <metadata name="altname" value="StaticVariableName"/>
+ <property name="applyToPublic" value="true"/>
+ <property name="applyToProtected" value="true"/>
+ <property name="applyToPackage" value="true"/>
+ <property name="applyToPrivate" value="true"/>
+ <property name="format" value="^s[A-Z][a-zA-Z0-9]*_?$"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="MemberNameCheck">
+ <!-- Validates non-static members against the supplied expression. -->
+ <metadata name="altname" value="MemberName"/>
+ <property name="applyToPublic" value="false"/>
+ <property name="applyToProtected" value="true"/>
+ <property name="applyToPackage" value="true"/>
+ <property name="applyToPrivate" value="true"/>
+ <property name="format" value="^m[A-Z][a-zA-Z0-9]*$"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="MemberNameCheck">
+ <!-- Validates non-static members against the supplied expression. -->
+ <metadata name="altname" value="MemberName"/>
+ <property name="applyToPublic" value="true"/>
+ <property name="applyToProtected" value="false"/>
+ <property name="applyToPackage" value="false"/>
+ <property name="applyToPrivate" value="false"/>
+ <property name="format" value="^[a-z]([^A-Z]|$)[a-zA-Z0-9]*$"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="MethodNameCheck">
+ <!-- Validates identifiers for method names. -->
+ <metadata name="altname" value="MethodName"/>
+ <property name="format" value="^[a-z]([^A-Z]|$)[a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="ParameterName">
+ <!-- Validates identifiers for method parameters against the
+ expression "^[a-z][a-zA-Z0-9]*$". -->
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="LocalFinalVariableName">
+ <!-- Validates identifiers for local final variables against the
+ expression "^[a-z][a-zA-Z0-9]*$". -->
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="LocalVariableName">
+ <!-- Validates identifiers for local variables against the
+ expression "^[a-z][a-zA-Z0-9]*$". -->
+ <property name="severity" value="warning"/>
+ </module>
+
+
+ <!--
+
+ LENGTH and CODING CHECKS
+
+ -->
+
+ <module name="LineLength">
+ <!-- Checks if a line is too long. -->
+ <property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="110"/>
+ <property name="severity" value="error"/>
+
+ <!--
+ The default ignore pattern exempts the following elements:
+ - import statements
+ - long URLs inside comments
+ -->
+
+ <property name="ignorePattern"
+ value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
+ default="^(package .*;\s*)|(import .*;\s*)|( *\* *https?://.*)$"/>
+ </module>
+
+ <module name="LeftCurly">
+ <!-- Checks for placement of the left curly brace ('{'). -->
+ <property name="severity" value="warning"/>
+ </module>
+
+ <module name="RightCurly">
+ <!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on
+ the same line. e.g., the following example is fine:
+ <pre>
+ if {
+ ...
+ } else
+ </pre>
+ -->
+ <!-- This next example is not fine:
+ <pre>
+ if {
+ ...
+ }
+ else
+ </pre>
+ -->
+ <property name="option" value="same"/>
+ <property name="severity" value="warning"/>
+ </module>
+
+ <!-- Checks for braces around if and else blocks -->
+ <module name="NeedBraces">
+ <property name="severity" value="warning"/>
+ <property name="tokens" value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
+ </module>
+
+ <module name="UpperEll">
+ <!-- Checks that long constants are defined with an upper ell.-->
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="FallThrough">
+ <!-- Warn about falling through to the next case statement. Similar to
+ javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
+ on the last non-blank line preceding the fallen-into case contains 'fall through' (or
+ some other variants which we don't publicized to promote consistency).
+ -->
+ <property name="reliefPattern"
+ value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
+ <property name="severity" value="error"/>
+ </module>
+
+
+ <!--
+
+ MODIFIERS CHECKS
+
+ -->
+
+ <module name="ModifierOrder">
+ <!-- Warn if modifier order is inconsistent with JLS3 8.1.1, 8.3.1, and
+ 8.4.3. The prescribed order is:
+ public, protected, private, abstract, static, final, transient, volatile,
+ synchronized, native, strictfp
+ -->
+ </module>
+
+
+ <!--
+
+ WHITESPACE CHECKS
+
+ -->
+
+ <module name="WhitespaceAround">
+ <!-- Checks that various tokens are surrounded by whitespace.
+ This includes most binary operators and keywords followed
+ by regular or curly braces.
+ -->
+ <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR,
+ BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
+ EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
+ LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
+ LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
+ MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
+ SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="WhitespaceAfter">
+ <!-- Checks that commas, semicolons and typecasts are followed by
+ whitespace.
+ -->
+ <property name="tokens" value="COMMA, SEMI, TYPECAST"/>
+ </module>
+
+ <module name="NoWhitespaceAfter">
+ <!-- Checks that there is no whitespace after various unary operators.
+ Linebreaks are allowed.
+ -->
+ <property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS,
+ UNARY_PLUS"/>
+ <property name="allowLineBreaks" value="true"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="NoWhitespaceBefore">
+ <!-- Checks that there is no whitespace before various unary operators.
+ Linebreaks are allowed.
+ -->
+ <property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
+ <property name="allowLineBreaks" value="true"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="ParenPad">
+ <!-- Checks that there is no whitespace before close parens or after
+ open parens.
+ -->
+ <property name="severity" value="warning"/>
+ </module>
+
+ </module>
+</module>
+