diff options
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" /> @@ -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> + |