From b09d222f3416d155153a681ed256c46fbf5b386a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 17 Sep 2014 21:51:25 +0200 Subject: package reordering: merge util and helper, there were no real difference; created ui.util for everything related to formatting --- .../keychain/KeychainApplication.java | 4 +- .../keychain/helper/ActionBarHelper.java | 99 ----- .../keychain/helper/ContactHelper.java | 468 --------------------- .../keychain/helper/EmailKeyHelper.java | 101 ----- .../keychain/helper/ExportHelper.java | 159 ------- .../keychain/helper/FileHelper.java | 240 ----------- .../keychain/helper/KeyUpdateHelper.java | 86 ---- .../keychain/helper/OtherHelper.java | 79 ---- .../keychain/helper/Preferences.java | 343 --------------- .../keychain/helper/ShareHelper.java | 101 ----- .../keychain/helper/TlsHelper.java | 133 ------ .../keychain/keyimport/CloudSearch.java | 2 +- .../keychain/keyimport/HkpKeyserver.java | 6 +- .../keychain/keyimport/ImportKeysListEntry.java | 8 +- .../keychain/keyimport/KeybaseKeyserver.java | 4 +- .../keychain/pgp/PgpDecryptVerify.java | 5 +- .../sufficientlysecure/keychain/pgp/PgpHelper.java | 2 +- .../keychain/pgp/PgpImportExport.java | 5 +- .../keychain/pgp/PgpKeyHelper.java | 334 --------------- .../keychain/pgp/PgpKeyOperation.java | 25 +- .../keychain/pgp/PgpSignEncrypt.java | 7 +- .../keychain/pgp/UncachedKeyRing.java | 14 +- .../keychain/provider/ProviderHelper.java | 35 +- .../remote/ui/AccountSettingsActivity.java | 2 +- .../keychain/remote/ui/RemoteServiceActivity.java | 5 +- .../service/ContactSyncAdapterService.java | 12 +- .../keychain/service/KeychainIntentService.java | 13 +- .../service/KeychainIntentServiceHandler.java | 2 +- .../keychain/service/PassphraseCacheService.java | 6 +- .../keychain/ui/CertifyKeyFragment.java | 13 +- .../keychain/ui/CreateKeyFinalFragment.java | 2 +- .../keychain/ui/CreateKeyInputFragment.java | 2 +- .../keychain/ui/DecryptFilesFragment.java | 4 +- .../keychain/ui/DecryptFragment.java | 4 +- .../keychain/ui/DecryptTextActivity.java | 2 +- .../keychain/ui/EditKeyFragment.java | 2 +- .../keychain/ui/EncryptFilesActivity.java | 6 +- .../keychain/ui/EncryptFilesFragment.java | 6 +- .../keychain/ui/EncryptTextActivity.java | 7 +- .../keychain/ui/FirstTimeActivity.java | 2 +- .../keychain/ui/ImportKeysActivity.java | 14 +- .../keychain/ui/ImportKeysCloudFragment.java | 4 +- .../keychain/ui/ImportKeysFileFragment.java | 2 +- .../keychain/ui/ImportKeysListFragment.java | 4 +- .../keychain/ui/ImportKeysQrCodeFragment.java | 2 +- .../keychain/ui/KeyListActivity.java | 6 +- .../keychain/ui/KeyListFragment.java | 10 +- .../keychain/ui/LogDisplayActivity.java | 2 +- .../keychain/ui/PreferencesActivity.java | 2 +- .../keychain/ui/PreferencesKeyServerActivity.java | 2 +- .../keychain/ui/QrCodeActivity.java | 12 +- .../keychain/ui/SelectPublicKeyActivity.java | 2 +- .../keychain/ui/UploadKeyActivity.java | 2 +- .../keychain/ui/ViewCertActivity.java | 8 +- .../keychain/ui/ViewKeyActivity.java | 12 +- .../keychain/ui/ViewKeyCertsFragment.java | 4 +- .../keychain/ui/ViewKeyMainFragment.java | 6 +- .../keychain/ui/ViewKeyShareFragment.java | 13 +- .../keychain/ui/adapter/ImportKeysAdapter.java | 2 +- .../ui/adapter/ImportKeysListCloudLoader.java | 2 +- .../ui/adapter/SelectKeyCursorAdapter.java | 6 +- .../keychain/ui/adapter/SubkeysAdapter.java | 14 +- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 4 +- .../keychain/ui/adapter/UserIdsAdapter.java | 8 +- .../ui/dialog/AddUserIdDialogFragment.java | 2 +- .../ui/dialog/DeleteFileDialogFragment.java | 2 +- .../keychain/ui/dialog/FileDialogFragment.java | 4 +- .../keychain/ui/util/ActionBarHelper.java | 99 +++++ .../keychain/ui/util/FormattingUtils.java | 41 ++ .../keychain/ui/util/Highlighter.java | 57 +++ .../keychain/ui/util/KeyFormattingUtils.java | 333 +++++++++++++++ .../keychain/ui/util/Notify.java | 70 +++ .../keychain/ui/util/QrCodeUtils.java | 76 ++++ .../ui/widget/EncryptKeyCompletionView.java | 12 +- .../keychain/ui/widget/KeySpinner.java | 4 +- .../keychain/util/ContactHelper.java | 467 ++++++++++++++++++++ .../keychain/util/EmailKeyHelper.java | 101 +++++ .../keychain/util/ExportHelper.java | 157 +++++++ .../keychain/util/FileHelper.java | 240 +++++++++++ .../keychain/util/Highlighter.java | 57 --- .../keychain/util/KeyUpdateHelper.java | 83 ++++ .../org/sufficientlysecure/keychain/util/Log.java | 36 ++ .../sufficientlysecure/keychain/util/Notify.java | 70 --- .../keychain/util/Preferences.java | 343 +++++++++++++++ .../keychain/util/QrCodeUtils.java | 75 ---- .../keychain/util/ShareHelper.java | 101 +++++ .../keychain/util/TlsHelper.java | 133 ++++++ 87 files changed, 2515 insertions(+), 2541 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/KeyUpdateHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ShareHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Highlighter.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Highlighter.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Notify.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/QrCodeUtils.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 67b172200..ec9509768 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -31,8 +31,8 @@ import android.provider.ContactsContract; import android.widget.Toast; import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.helper.TlsHelper; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.TlsHelper; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java deleted file mode 100644 index 5866a9890..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ActionBarHelper.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.app.Activity; -import android.support.v7.app.ActionBar; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.R; - -public class ActionBarHelper { - - /** - * Sets custom view on ActionBar for Done/Cancel activities - * - * @param actionBar - * @param firstText - * @param firstDrawableId - * @param firstOnClickListener - * @param secondText - * @param secondDrawableId - * @param secondOnClickListener - */ - public static void setTwoButtonView(ActionBar actionBar, - int firstText, int firstDrawableId, OnClickListener firstOnClickListener, - int secondText, int secondDrawableId, OnClickListener secondOnClickListener) { - - // Inflate the custom action bar view - final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext() - .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); - final View customActionBarView = inflater.inflate( - R.layout.actionbar_custom_view_done_cancel, null); - - 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( - 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( - secondOnClickListener); - - // 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)); - } - - /** - * Sets custom view on ActionBar for Done activities - * - * @param actionBar - * @param firstText - * @param firstOnClickListener - */ - 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 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( - firstOnClickListener); - - // 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); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java deleted file mode 100644 index 6124112d3..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.annotation.TargetApi; -import android.content.ContentProviderOperation; -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -import android.provider.ContactsContract; -import android.util.Patterns; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class ContactHelper { - - public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{ - KeychainContract.KeyRings.USER_ID, - KeychainContract.KeyRings.FINGERPRINT, - KeychainContract.KeyRings.KEY_ID, - KeychainContract.KeyRings.MASTER_KEY_ID, - KeychainContract.KeyRings.EXPIRY, - KeychainContract.KeyRings.IS_REVOKED}; - public static final String[] USER_IDS_PROJECTION = new String[]{ - KeychainContract.UserIds.USER_ID - }; - - public static final String NON_REVOKED_SELECTION = KeychainContract.UserIds.IS_REVOKED + "=0"; - - public static final String[] ID_PROJECTION = new String[]{ContactsContract.RawContacts._ID}; - public static final String[] SOURCE_ID_PROJECTION = new String[]{ContactsContract.RawContacts.SOURCE_ID}; - - public static final String ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION = - ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?"; - public static final String ACCOUNT_TYPE_SELECTION = ContactsContract.RawContacts.ACCOUNT_TYPE + "=?"; - public static final String RAW_CONTACT_AND_MIMETYPE_SELECTION = - ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; - public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?"; - - private static final Map photoCache = new HashMap(); - - public static List getPossibleUserEmails(Context context) { - Set accountMails = getAccountEmails(context); - accountMails.addAll(getMainProfileContactEmails(context)); - // now return the Set (without duplicates) as a List - return new ArrayList(accountMails); - } - - public static List getPossibleUserNames(Context context) { - Set accountMails = getAccountEmails(context); - Set names = getContactNamesFromEmails(context, accountMails); - names.addAll(getMainProfileContactName(context)); - return new ArrayList(names); - } - - /** - * Get emails from AccountManager - * - * @param context - * @return - */ - private static Set getAccountEmails(Context context) { - final Account[] accounts = AccountManager.get(context).getAccounts(); - final Set emailSet = new HashSet(); - for (Account account : accounts) { - if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { - emailSet.add(account.name); - } - } - return emailSet; - } - - /** - * Search for contact names based on a list of emails (to find out the names of the - * device owner based on the email addresses from AccountsManager) - * - * @param context - * @param emails - * @return - */ - private static Set getContactNamesFromEmails(Context context, Set emails) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - Set names = new HashSet(); - for (String email : emails) { - ContentResolver resolver = context.getContentResolver(); - Cursor profileCursor = resolver.query( - ContactsContract.CommonDataKinds.Email.CONTENT_URI, - new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, - ContactsContract.Contacts.DISPLAY_NAME}, - ContactsContract.CommonDataKinds.Email.ADDRESS + "=?", - new String[]{email}, null - ); - if (profileCursor == null) return null; - - Set currNames = new HashSet(); - while (profileCursor.moveToNext()) { - String name = profileCursor.getString(1); - Log.d(Constants.TAG, "name" + name); - if (name != null) { - currNames.add(name); - } - } - profileCursor.close(); - names.addAll(currNames); - } - return names; - } else { - return new HashSet(); - } - } - - /** - * Retrieves the emails of the primary profile contact - * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html - * - * @param context - * @return - */ - private static Set getMainProfileContactEmails(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - ContentResolver resolver = context.getContentResolver(); - Cursor profileCursor = resolver.query( - Uri.withAppendedPath( - ContactsContract.Profile.CONTENT_URI, - ContactsContract.Contacts.Data.CONTENT_DIRECTORY), - new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, - ContactsContract.CommonDataKinds.Email.IS_PRIMARY}, - - // Selects only email addresses - ContactsContract.Contacts.Data.MIMETYPE + "=?", - new String[]{ - ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, - }, - // Show primary rows first. Note that there won't be a primary email address if the - // user hasn't specified one. - ContactsContract.Contacts.Data.IS_PRIMARY + " DESC" - ); - if (profileCursor == null) return null; - - Set emails = new HashSet(); - while (profileCursor.moveToNext()) { - String email = profileCursor.getString(0); - if (email != null) { - emails.add(email); - } - } - profileCursor.close(); - return emails; - } else { - return new HashSet(); - } - } - - /** - * Retrieves the name of the primary profile contact - * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html - * - * @param context - * @return - */ - private static List getMainProfileContactName(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - ContentResolver resolver = context.getContentResolver(); - Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI, - new String[]{ContactsContract.Profile.DISPLAY_NAME}, - null, null, null); - if (profileCursor == null) return null; - - Set names = new HashSet(); - // should only contain one entry! - while (profileCursor.moveToNext()) { - String name = profileCursor.getString(0); - if (name != null) { - names.add(name); - } - } - profileCursor.close(); - return new ArrayList(names); - } else { - return new ArrayList(); - } - } - - public static List getContactMails(Context context) { - ContentResolver resolver = context.getContentResolver(); - Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, - new String[]{ContactsContract.CommonDataKinds.Email.DATA}, - null, null, null); - if (mailCursor == null) return new ArrayList(); - - Set mails = new HashSet(); - while (mailCursor.moveToNext()) { - String email = mailCursor.getString(0); - if (email != null) { - mails.add(email); - } - } - mailCursor.close(); - return new ArrayList(mails); - } - - public static List getContactNames(Context context) { - ContentResolver resolver = context.getContentResolver(); - Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, - new String[]{ContactsContract.Contacts.DISPLAY_NAME}, - null, null, null); - if (cursor == null) return new ArrayList(); - - Set names = new HashSet(); - while (cursor.moveToNext()) { - String name = cursor.getString(0); - if (name != null) { - names.add(name); - } - } - cursor.close(); - return new ArrayList(names); - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - public static Uri dataUriFromContactUri(Context context, Uri contactUri) { - Cursor contactMasterKey = context.getContentResolver().query(contactUri, - new String[]{ContactsContract.Data.DATA2}, null, null, null, null); - if (contactMasterKey != null) { - if (contactMasterKey.moveToNext()) { - return KeychainContract.KeyRings.buildGenericKeyRingUri(contactMasterKey.getLong(0)); - } - contactMasterKey.close(); - } - return null; - } - - public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { - if (fingerprint == null) return null; - if (!photoCache.containsKey(fingerprint)) { - photoCache.put(fingerprint, loadPhotoFromFingerprint(contentResolver, fingerprint)); - } - return photoCache.get(fingerprint); - } - - private static Bitmap loadPhotoFromFingerprint(ContentResolver contentResolver, String fingerprint) { - if (fingerprint == null) return null; - try { - int rawContactId = findRawContactId(contentResolver, fingerprint); - if (rawContactId == -1) return null; - Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); - Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri); - InputStream photoInputStream = - ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri); - if (photoInputStream == null) return null; - return BitmapFactory.decodeStream(photoInputStream); - } catch (Throwable ignored) { - return null; - } - } - - /** - * Write the current Keychain to the contact db - */ - public static void writeKeysToContacts(Context context) { - ContentResolver resolver = context.getContentResolver(); - Set contactFingerprints = getRawContactFingerprints(resolver); - - // Load all Keys from OK - Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), KEYS_TO_CONTACT_PROJECTION, - null, null, null); - if (cursor != null) { - while (cursor.moveToNext()) { - String[] primaryUserId = KeyRing.splitUserId(cursor.getString(0)); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1)); - contactFingerprints.remove(fingerprint); - String keyIdShort = PgpKeyHelper.convertKeyIdToHexShort(cursor.getLong(2)); - long masterKeyId = cursor.getLong(3); - boolean isExpired = !cursor.isNull(4) && new Date(cursor.getLong(4) * 1000).before(new Date()); - boolean isRevoked = cursor.getInt(5) > 0; - int rawContactId = findRawContactId(resolver, fingerprint); - ArrayList ops = new ArrayList(); - - // Do not store expired or revoked keys in contact db - and remove them if they already exist - if (isExpired || isRevoked) { - if (rawContactId != -1) { - resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ID_SELECTION, - new String[]{Integer.toString(rawContactId)}); - } - } else { - - // Create a new rawcontact with corresponding key if it does not exist yet - if (rawContactId == -1) { - insertContact(ops, context, fingerprint); - writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort); - } - - // We always update the display name (which is derived from primary user id) - // and email addresses from user id - writeContactDisplayName(ops, rawContactId, primaryUserId[0]); - writeContactEmail(ops, resolver, rawContactId, masterKeyId); - try { - resolver.applyBatch(ContactsContract.AUTHORITY, ops); - } catch (Exception e) { - Log.w(Constants.TAG, e); - } - } - } - cursor.close(); - } - - // Delete fingerprints that are no longer present in OK - for (String fingerprint : contactFingerprints) { - resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, - new String[]{Constants.ACCOUNT_TYPE, fingerprint}); - } - - } - - /** - * @return a set of all key fingerprints currently present in the contact db - */ - private static Set getRawContactFingerprints(ContentResolver resolver) { - HashSet result = new HashSet(); - Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION, - ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null); - if (fingerprints != null) { - while (fingerprints.moveToNext()) { - result.add(fingerprints.getString(0)); - } - fingerprints.close(); - } - return result; - } - - /** - * This will search the contact db for a raw contact with a given fingerprint - * - * @return raw contact id or -1 if not found - */ - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private static int findRawContactId(ContentResolver resolver, String fingerprint) { - int rawContactId = -1; - Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, ID_PROJECTION, - ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, new String[]{Constants.ACCOUNT_TYPE, fingerprint}, null, null); - if (raw != null) { - if (raw.moveToNext()) { - rawContactId = raw.getInt(0); - } - raw.close(); - } - return rawContactId; - } - - /** - * Creates a empty raw contact with a given fingerprint - */ - private static void insertContact(ArrayList ops, Context context, String fingerprint) { - ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) - .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME) - .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE) - .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint) - .build()); - } - - /** - * Adds a key id to the given raw contact. - *

- * This creates the link to OK in contact details - */ - private static void writeContactKey(ArrayList ops, Context context, int rawContactId, - long masterKeyId, String keyIdShort) { - ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId) - .withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE) - .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyIdShort)) - .withValue(ContactsContract.Data.DATA2, masterKeyId) - .build()); - } - - /** - * Write all known email addresses of a key (derived from user ids) to a given raw contact - */ - private static void writeContactEmail(ArrayList ops, ContentResolver resolver, - int rawContactId, long masterKeyId) { - ops.add(selectByRawContactAndItemType(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI), - rawContactId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE).build()); - Cursor ids = resolver.query(KeychainContract.UserIds.buildUserIdsUri(masterKeyId), - USER_IDS_PROJECTION, NON_REVOKED_SELECTION, null, null); - if (ids != null) { - while (ids.moveToNext()) { - String[] userId = KeyRing.splitUserId(ids.getString(0)); - if (userId[1] != null) { - ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), - rawContactId) - .withValue(ContactsContract.Data.MIMETYPE, - ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) - .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId[1]) - .build()); - } - } - ids.close(); - } - } - - private static void writeContactDisplayName(ArrayList ops, int rawContactId, - String displayName) { - if (displayName != null) { - ops.add(insertOrUpdateForRawContact(ContactsContract.Data.CONTENT_URI, rawContactId, - ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) - .build()); - } - } - - private static ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder, - int rawContactId) { - return rawContactId == -1 ? - builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) : - builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); - } - - private static ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, int rawContactId, - String itemType) { - if (rawContactId == -1) { - return referenceRawContact(ContentProviderOperation.newInsert(uri), rawContactId).withValue( - ContactsContract.Data.MIMETYPE, itemType); - } else { - return selectByRawContactAndItemType(ContentProviderOperation.newUpdate(uri), rawContactId, itemType); - } - } - - private static ContentProviderOperation.Builder selectByRawContactAndItemType( - ContentProviderOperation.Builder builder, int rawContactId, String itemType) { - return builder.withSelection(RAW_CONTACT_AND_MIMETYPE_SELECTION, - new String[]{Integer.toString(rawContactId), itemType}); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java deleted file mode 100644 index 91325ca1f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Messenger; - -import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; -import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; -import org.sufficientlysecure.keychain.keyimport.Keyserver; -import org.sufficientlysecure.keychain.service.KeychainIntentService; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -public class EmailKeyHelper { - - public static void importContacts(Context context, Messenger messenger) { - importAll(context, messenger, ContactHelper.getContactMails(context)); - } - - public static void importAll(Context context, Messenger messenger, List mails) { - Set keys = new HashSet(); - for (String mail : mails) { - keys.addAll(getEmailKeys(context, mail)); - } - importKeys(context, messenger, new ArrayList(keys)); - } - - public static List getEmailKeys(Context context, String mail) { - Set keys = new HashSet(); - - // Try _hkp._tcp SRV record first - String[] mailparts = mail.split("@"); - if (mailparts.length == 2) { - HkpKeyserver hkp = HkpKeyserver.resolve(mailparts[1]); - if (hkp != null) { - keys.addAll(getEmailKeys(mail, hkp)); - } - } - - if (keys.isEmpty()) { - // Most users don't have the SRV record, so ask a default server as well - String server = Preferences.getPreferences(context).getPreferredKeyserver(); - if (server != null) { - HkpKeyserver hkp = new HkpKeyserver(server); - keys.addAll(getEmailKeys(mail, hkp)); - } - } - return new ArrayList(keys); - } - - private static void importKeys(Context context, Messenger messenger, List keys) { - Intent importIntent = new Intent(context, KeychainIntentService.class); - importIntent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); - Bundle importData = new Bundle(); - importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, - new ArrayList(keys)); - importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData); - importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - context.startService(importIntent); - } - - public static List getEmailKeys(String mail, Keyserver keyServer) { - Set keys = new HashSet(); - try { - for (ImportKeysListEntry key : keyServer.search(mail)) { - if (key.isRevoked() || key.isExpired()) continue; - for (String userId : key.getUserIds()) { - if (userId.toLowerCase().contains(mail.toLowerCase(Locale.ENGLISH))) { - keys.add(key); - } - } - } - } catch (Keyserver.QueryFailedException ignored) { - } catch (Keyserver.QueryNeedsRepairException ignored) { - } - return new ArrayList(keys); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java deleted file mode 100644 index f065dbc6d..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.app.ProgressDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.support.v7.app.ActionBarActivity; -import android.widget.Toast; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.File; - -public class ExportHelper { - protected File mExportFile; - - ActionBarActivity mActivity; - - public ExportHelper(ActionBarActivity activity) { - super(); - this.mActivity = activity; - } - - public void deleteKey(Uri dataUri, Handler deleteHandler) { - try { - long masterKeyId = new ProviderHelper(mActivity).getCachedPublicKeyRing(dataUri) - .extractOrGetMasterKeyId(); - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(deleteHandler); - DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - new long[]{ masterKeyId }); - deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog"); - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, "key not found!", e); - } - } - - /** - * Show dialog where to export keys - */ - public void showExportKeysDialog(final long[] masterKeyIds, final File exportFile, - final boolean showSecretCheckbox) { - mExportFile = exportFile; - - String title = null; - if (masterKeyIds == null) { - // export all keys - title = mActivity.getString(R.string.title_export_keys); - } else { - // export only key specified at data uri - title = mActivity.getString(R.string.title_export_key); - } - - String message = mActivity.getString(R.string.specify_file_to_export_to); - String checkMsg = showSecretCheckbox ? - mActivity.getString(R.string.also_export_secret_keys) : null; - - FileHelper.saveFile(new FileHelper.FileDialogCallback() { - @Override - public void onFileSelected(File file, boolean checked) { - mExportFile = file; - exportKeys(masterKeyIds, checked); - } - }, mActivity.getSupportFragmentManager() ,title, message, exportFile, checkMsg); - } - - /** - * Export keys - */ - public void exportKeys(long[] masterKeyIds, boolean exportSecret) { - Log.d(Constants.TAG, "exportKeys started"); - - // Send all information needed to service to export key in other thread - final Intent intent = new Intent(mActivity, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING); - - // fill values for this action - Bundle data = new Bundle(); - - data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFile.getAbsolutePath()); - data.putBoolean(KeychainIntentService.EXPORT_SECRET, exportSecret); - - if (masterKeyIds == null) { - data.putBoolean(KeychainIntentService.EXPORT_ALL, true); - } else { - data.putLongArray(KeychainIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, masterKeyIds); - } - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after exporting is done in KeychainIntentService - KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(mActivity, - mActivity.getString(R.string.progress_exporting), - ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - - int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT); - String toastMessage; - if (exported == 1) { - toastMessage = mActivity.getString(R.string.key_exported); - } else if (exported > 0) { - toastMessage = mActivity.getString(R.string.keys_exported, exported); - } else { - toastMessage = mActivity.getString(R.string.no_keys_exported); - } - Toast.makeText(mActivity, toastMessage, Toast.LENGTH_SHORT).show(); - - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(exportHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - exportHandler.showProgressDialog(mActivity); - - // start service with intent - mActivity.startService(intent); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java deleted file mode 100644 index b640ecb03..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.Point; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.provider.DocumentsContract; -import android.provider.OpenableColumns; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.widget.Toast; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; - -import java.io.File; -import java.text.DecimalFormat; - -public class FileHelper { - - /** - * Checks if external storage is mounted if file is located on external storage - * - * @param file - * @return true if storage is mounted - */ - public static boolean isStorageMounted(String file) { - if (file.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) { - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - return false; - } - } - - return true; - } - - /** - * Opens the preferred installed file manager on Android and shows a toast if no manager is - * installed. - * - * @param fragment - * @param last default selected Uri, not supported by all file managers - * @param mimeType can be text/plain for example - * @param requestCode requestCode used to identify the result coming back from file manager to - * onActivityResult() in your activity - */ - public static void openFile(Fragment fragment, Uri last, String mimeType, int requestCode) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - - intent.setData(last); - intent.setType(mimeType); - - try { - fragment.startActivityForResult(intent, requestCode); - } catch (ActivityNotFoundException e) { - // No compatible file manager was found. - Toast.makeText(fragment.getActivity(), R.string.no_filemanager_installed, - Toast.LENGTH_SHORT).show(); - } - } - - public static void saveFile(final FileDialogCallback callback, final FragmentManager fragmentManager, - final String title, final String message, final File defaultFile, - final String checkMsg) { - // Message is received after file is selected - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == FileDialogFragment.MESSAGE_OKAY) { - callback.onFileSelected( - new File(message.getData().getString(FileDialogFragment.MESSAGE_DATA_FILE)), - message.getData().getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED)); - } - } - }; - - // Create a new Messenger for the communication back - final Messenger messenger = new Messenger(returnHandler); - - DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { - @Override - public void run() { - FileDialogFragment fileDialog = FileDialogFragment.newInstance(messenger, title, message, - defaultFile, checkMsg); - - fileDialog.show(fragmentManager, "fileDialog"); - } - }); - } - - public static void saveFile(Fragment fragment, String title, String message, File defaultFile, int requestCode) { - saveFile(fragment, title, message, defaultFile, requestCode, null); - } - - public static void saveFile(final Fragment fragment, String title, String message, File defaultFile, - final int requestCode, String checkMsg) { - saveFile(new FileDialogCallback() { - @Override - public void onFileSelected(File file, boolean checked) { - Intent intent = new Intent(); - intent.setData(Uri.fromFile(file)); - fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent); - } - }, fragment.getActivity().getSupportFragmentManager(), title, message, defaultFile, checkMsg); - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - public static void openDocument(Fragment fragment, String mimeType, int requestCode) { - openDocument(fragment, mimeType, false, requestCode); - } - - /** - * Opens the storage browser on Android 4.4 or later for opening a file - * - * @param fragment - * @param mimeType can be text/plain for example - * @param multiple allow file chooser to return multiple files - * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your - */ - @TargetApi(Build.VERSION_CODES.KITKAT) - public static void openDocument(Fragment fragment, String mimeType, boolean multiple, int requestCode) { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType(mimeType); - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple); - - fragment.startActivityForResult(intent, requestCode); - } - - /** - * Opens the storage browser on Android 4.4 or later for saving a file - * - * @param fragment - * @param mimeType can be text/plain for example - * @param suggestedName a filename desirable for the file to be saved - * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your - */ - @TargetApi(Build.VERSION_CODES.KITKAT) - public static void saveDocument(Fragment fragment, String mimeType, String suggestedName, int requestCode) { - Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType(mimeType); - intent.putExtra("android.content.extra.SHOW_ADVANCED", true); // Note: This is not documented, but works - intent.putExtra(Intent.EXTRA_TITLE, suggestedName); - fragment.startActivityForResult(intent, requestCode); - } - - public static String getFilename(Context context, Uri uri) { - String filename = null; - try { - Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); - - if (cursor != null) { - if (cursor.moveToNext()) { - filename = cursor.getString(0); - } - cursor.close(); - } - } catch (Exception ignored) { - // This happens in rare cases (eg: document deleted since selection) and should not cause a failure - } - if (filename == null) { - String[] split = uri.toString().split("/"); - filename = split[split.length - 1]; - } - return filename; - } - - public static long getFileSize(Context context, Uri uri) { - return getFileSize(context, uri, -1); - } - - public static long getFileSize(Context context, Uri uri, long def) { - long size = def; - try { - Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null); - - if (cursor != null) { - if (cursor.moveToNext()) { - size = cursor.getLong(0); - } - cursor.close(); - } - } catch (Exception ignored) { - // This happens in rare cases (eg: document deleted since selection) and should not cause a failure - } - return size; - } - - /** - * Retrieve thumbnail of file, document api feature and thus KitKat only - */ - public static Bitmap getThumbnail(Context context, Uri uri, Point size) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - return DocumentsContract.getDocumentThumbnail(context.getContentResolver(), uri, size, null); - } else { - return null; - } - } - - public static String readableFileSize(long size) { - if (size <= 0) return "0"; - final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"}; - int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); - return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; - } - - public static interface FileDialogCallback { - public void onFileSelected(File file, boolean checked); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/KeyUpdateHelper.java deleted file mode 100644 index 0a804fa64..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/KeyUpdateHelper.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2014 Daniel Albert - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.content.Context; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Messenger; - -import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; -import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; -import org.sufficientlysecure.keychain.keyimport.Keyserver; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.ArrayList; -import java.util.List; - -public class KeyUpdateHelper { - - public void updateAllKeys(Context context, KeychainIntentServiceHandler finishedHandler) { - UpdateTask updateTask = new UpdateTask(context, finishedHandler); - updateTask.execute(); - } - - private class UpdateTask extends AsyncTask { - private Context mContext; - private KeychainIntentServiceHandler mHandler; - - public UpdateTask(Context context, KeychainIntentServiceHandler handler) { - this.mContext = context; - this.mHandler = handler; - } - - @Override - protected Void doInBackground(Void... voids) { - ProviderHelper providerHelper = new ProviderHelper(mContext); - List keys = new ArrayList(); - String[] servers = Preferences.getPreferences(mContext).getKeyServers(); - - if (servers != null && servers.length > 0) { - // Load all the fingerprints in the database and prepare to import them - for (String fprint : providerHelper.getAllFingerprints(KeychainContract.KeyRings.buildUnifiedKeyRingsUri())) { - ImportKeysListEntry key = new ImportKeysListEntry(); - key.setFingerprintHex(fprint); - key.setBitStrength(1337); - key.addOrigin(servers[0]); - keys.add(key); - } - - // Start the service and update the keys - Intent importIntent = new Intent(mContext, KeychainIntentService.class); - importIntent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); - - Bundle importData = new Bundle(); - importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, - new ArrayList(keys)); - importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData); - - importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, new Messenger(mHandler)); - - mContext.startService(importIntent); - } - return null; - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java deleted file mode 100644 index f04d84315..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.content.Context; -import android.os.Bundle; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.style.StrikethroughSpan; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.Iterator; -import java.util.Set; - -public class OtherHelper { - - /** - * Logs bundle content to debug for inspecting the content - * - * @param bundle - * @param bundleName - */ - public static void logDebugBundle(Bundle bundle, String bundleName) { - if (Constants.DEBUG) { - if (bundle != null) { - Set ks = bundle.keySet(); - Iterator iterator = ks.iterator(); - - Log.d(Constants.TAG, "Bundle " + bundleName + ":"); - Log.d(Constants.TAG, "------------------------------"); - while (iterator.hasNext()) { - String key = iterator.next(); - Object value = bundle.get(key); - - if (value != null) { - Log.d(Constants.TAG, key + " : " + value.toString()); - } else { - Log.d(Constants.TAG, key + " : null"); - } - } - Log.d(Constants.TAG, "------------------------------"); - } else { - Log.d(Constants.TAG, "Bundle " + bundleName + ": null"); - } - } - } - - public static SpannableStringBuilder strikeOutText(CharSequence text) { - SpannableStringBuilder sb = new SpannableStringBuilder(text); - sb.setSpan(new StrikethroughSpan(), 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); - return sb; - } - - public static int dpToPx(Context context, int dp) { - return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5); - } - - public static int pxToDp(Context context, int px) { - return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java deleted file mode 100644 index bf09997a0..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; - -import org.spongycastle.bcpg.CompressionAlgorithmTags; -import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.openpgp.PGPEncryptedData; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Constants.Pref; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.ListIterator; -import java.util.Vector; - -/** - * Singleton Implementation of a Preference Helper - */ -public class Preferences { - private static Preferences sPreferences; - private SharedPreferences mSharedPreferences; - - public static synchronized Preferences getPreferences(Context context) { - return getPreferences(context, false); - } - - public static synchronized Preferences getPreferences(Context context, boolean forceNew) { - if (sPreferences == null || forceNew) { - sPreferences = new Preferences(context); - } else { - // to make it safe for multiple processes, call getSharedPreferences everytime - sPreferences.updateSharedPreferences(context); - } - return sPreferences; - } - - private Preferences(Context context) { - updateSharedPreferences(context); - } - - public void updateSharedPreferences(Context context) { - // multi-process preferences - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_MULTI_PROCESS); - } else { - mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE); - } - } - - public String getLanguage() { - return mSharedPreferences.getString(Constants.Pref.LANGUAGE, ""); - } - - public void setLanguage(String value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putString(Constants.Pref.LANGUAGE, value); - editor.commit(); - } - - public long getPassphraseCacheTtl() { - int ttl = mSharedPreferences.getInt(Constants.Pref.PASSPHRASE_CACHE_TTL, 180); - // fix the value if it was set to "never" in previous versions, which currently is not - // supported - if (ttl == 0) { - ttl = 180; - } - return (long) ttl; - } - - public void setPassphraseCacheTtl(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.PASSPHRASE_CACHE_TTL, value); - editor.commit(); - } - - public int getDefaultEncryptionAlgorithm() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, - PGPEncryptedData.AES_256); - } - - public void setDefaultEncryptionAlgorithm(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, value); - editor.commit(); - } - - public int getDefaultHashAlgorithm() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, - HashAlgorithmTags.SHA256); - } - - public void setDefaultHashAlgorithm(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, value); - editor.commit(); - } - - public int getDefaultMessageCompression() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, - CompressionAlgorithmTags.ZLIB); - } - - public void setDefaultMessageCompression(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, value); - editor.commit(); - } - - public int getDefaultFileCompression() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, - CompressionAlgorithmTags.UNCOMPRESSED); - } - - public void setDefaultFileCompression(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, value); - editor.commit(); - } - - public boolean getDefaultAsciiArmor() { - return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, false); - } - - public void setDefaultAsciiArmor(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, value); - editor.commit(); - } - - public boolean getShowAdvancedTabs() { - return mSharedPreferences.getBoolean(Pref.SHOW_ADVANCED_TABS, false); - } - - public void setShowAdvancedTabs(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Pref.SHOW_ADVANCED_TABS, value); - editor.commit(); - } - - public boolean getCachedConsolidate() { - return mSharedPreferences.getBoolean(Pref.CACHED_CONSOLIDATE, false); - } - - public void setCachedConsolidate(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Pref.CACHED_CONSOLIDATE, value); - editor.commit(); - } - - public int getCachedConsolidateNumPublics() { - return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_PUBLICS, -1); - } - - public void setCachedConsolidateNumPublics(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Pref.CACHED_CONSOLIDATE_PUBLICS, value); - editor.commit(); - } - - public int getCachedConsolidateNumSecrets() { - return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_SECRETS, -1); - } - - public void setCachedConsolidateNumSecrets(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Pref.CACHED_CONSOLIDATE_SECRETS, value); - editor.commit(); - } - - public boolean isFirstTime() { - return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true); - } - - public boolean useDefaultYubikeyPin() { - return mSharedPreferences.getBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, true); - } - - public void setUseDefaultYubikeyPin(boolean useDefaultYubikeyPin) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, useDefaultYubikeyPin); - editor.commit(); - } - - public void setFirstTime(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.FIRST_TIME, value); - editor.commit(); - } - - public String[] getKeyServers() { - String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS, - Constants.Defaults.KEY_SERVERS); - Vector servers = new Vector(); - String chunks[] = rawData.split(","); - for (String c : chunks) { - String tmp = c.trim(); - if (tmp.length() > 0) { - servers.add(tmp); - } - } - return servers.toArray(chunks); - } - public String getPreferredKeyserver() { - return getKeyServers()[0]; - } - - public void setKeyServers(String[] value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - String rawData = ""; - for (String v : value) { - String tmp = v.trim(); - if (tmp.length() == 0) { - continue; - } - if (!"".equals(rawData)) { - rawData += ","; - } - rawData += tmp; - } - editor.putString(Constants.Pref.KEY_SERVERS, rawData); - editor.commit(); - } - - public void setWriteVersionHeader(boolean conceal) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.WRITE_VERSION_HEADER, conceal); - editor.commit(); - } - - public boolean getWriteVersionHeader() { - return mSharedPreferences.getBoolean(Constants.Pref.WRITE_VERSION_HEADER, false); - } - - public void setSearchKeyserver(boolean searchKeyserver) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver); - editor.commit(); - } - public void setSearchKeybase(boolean searchKeybase) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase); - editor.commit(); - } - - public CloudSearchPrefs getCloudSearchPrefs() { - return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true), - mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true), - getPreferredKeyserver()); - } - - public static class CloudSearchPrefs { - public final boolean searchKeyserver; - public final boolean searchKeybase; - public final String keyserver; - - public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase, String keyserver) { - this.searchKeyserver = searchKeyserver; - this.searchKeybase = searchKeybase; - this.keyserver = keyserver; - } - } - - public void updatePreferences() { - if (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0) != - Constants.Defaults.PREF_VERSION) { - switch (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0)) { - case 1: - // fall through - case 2: - // fall through - case 3: { - // migrate keyserver to hkps - String[] serversArray = getKeyServers(); - ArrayList servers = new ArrayList(Arrays.asList(serversArray)); - ListIterator it = servers.listIterator(); - while (it.hasNext()) { - String server = it.next(); - if (server == null) { - continue; - } - if (server.equals("pool.sks-keyservers.net")) { - // use HKPS! - it.set("hkps://hkps.pool.sks-keyservers.net"); - } else if (server.equals("pgp.mit.edu")) { - // use HKPS! - it.set("hkps://pgp.mit.edu"); - } else if (server.equals("subkeys.pgp.net")) { - // remove, because often down and no HKPS! - it.remove(); - } - - } - setKeyServers(servers.toArray(new String[servers.size()])); - - // migrate old uncompressed constant to new one - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, 0) - == 0x21070001) { - setDefaultFileCompression(CompressionAlgorithmTags.UNCOMPRESSED); - } - - // migrate away from MD5 - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) - == HashAlgorithmTags.MD5) { - setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); - } - } - // fall through - case 4: { - // for compatibility: change from SHA512 to SHA256 - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) - == HashAlgorithmTags.SHA512) { - setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); - } - } - } - - // write new preference version - mSharedPreferences.edit() - .putInt(Constants.Pref.PREF_DEFAULT_VERSION, Constants.Defaults.PREF_VERSION) - .commit(); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ShareHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ShareHelper.java deleted file mode 100644 index 58178e296..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ShareHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.sufficientlysecure.keychain.helper; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.LabeledIntent; -import android.content.pm.ResolveInfo; -import android.os.Build; -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import android.os.Parcelable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -public class ShareHelper { - Context mContext; - - public ShareHelper(Context context) { - mContext = context; - } - - /** - * Create Intent Chooser but exclude OK's EncryptActivity. - *

- * Put together from some stackoverflow posts... - */ - public Intent createChooserExcluding(Intent prototype, String title, String[] activityBlacklist) { - // Produced an empty list on Huawei U8860 with Android Version 4.0.3 and weird results on 2.3 - // TODO: test on 4.1, 4.2, 4.3, only tested on 4.4 - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - return Intent.createChooser(prototype, title); - } - - List targetedShareIntents = new ArrayList(); - - List resInfoList = mContext.getPackageManager().queryIntentActivities(prototype, 0); - List resInfoListFiltered = new ArrayList(); - if (!resInfoList.isEmpty()) { - for (ResolveInfo resolveInfo : resInfoList) { - // do not add blacklisted ones - if (resolveInfo.activityInfo == null || Arrays.asList(activityBlacklist).contains(resolveInfo.activityInfo.name)) - continue; - - resInfoListFiltered.add(resolveInfo); - } - - if (!resInfoListFiltered.isEmpty()) { - // sorting for nice readability - Collections.sort(resInfoListFiltered, new Comparator() { - @Override - public int compare(ResolveInfo first, ResolveInfo second) { - String firstName = first.loadLabel(mContext.getPackageManager()).toString(); - String secondName = second.loadLabel(mContext.getPackageManager()).toString(); - return firstName.compareToIgnoreCase(secondName); - } - }); - - // create the custom intent list - for (ResolveInfo resolveInfo : resInfoListFiltered) { - Intent targetedShareIntent = (Intent) prototype.clone(); - targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName); - targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); - - LabeledIntent lIntent = new LabeledIntent(targetedShareIntent, - resolveInfo.activityInfo.packageName, - resolveInfo.loadLabel(mContext.getPackageManager()), - resolveInfo.activityInfo.icon); - targetedShareIntents.add(lIntent); - } - - // Create chooser with only one Intent in it - Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), title); - // append all other Intents - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{})); - return chooserIntent; - } - - } - - // fallback to Android's default chooser - return Intent.createChooser(prototype, title); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java deleted file mode 100644 index 8bbe73676..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.helper; - -import android.content.res.AssetManager; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.util.HashMap; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; - -public class TlsHelper { - - public static class TlsHelperException extends Exception { - public TlsHelperException(Exception e) { - super(e); - } - } - - private static Map sStaticCA = new HashMap(); - - public static void addStaticCA(String domain, byte[] certificate) { - sStaticCA.put(domain, certificate); - } - - public static void addStaticCA(String domain, AssetManager assetManager, String name) { - try { - InputStream is = assetManager.open(name); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int reads = is.read(); - - while(reads != -1){ - baos.write(reads); - reads = is.read(); - } - - is.close(); - - addStaticCA(domain, baos.toByteArray()); - } catch (IOException e) { - Log.w(Constants.TAG, e); - } - } - - public static URLConnection openConnection(URL url) throws IOException, TlsHelperException { - if (url.getProtocol().equals("https")) { - for (String domain : sStaticCA.keySet()) { - if (url.getHost().endsWith(domain)) { - return openCAConnection(sStaticCA.get(domain), url); - } - } - } - return url.openConnection(); - } - - /** - * Opens a Connection that will only accept certificates signed with a specific CA and skips common name check. - * This is required for some distributed Keyserver networks like sks-keyservers.net - * - * @param certificate The X.509 certificate used to sign the servers certificate - * @param url Connection target - */ - public static HttpsURLConnection openCAConnection(byte[] certificate, URL url) - throws TlsHelperException, IOException { - try { - // Load CA - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate)); - - // Create a KeyStore containing our trusted CAs - String keyStoreType = KeyStore.getDefaultType(); - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - keyStore.load(null, null); - keyStore.setCertificateEntry("ca", ca); - - // Create a TrustManager that trusts the CAs in our KeyStore - String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); - tmf.init(keyStore); - - // Create an SSLContext that uses our TrustManager - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, tmf.getTrustManagers(), null); - - // Tell the URLConnection to use a SocketFactory from our SSLContext - HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); - urlConnection.setSSLSocketFactory(context.getSocketFactory()); - - return urlConnection; - } catch (CertificateException e) { - throw new TlsHelperException(e); - } catch (NoSuchAlgorithmException e) { - throw new TlsHelperException(e); - } catch (KeyStoreException e) { - throw new TlsHelperException(e); - } catch (KeyManagementException e) { - throw new TlsHelperException(e); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java index 27d826c59..255ca1cde 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java @@ -17,7 +17,7 @@ package org.sufficientlysecure.keychain.keyimport; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index a6f1334ea..7f07b8162 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -19,9 +19,9 @@ package org.sufficientlysecure.keychain.keyimport; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.helper.TlsHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.TlsHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.util.Log; import java.io.BufferedWriter; @@ -283,7 +283,7 @@ public class HkpKeyserver extends Keyserver { int bitSize = Integer.parseInt(matcher.group(3)); entry.setBitStrength(bitSize); int algorithmId = Integer.decode(matcher.group(2)); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, bitSize, null)); + entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitSize, null)); // group 1 contains the full fingerprint (v4) or the long key id if available // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index b3df67c0c..b49442ec0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -21,7 +21,7 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; @@ -273,14 +273,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable { } mKeyId = key.getKeyId(); - mKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mKeyId); + mKeyIdHex = KeyFormattingUtils.convertKeyIdToHex(mKeyId); mRevoked = key.isRevoked(); - mFingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); + mFingerprintHex = KeyFormattingUtils.convertFingerprintToHex(key.getFingerprint()); mBitStrength = key.getBitStrength(); mCurveOid = key.getCurveOid(); final int algorithm = key.getAlgorithm(); - mAlgorithm = PgpKeyHelper.getAlgorithmInfo(context, algorithm, mBitStrength, mCurveOid); + mAlgorithm = KeyFormattingUtils.getAlgorithmInfo(context, algorithm, mBitStrength, mCurveOid); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java index a228c3041..2c26ddcc6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java @@ -23,7 +23,7 @@ import com.textuality.keybase.lib.Search; import com.textuality.keybase.lib.User; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; @@ -79,7 +79,7 @@ public class KeybaseKeyserver extends Keyserver { final int bitStrength = match.getBitStrength(); entry.setBitStrength(bitStrength); final int algorithmId = match.getAlgorithmId(); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, bitStrength, null)); + entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitStrength, null)); ArrayList userIds = new ArrayList(); String name = fullName + " "; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index e0e199684..e8f139b22 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -51,6 +51,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.service.results.OperationResult.LogType; import org.sufficientlysecure.keychain.service.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -260,7 +261,7 @@ public class PgpDecryptVerify { long subKeyId = encData.getKeyID(); log.add(LogType.MSG_DC_ASYM, indent, - PgpKeyHelper.convertKeyIdToHex(subKeyId)); + KeyFormattingUtils.convertKeyIdToHex(subKeyId)); CanonicalizedSecretKeyRing secretKeyRing; try { @@ -367,7 +368,7 @@ public class PgpDecryptVerify { PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; long subKeyId = encData.getKeyID(); log.add(LogType.MSG_DC_TRAIL_ASYM, indent, - PgpKeyHelper.convertKeyIdToHex(subKeyId)); + KeyFormattingUtils.convertKeyIdToHex(subKeyId)); } else if (obj instanceof PGPPBEEncryptedData) { log.add(LogType.MSG_DC_TRAIL_SYM, indent); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index db360f810..0a15fd98f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -24,7 +24,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; import java.io.File; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index 1c2c1e78a..26c705347 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -37,6 +37,7 @@ import org.sufficientlysecure.keychain.service.results.OperationResult.LogType; import org.sufficientlysecure.keychain.service.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.service.results.ImportKeyResult; import org.sufficientlysecure.keychain.service.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -144,8 +145,8 @@ public class PgpImportExport { String expectedFp = entry.getExpectedFingerprint(); if(expectedFp != null) { - if(!PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()).equals(expectedFp)) { - Log.d(Constants.TAG, "fingerprint: " + PgpKeyHelper.convertFingerprintToHex(key.getFingerprint())); + if(!KeyFormattingUtils.convertFingerprintToHex(key.getFingerprint()).equals(expectedFp)) { + Log.d(Constants.TAG, "fingerprint: " + KeyFormattingUtils.convertFingerprintToHex(key.getFingerprint())); Log.d(Constants.TAG, "expected fingerprint: " + expectedFp); Log.e(Constants.TAG, "Actual key fingerprint is not the same as expected!"); badKeys += 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java deleted file mode 100644 index 78d1a857f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.pgp; - -import android.content.Context; -import android.graphics.Color; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.style.ForegroundColorSpan; - -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.nist.NISTNamedCurves; -import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; -import org.spongycastle.bcpg.PublicKeyAlgorithmTags; -import org.spongycastle.util.encoders.Hex; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; -import org.sufficientlysecure.keychain.util.Log; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; - -public class PgpKeyHelper { - - public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) { - return getAlgorithmInfo(null, algorithm, keySize, oid); - } - - /** - * Based on OpenPGP Message Format - */ - public static String getAlgorithmInfo(Context context, int algorithm, Integer keySize, String oid) { - String algorithmStr; - - switch (algorithm) { - case PublicKeyAlgorithmTags.RSA_ENCRYPT: - case PublicKeyAlgorithmTags.RSA_GENERAL: - case PublicKeyAlgorithmTags.RSA_SIGN: { - algorithmStr = "RSA"; - break; - } - case PublicKeyAlgorithmTags.DSA: { - algorithmStr = "DSA"; - break; - } - - case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: - case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: { - algorithmStr = "ElGamal"; - break; - } - - case PublicKeyAlgorithmTags.ECDSA: { - if (oid == null) { - return "ECDSA"; - } - String oidName = PgpKeyHelper.getCurveInfo(context, oid); - return "ECDSA (" + oidName + ")"; - } - case PublicKeyAlgorithmTags.ECDH: { - if (oid == null) { - return "ECDH"; - } - String oidName = PgpKeyHelper.getCurveInfo(context, oid); - return "ECDH (" + oidName + ")"; - } - - default: { - if (context != null) { - algorithmStr = context.getResources().getString(R.string.unknown_algorithm); - } else { - algorithmStr = "unknown"; - } - break; - } - } - if (keySize != null && keySize > 0) - return algorithmStr + ", " + keySize + " bit"; - else - return algorithmStr; - } - - public static String getAlgorithmInfo(Algorithm algorithm, Integer keySize, Curve curve) { - return getAlgorithmInfo(null, algorithm, keySize, curve); - } - - /** - * Based on OpenPGP Message Format - */ - public static String getAlgorithmInfo(Context context, Algorithm algorithm, Integer keySize, Curve curve) { - String algorithmStr; - - switch (algorithm) { - case RSA: { - algorithmStr = "RSA"; - break; - } - case DSA: { - algorithmStr = "DSA"; - break; - } - - case ELGAMAL: { - algorithmStr = "ElGamal"; - break; - } - - case ECDSA: { - algorithmStr = "ECDSA"; - if (curve != null) { - algorithmStr += " (" + getCurveInfo(context, curve) + ")"; - } - return algorithmStr; - } - case ECDH: { - algorithmStr = "ECDH"; - if (curve != null) { - algorithmStr += " (" + getCurveInfo(context, curve) + ")"; - } - return algorithmStr; - } - - default: { - if (context != null) { - algorithmStr = context.getResources().getString(R.string.unknown_algorithm); - } else { - algorithmStr = "unknown"; - } - break; - } - } - if (keySize != null && keySize > 0) - return algorithmStr + ", " + keySize + " bit"; - else - return algorithmStr; - } - - /** - * Return name of a curve. These are names, no need for translation - */ - public static String getCurveInfo(Context context, Curve curve) { - switch (curve) { - case NIST_P256: - return "NIST P-256"; - case NIST_P384: - return "NIST P-384"; - case NIST_P521: - return "NIST P-521"; - - /* see SaveKeyringParcel - case BRAINPOOL_P256: - return "Brainpool P-256"; - case BRAINPOOL_P384: - return "Brainpool P-384"; - case BRAINPOOL_P512: - return "Brainpool P-512"; - */ - } - if (context != null) { - return context.getResources().getString(R.string.unknown_algorithm); - } else { - return "unknown"; - } - } - - public static String getCurveInfo(Context context, String oidStr) { - ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidStr); - - String name; - name = NISTNamedCurves.getName(oid); - if (name != null) { - return name; - } - name = TeleTrusTNamedCurves.getName(oid); - if (name != null) { - return name; - } - if (context != null) { - return context.getResources().getString(R.string.unknown_algorithm); - } else { - return "unknown"; - } - } - - /** - * Converts fingerprint to hex - *

- * Fingerprint is shown using lowercase characters. Studies have shown that humans can - * better differentiate between numbers and letters when letters are lowercase. - * - * @param fingerprint - * @return - */ - public static String convertFingerprintToHex(byte[] fingerprint) { - return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); - } - - /** - * Convert key id from long to 64 bit hex string - *

- * V4: "The Key ID is the low-order 64 bits of the fingerprint" - *

- * see http://tools.ietf.org/html/rfc4880#section-12.2 - * - * @param keyId - * @return - */ - public static String convertKeyIdToHex(long keyId) { - long upper = keyId >> 32; - if (upper == 0) { - // this is a short key id - return convertKeyIdToHexShort(keyId); - } - return "0x" + convertKeyIdToHex32bit(keyId >> 32) + convertKeyIdToHex32bit(keyId); - } - - public static String convertKeyIdToHexShort(long keyId) { - return "0x" + convertKeyIdToHex32bit(keyId); - } - - private static String convertKeyIdToHex32bit(long keyId) { - String hexString = Long.toHexString(keyId & 0xffffffffL).toLowerCase(Locale.ENGLISH); - while (hexString.length() < 8) { - hexString = "0" + hexString; - } - return hexString; - } - - - public static SpannableStringBuilder colorizeFingerprint(String fingerprint) { - // split by 4 characters - fingerprint = fingerprint.replaceAll("(.{4})(?!$)", "$1 "); - - // add line breaks to have a consistent "image" that can be recognized - char[] chars = fingerprint.toCharArray(); - chars[24] = '\n'; - fingerprint = String.valueOf(chars); - - SpannableStringBuilder sb = new SpannableStringBuilder(fingerprint); - try { - // for each 4 characters of the fingerprint + 1 space - for (int i = 0; i < fingerprint.length(); i += 5) { - int spanEnd = Math.min(i + 4, fingerprint.length()); - String fourChars = fingerprint.substring(i, spanEnd); - - int raw = Integer.parseInt(fourChars, 16); - byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)}; - int[] color = getRgbForData(bytes); - int r = color[0]; - int g = color[1]; - int b = color[2]; - - // we cannot change black by multiplication, so adjust it to an almost-black grey, - // which will then be brightened to the minimal brightness level - if (r == 0 && g == 0 && b == 0) { - r = 1; - g = 1; - b = 1; - } - - // Convert rgb to brightness - double brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b; - - // If a color is too dark to be seen on black, - // then brighten it up to a minimal brightness. - if (brightness < 80) { - double factor = 80.0 / brightness; - r = Math.min(255, (int) (r * factor)); - g = Math.min(255, (int) (g * factor)); - b = Math.min(255, (int) (b * factor)); - - // If it is too light, then darken it to a respective maximal brightness. - } else if (brightness > 180) { - double factor = 180.0 / brightness; - r = (int) (r * factor); - g = (int) (g * factor); - b = (int) (b * factor); - } - - // Create a foreground color with the 3 digest integers as RGB - // and then converting that int to hex to use as a color - sb.setSpan(new ForegroundColorSpan(Color.rgb(r, g, b)), - i, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE); - } - } catch (Exception e) { - Log.e(Constants.TAG, "Colorization failed", e); - // if anything goes wrong, then just display the fingerprint without colour, - // instead of partially correct colour or wrong colours - return new SpannableStringBuilder(fingerprint); - } - - return sb; - } - - /** - * Converts the given bytes to a unique RGB color using SHA1 algorithm - * - * @param bytes - * @return an integer array containing 3 numeric color representations (Red, Green, Black) - * @throws java.security.NoSuchAlgorithmException - * @throws java.security.DigestException - */ - private static int[] getRgbForData(byte[] bytes) throws NoSuchAlgorithmException, DigestException { - MessageDigest md = MessageDigest.getInstance("SHA1"); - - md.update(bytes); - byte[] digest = md.digest(); - - return new int[]{((int) digest[0] + 256) % 256, - ((int) digest[1] + 256) % 256, - ((int) digest[2] + 256) % 256}; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 63a86e107..0a8774029 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Primes; @@ -405,7 +406,7 @@ public class PgpKeyOperation { */ log.add(LogType.MSG_MF, indent, - PgpKeyHelper.convertKeyIdToHex(wsKR.getMasterKeyId())); + KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); @@ -674,12 +675,12 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mChangeSubKeys.size())); SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i); log.add(LogType.MSG_MF_SUBKEY_CHANGE, - indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); + indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId); if (sKey == null) { log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING, - indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); + indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -687,7 +688,7 @@ public class PgpKeyOperation { if (change.mExpiry != null && change.mExpiry != 0 && new Date(change.mExpiry*1000).before(new Date())) { log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY, - indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); + indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -755,12 +756,12 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / saveParcel.mRevokeSubKeys.size())); long revocation = saveParcel.mRevokeSubKeys.get(i); log.add(LogType.MSG_MF_SUBKEY_REVOKE, - indent, PgpKeyHelper.convertKeyIdToHex(revocation)); + indent, KeyFormattingUtils.convertKeyIdToHex(revocation)); PGPSecretKey sKey = sKR.getSecretKey(revocation); if (sKey == null) { log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING, - indent+1, PgpKeyHelper.convertKeyIdToHex(revocation)); + indent+1, KeyFormattingUtils.convertKeyIdToHex(revocation)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } PGPPublicKey pKey = sKey.getPublicKey(); @@ -780,12 +781,12 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeystrip, (i-1) * (100 / saveParcel.mStripSubKeys.size())); long strip = saveParcel.mStripSubKeys.get(i); log.add(LogType.MSG_MF_SUBKEY_STRIP, - indent, PgpKeyHelper.convertKeyIdToHex(strip)); + indent, KeyFormattingUtils.convertKeyIdToHex(strip)); PGPSecretKey sKey = sKR.getSecretKey(strip); if (sKey == null) { log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING, - indent+1, PgpKeyHelper.convertKeyIdToHex(strip)); + indent+1, KeyFormattingUtils.convertKeyIdToHex(strip)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -810,7 +811,7 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); log.add(LogType.MSG_MF_SUBKEY_NEW, indent, - PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) ); + KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) ); if (add.mExpiry == null) { log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1); @@ -856,7 +857,7 @@ public class PgpKeyOperation { } log.add(LogType.MSG_MF_SUBKEY_NEW_ID, - indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); + indent+1, KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID())); sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); @@ -888,7 +889,7 @@ public class PgpKeyOperation { // noinspection unchecked for (PGPSecretKey sKey : new IterableIterator(sKR.getSecretKeys())) { log.add(LogType.MSG_MF_PASSPHRASE_KEY, indent, - PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); + KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID())); boolean ok = false; @@ -921,7 +922,7 @@ public class PgpKeyOperation { if (!ok) { // for a subkey, it's merely a warning log.add(LogType.MSG_MF_PASSPHRASE_FAIL, indent+1, - PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); + KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID())); continue; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 25840495e..e4df1c447 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -39,6 +39,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.results.OperationResult.LogType; import org.sufficientlysecure.keychain.service.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.service.results.SignEncryptResult; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -389,13 +390,13 @@ public class PgpSignEncrypt { CanonicalizedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); log.add(LogType.MSG_SE_KEY_OK, indent + 1, - PgpKeyHelper.convertKeyIdToHex(id)); + KeyFormattingUtils.convertKeyIdToHex(id)); } catch (PgpGeneralException e) { log.add(LogType.MSG_SE_KEY_WARN, indent + 1, - PgpKeyHelper.convertKeyIdToHex(id)); + KeyFormattingUtils.convertKeyIdToHex(id)); } catch (ProviderHelper.NotFoundException e) { log.add(LogType.MSG_SE_KEY_UNKNOWN, indent + 1, - PgpKeyHelper.convertKeyIdToHex(id)); + KeyFormattingUtils.convertKeyIdToHex(id)); } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 612077e34..cde25c19d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -33,11 +33,11 @@ import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureList; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; -import org.spongycastle.util.Strings; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.results.OperationResult.LogType; import org.sufficientlysecure.keychain.service.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Utf8Util; @@ -261,7 +261,7 @@ public class UncachedKeyRing { public CanonicalizedKeyRing canonicalize(OperationLog log, int indent) { log.add(isSecret() ? LogType.MSG_KC_SECRET : LogType.MSG_KC_PUBLIC, - indent, PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())); + indent, KeyFormattingUtils.convertKeyIdToHex(getMasterKeyId())); indent += 1; // do not accept v3 keys @@ -286,7 +286,7 @@ public class UncachedKeyRing { { log.add(LogType.MSG_KC_MASTER, - indent, PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())); + indent, KeyFormattingUtils.convertKeyIdToHex(masterKey.getKeyID())); indent += 1; PGPPublicKey modified = masterKey; @@ -420,7 +420,7 @@ public class UncachedKeyRing { // never mind any further for public keys, but remove them from secret ones if (isSecret()) { log.add(LogType.MSG_KC_UID_FOREIGN, - indent, PgpKeyHelper.convertKeyIdToHex(certId)); + indent, KeyFormattingUtils.convertKeyIdToHex(certId)); modified = PGPPublicKey.removeCertification(modified, rawUserId, zert); badCerts += 1; } @@ -536,7 +536,7 @@ public class UncachedKeyRing { continue; } log.add(LogType.MSG_KC_SUB, - indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); + indent, KeyFormattingUtils.convertKeyIdToHex(key.getKeyID())); indent += 1; if (Arrays.binarySearch(KNOWN_ALGORITHMS, key.getAlgorithm()) < 0) { @@ -689,7 +689,7 @@ public class UncachedKeyRing { ring = removeSubKey(ring, key); log.add(LogType.MSG_KC_SUB_NO_CERT, - indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); + indent, KeyFormattingUtils.convertKeyIdToHex(key.getKeyID())); indent -= 1; continue; } @@ -737,7 +737,7 @@ public class UncachedKeyRing { public UncachedKeyRing merge(UncachedKeyRing other, OperationLog log, int indent) { log.add(isSecret() ? LogType.MSG_MG_SECRET : LogType.MSG_MG_PUBLIC, - indent, PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())); + indent, KeyFormattingUtils.convertKeyIdToHex(getMasterKeyId())); indent += 1; long masterKeyId = other.getMasterKeyId(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 702da275a..cd8abffcb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -28,10 +28,10 @@ import android.net.Uri; import android.os.RemoteException; import android.support.v4.util.LongSparseArray; -import org.spongycastle.util.Strings; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; @@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpImportExport; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; @@ -344,7 +343,7 @@ public class ProviderHelper { for (CanonicalizedPublicKey key : keyRing.publicKeyIterator()) { long keyId = key.getKeyId(); log(LogLevel.DEBUG, keyId == masterKeyId ? LogType.MSG_IP_MASTER : LogType.MSG_IP_SUBKEY, - PgpKeyHelper.convertKeyIdToHex(keyId) + KeyFormattingUtils.convertKeyIdToHex(keyId) ); mIndent += 1; @@ -480,7 +479,7 @@ public class ProviderHelper { if (cert.verifySignature(masterKey, rawUserId)) { item.trustedCerts.add(cert); log(LogLevel.INFO, LogType.MSG_IP_UID_CERT_GOOD, - PgpKeyHelper.convertKeyIdToHexShort(trustedKey.getKeyId()) + KeyFormattingUtils.convertKeyIdToHexShort(trustedKey.getKeyId()) ); } else { log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_BAD); @@ -491,7 +490,7 @@ public class ProviderHelper { } catch (PgpGeneralException e) { log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_ERROR, - PgpKeyHelper.convertKeyIdToHex(cert.getKeyId())); + KeyFormattingUtils.convertKeyIdToHex(cert.getKeyId())); } } @@ -592,7 +591,7 @@ public class ProviderHelper { private int saveCanonicalizedSecretKeyRing(CanonicalizedSecretKeyRing keyRing) { long masterKeyId = keyRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); + log(LogLevel.START, LogType.MSG_IS, KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); mIndent += 1; try { @@ -638,28 +637,28 @@ public class ProviderHelper { switch (mode) { case PASSPHRASE: log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK, - PgpKeyHelper.convertKeyIdToHex(id) + KeyFormattingUtils.convertKeyIdToHex(id) ); break; case PASSPHRASE_EMPTY: log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_EMPTY, - PgpKeyHelper.convertKeyIdToHex(id) + KeyFormattingUtils.convertKeyIdToHex(id) ); break; case GNU_DUMMY: log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_STRIPPED, - PgpKeyHelper.convertKeyIdToHex(id) + KeyFormattingUtils.convertKeyIdToHex(id) ); break; case DIVERT_TO_CARD: log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_DIVERT, - PgpKeyHelper.convertKeyIdToHex(id) + KeyFormattingUtils.convertKeyIdToHex(id) ); break; } } else { log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT, - PgpKeyHelper.convertKeyIdToHex(id) + KeyFormattingUtils.convertKeyIdToHex(id) ); } } @@ -691,7 +690,7 @@ public class ProviderHelper { try { long masterKeyId = publicRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IP, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); + log(LogLevel.START, LogType.MSG_IP, KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); mIndent += 1; if (publicRing.isSecret()) { @@ -783,7 +782,7 @@ public class ProviderHelper { try { long masterKeyId = secretRing.getMasterKeyId(); - log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); + log(LogLevel.START, LogType.MSG_IS, KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); mIndent += 1; if ( ! secretRing.isSecret()) { @@ -816,7 +815,7 @@ public class ProviderHelper { if (Arrays.hashCode(secretRing.getEncoded()) == Arrays.hashCode(oldSecretRing.getEncoded())) { log(LogLevel.OK, LogType.MSG_IS_SUCCESS_IDENTICAL, - PgpKeyHelper.convertKeyIdToHex(masterKeyId) ); + KeyFormattingUtils.convertKeyIdToHex(masterKeyId) ); return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog, null); } } catch (NotFoundException e) { @@ -911,7 +910,7 @@ public class ProviderHelper { return false; } ring = new ParcelableKeyRing(cursor.getBlob(0), - PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1))); + KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1))); cursor.moveToNext(); return true; } @@ -973,7 +972,7 @@ public class ProviderHelper { return false; } ring = new ParcelableKeyRing(cursor.getBlob(0), - PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1))); + KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1))); cursor.moveToNext(); return true; } @@ -1325,7 +1324,7 @@ public class ProviderHelper { int fingerprintColumn = cursor.getColumnIndex(KeyRings.FINGERPRINT); while(cursor.moveToNext()) { fingerprints.add( - PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(fingerprintColumn)) + KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(fingerprintColumn)) ); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java index 231b26409..26063fc66 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java @@ -27,7 +27,7 @@ import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.service.results.OperationResult; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java index 6a96a831c..6a8a5a03e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java @@ -22,8 +22,6 @@ import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.support.v7.app.ActionBarActivity; import android.text.Spannable; import android.text.SpannableString; @@ -38,13 +36,12 @@ import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.htmltextview.HtmlTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index fbe914b78..447f413ef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -22,26 +22,16 @@ import android.app.Service; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; import android.content.ContentResolver; -import android.content.Context; import android.content.Intent; import android.content.SyncResult; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.provider.ContactsContract; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.KeychainApplication; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; -import org.sufficientlysecure.keychain.helper.EmailKeyHelper; +import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; -import java.util.concurrent.atomic.AtomicBoolean; - public class ContactSyncAdapterService extends Service { private class ContactSyncAdapter extends AbstractThreadedSyncAdapter { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 78464a5aa..94ea20328 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -29,9 +29,8 @@ import android.os.RemoteException; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; -import org.sufficientlysecure.keychain.helper.OtherHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.FileHelper; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver; @@ -242,7 +241,7 @@ public class KeychainIntentService extends IntentService implements Progressable return; } - OtherHelper.logDebugBundle(data, "EXTRA_DATA"); + Log.logDebugBundle(data, "EXTRA_DATA"); String action = intent.getAction(); @@ -328,7 +327,7 @@ public class KeychainIntentService extends IntentService implements Progressable } - OtherHelper.logDebugBundle(resultData, "resultData"); + Log.logDebugBundle(resultData, "resultData"); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { @@ -377,7 +376,7 @@ public class KeychainIntentService extends IntentService implements Progressable finalizeDecryptOutputStream(data, resultData, outStream); - OtherHelper.logDebugBundle(resultData, "resultData"); + Log.logDebugBundle(resultData, "resultData"); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { @@ -421,7 +420,7 @@ public class KeychainIntentService extends IntentService implements Progressable resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult); /* Output */ - OtherHelper.logDebugBundle(resultData, "resultData"); + Log.logDebugBundle(resultData, "resultData"); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java index 940777458..0e646fca1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java @@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; public class KeychainIntentServiceHandler extends Handler { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 0ac1812f3..949ce0f0b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -37,15 +37,11 @@ import android.os.RemoteException; import android.support.v4.app.NotificationCompat; import android.support.v4.util.LongSparseArray; -import org.spongycastle.bcpg.S2K; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; -import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 81fa98e7a..5aadaa2a2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -48,13 +48,12 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.results.OperationResult; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.results.OperationResult.LogLevel; import org.sufficientlysecure.keychain.service.results.OperationResult.LogType; @@ -64,7 +63,7 @@ import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner; import org.sufficientlysecure.keychain.ui.widget.KeySpinner; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.ArrayList; @@ -238,15 +237,15 @@ public class CertifyKeyFragment extends LoaderFragment if (data.moveToFirst()) { mPubKeyId = data.getLong(INDEX_MASTER_KEY_ID); mCertifyKeySpinner.setHiddenMasterKeyId(mPubKeyId); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(mPubKeyId); + String keyIdStr = KeyFormattingUtils.convertKeyIdToHex(mPubKeyId); mInfoKeyId.setText(keyIdStr); String mainUserId = data.getString(INDEX_USER_ID); mInfoPrimaryUserId.setText(mainUserId); byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); - mInfoFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob); + mInfoFingerprint.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint)); } break; case LOADER_ID_USER_IDS: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index c6edc47a1..38c8eb464 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -34,7 +34,7 @@ import android.widget.TextView; import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.service.KeychainIntentService; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java index ef5a3b145..cd754694b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -32,7 +32,7 @@ import android.widget.AutoCompleteTextView; import android.widget.EditText; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.util.ContactHelper; import java.util.regex.Matcher; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index baf72bad2..deb994808 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -35,14 +35,14 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; +import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.io.File; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index ff20d0e98..7298ff6d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -35,7 +35,7 @@ import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; public abstract class DecryptFragment extends Fragment { @@ -121,7 +121,7 @@ public abstract class DecryptFragment extends Fragment { mUserIdRest.setText(userIdSplit[1]); } else { mUserIdRest.setText(getString(R.string.label_key_id) + ": " - + PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId)); + + KeyFormattingUtils.convertKeyIdToHex(mSignatureKeyId)); } switch (signatureResult.getStatus()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java index 5d46b351b..1bbe58f07 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java @@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.regex.Matcher; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 0911a98ae..641e6e17e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -39,7 +39,7 @@ import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index e8a0f4689..9b97b6693 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -31,15 +31,15 @@ import android.view.MenuItem; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.helper.ShareHelper; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.ShareHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.ArrayList; import java.util.HashSet; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 477083903..23021ce44 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -36,8 +36,8 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; -import org.sufficientlysecure.keychain.helper.OtherHelper; +import org.sufficientlysecure.keychain.ui.util.FormattingUtils; +import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import java.io.File; @@ -282,7 +282,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt delInputUri(position); } }); - int px = OtherHelper.dpToPx(getActivity(), 48); + int px = FormattingUtils.dpToPx(getActivity(), 48); if (!thumbnailCache.containsKey(inputUri)) { thumbnailCache.put(inputUri, FileHelper.getThumbnail(getActivity(), inputUri, new Point(px, px))); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index e86790835..24e2c7f7b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -32,15 +32,14 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.helper.ShareHelper; -import org.sufficientlysecure.keychain.nfc.NfcActivity; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.ShareHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.ArrayList; import java.util.HashSet; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java index 7b608a0a2..2df5ed1f6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java @@ -25,7 +25,7 @@ import android.view.Window; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; public class FirstTimeActivity extends ActionBarActivity { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 518a8046a..6298f96c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -39,11 +39,11 @@ import android.view.ViewGroup; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; -import org.sufficientlysecure.keychain.helper.OtherHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.ui.util.FormattingUtils; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.results.OperationResult; @@ -52,7 +52,7 @@ import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.io.IOException; import java.util.ArrayList; @@ -183,7 +183,7 @@ public class ImportKeysActivity extends ActionBarActivity { } else if (extras.containsKey(EXTRA_KEY_ID)) { long keyId = extras.getLong(EXTRA_KEY_ID, 0); if (keyId != 0) { - query = PgpKeyHelper.convertKeyIdToHex(keyId); + query = KeyFormattingUtils.convertKeyIdToHex(keyId); } } @@ -340,14 +340,14 @@ public class ImportKeysActivity extends ActionBarActivity { public void resizeViewPager(int dp) { ViewGroup.LayoutParams params = mViewPager.getLayoutParams(); - params.height = OtherHelper.dpToPx(this, dp); + params.height = FormattingUtils.dpToPx(this, dp); // update layout after operations mSlidingTabLayout.setViewPager(mViewPager); } public int getViewPagerHeight() { ViewGroup.LayoutParams params = mViewPager.getLayoutParams(); - return OtherHelper.pxToDp(this, params.height); + return FormattingUtils.pxToDp(this, params.height); } private String getFingerprintFromUri(Uri dataUri) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java index 6b4b833c6..40a60f119 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java @@ -35,8 +35,8 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.ContactHelper; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; import java.util.List; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java index cb53647f6..a1c49b569 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java @@ -29,7 +29,7 @@ import android.view.ViewGroup; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.helper.FileHelper; +import org.sufficientlysecure.keychain.util.FileHelper; import java.util.Locale; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index f1f234461..4dbe23863 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -31,7 +31,7 @@ import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; @@ -41,7 +41,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListCloudLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index 5f54daa3c..a52737979 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -32,7 +32,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.Locale; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 4c94d25be..24c15046a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -28,8 +28,8 @@ import android.view.MenuItem; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ExportHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.ExportHelper; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -37,7 +37,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.results.OperationResult; import org.sufficientlysecure.keychain.service.results.ConsolidateResult; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.io.IOException; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 33efc549b..e409e1bc8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -56,17 +56,17 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ExportHelper; -import org.sufficientlysecure.keychain.helper.KeyUpdateHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.ExportHelper; +import org.sufficientlysecure.keychain.util.KeyUpdateHelper; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.widget.ListAwareSwipeRefreshLayout; -import org.sufficientlysecure.keychain.util.Highlighter; +import org.sufficientlysecure.keychain.ui.util.Highlighter; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.Date; import java.util.HashMap; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java index 248b8976a..4a2b88518 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java @@ -23,7 +23,7 @@ import android.support.v7.app.ActionBarActivity; import android.view.View; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; public class LogDisplayActivity extends ActionBarActivity { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java index dd4fedf9d..550caf7a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java @@ -33,7 +33,7 @@ import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference; import java.util.List; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java index 520f0b6a5..2a8ef171c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java @@ -28,7 +28,7 @@ import android.view.ViewGroup; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.ui.widget.Editor; import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java index a906dfa97..6193be297 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java @@ -25,14 +25,14 @@ import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; -import org.sufficientlysecure.keychain.util.Notify.Style; -import org.sufficientlysecure.keychain.util.QrCodeUtils; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; +import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; public class QrCodeActivity extends ActionBarActivity { @@ -85,7 +85,7 @@ public class QrCodeActivity extends ActionBarActivity { finish(); } - String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob); String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; mFingerprintQrCode.setImageBitmap(QrCodeUtils.getQRCodeBitmap(qrCodeContent, QR_CODE_SIZE)); } catch (ProviderHelper.NotFoundException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java index 7be02da50..148aa7d67 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java @@ -25,7 +25,7 @@ import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; public class SelectPublicKeyActivity extends ActionBarActivity { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java index 9d448c1e5..497486a5e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java @@ -34,7 +34,7 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.service.KeychainIntentService; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 92f38a44c..a45d1476c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -36,7 +36,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; @@ -120,7 +120,7 @@ public class ViewCertActivity extends ActionBarActivity @Override public void onLoadFinished(Loader loader, Cursor data) { if (data.moveToFirst()) { - String signeeKey = PgpKeyHelper.convertKeyIdToHex(data.getLong(INDEX_MASTER_KEY_ID)); + String signeeKey = KeyFormattingUtils.convertKeyIdToHex(data.getLong(INDEX_MASTER_KEY_ID)); mSigneeKey.setText(signeeKey); String signeeUid = data.getString(INDEX_USER_ID); @@ -130,7 +130,7 @@ public class ViewCertActivity extends ActionBarActivity mCreation.setText(DateFormat.getDateFormat(getApplicationContext()).format(creationDate)); mCertifierKeyId = data.getLong(INDEX_KEY_ID_CERTIFIER); - String certifierKey = PgpKeyHelper.convertKeyIdToHex(mCertifierKeyId); + String certifierKey = KeyFormattingUtils.convertKeyIdToHex(mCertifierKeyId); mCertifierKey.setText(certifierKey); String certifierUid = data.getString(INDEX_SIGNER_UID); @@ -167,7 +167,7 @@ public class ViewCertActivity extends ActionBarActivity mStatus.setTextColor(getResources().getColor(R.color.black)); } - String algorithmStr = PgpKeyHelper.getAlgorithmInfo(this, sig.getKeyAlgorithm(), null, null); + String algorithmStr = KeyFormattingUtils.getAlgorithmInfo(this, sig.getKeyAlgorithm(), null, null); mAlgorithm.setText(algorithmStr); mRowReason.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 805fc8753..fa20bc3bc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -48,11 +48,11 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; -import org.sufficientlysecure.keychain.helper.ExportHelper; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.ContactHelper; +import org.sufficientlysecure.keychain.util.ExportHelper; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -61,7 +61,7 @@ import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout.TabColorizer; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.Date; import java.util.HashMap; @@ -470,7 +470,7 @@ public class ViewKeyActivity extends ActionBarActivity implements // get key id from MASTER_KEY_ID long masterKeyId = data.getLong(INDEX_UNIFIED_MASTER_KEY_ID); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(masterKeyId); + String keyIdStr = KeyFormattingUtils.convertKeyIdToHex(masterKeyId); getSupportActionBar().setSubtitle(keyIdStr); boolean isRevoked = data.getInt(INDEX_UNIFIED_IS_REVOKED) > 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java index 786537b25..9edb29989 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java @@ -37,7 +37,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; @@ -219,7 +219,7 @@ public class ViewKeyCertsFragment extends LoaderFragment TextView wSignerName = (TextView) view.findViewById(R.id.signerName); TextView wSignStatus = (TextView) view.findViewById(R.id.signStatus); - String signerKeyId = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexSignerKeyId)); + String signerKeyId = KeyFormattingUtils.convertKeyIdToHex(cursor.getLong(mIndexSignerKeyId)); String[] userId = KeyRing.splitUserId(cursor.getString(mIndexSignerUserId)); if (userId[0] != null) { wSignerName.setText(userId[0]); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index c20b13764..2d7bb07cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -36,7 +36,7 @@ import android.widget.ListView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -46,7 +46,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.Date; @@ -318,7 +318,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements byte[] blob = (byte[]) providerHelper.getGenericData( KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob); Intent queryIntent = new Intent(getActivity(), ImportKeysActivity.class); queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index 72242a6cc..4f66a7efc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -43,7 +43,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -51,12 +51,11 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Notify; -import org.sufficientlysecure.keychain.util.QrCodeUtils; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.ArrayList; import edu.cmu.cylab.starslinger.exchange.ExchangeActivity; import edu.cmu.cylab.starslinger.exchange.ExchangeConfig; @@ -180,7 +179,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements byte[] data = (byte[]) providerHelper.getGenericData( KeyRings.buildUnifiedKeyRingUri(dataUri), Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(data); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(data); if (!toClipboard) { content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { @@ -375,8 +374,8 @@ public class ViewKeyShareFragment extends LoaderFragment implements if (data.moveToFirst()) { byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); - mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob); + mFingerprint.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint)); loadQrCode(fingerprint); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 1fed58721..5abbdcc05 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -33,7 +33,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.util.Highlighter; +import org.sufficientlysecure.keychain.ui.util.Highlighter; import java.util.ArrayList; import java.util.Iterator; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java index d39feda76..0332e8882 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java @@ -21,7 +21,7 @@ import android.content.Context; import android.support.v4.content.AsyncTaskLoader; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.CloudSearch; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index 0e2177568..53e4e0fd6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -29,9 +29,9 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.util.Highlighter; +import org.sufficientlysecure.keychain.ui.util.Highlighter; import java.util.Date; @@ -128,7 +128,7 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { } long masterKeyId = cursor.getLong(mIndexMasterKeyId); - h.keyId.setText(PgpKeyHelper.convertKeyIdToHex(masterKeyId)); + h.keyId.setText(KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); boolean enabled = true; if (cursor.getInt(mIndexRevoked) != 0) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 38ba675e9..99ceeb929 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -34,9 +34,9 @@ import android.widget.ImageView; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.OtherHelper; +import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; @@ -145,12 +145,12 @@ public class SubkeysAdapter extends CursorAdapter { deleteImage.setVisibility(View.GONE); long keyId = cursor.getLong(INDEX_KEY_ID); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(keyId); + String keyIdStr = KeyFormattingUtils.convertKeyIdToHex(keyId); vKeyId.setText(keyIdStr); // may be set with additional "stripped" later on SpannableStringBuilder algorithmStr = new SpannableStringBuilder(); - algorithmStr.append(PgpKeyHelper.getAlgorithmInfo( + algorithmStr.append(KeyFormattingUtils.getAlgorithmInfo( context, cursor.getInt(INDEX_ALGORITHM), cursor.getInt(INDEX_KEY_SIZE), @@ -259,9 +259,9 @@ public class SubkeysAdapter extends CursorAdapter { // if key is expired or revoked, strike through text boolean isInvalid = isRevoked || isExpired; if (isInvalid) { - vKeyId.setText(OtherHelper.strikeOutText(vKeyId.getText())); - vKeyDetails.setText(OtherHelper.strikeOutText(vKeyDetails.getText())); - vKeyExpiry.setText(OtherHelper.strikeOutText(vKeyExpiry.getText())); + vKeyId.setText(FormattingUtils.strikeOutText(vKeyId.getText())); + vKeyDetails.setText(FormattingUtils.strikeOutText(vKeyDetails.getText())); + vKeyExpiry.setText(FormattingUtils.strikeOutText(vKeyExpiry.getText())); } vKeyId.setEnabled(!isInvalid); vKeyDetails.setEnabled(!isInvalid); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java index d50318fb4..009e4c620 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -30,7 +30,7 @@ import android.widget.TextView; import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import java.util.Calendar; @@ -96,7 +96,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.app.Activity; +import android.support.v7.app.ActionBar; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; + +public class ActionBarHelper { + + /** + * Sets custom view on ActionBar for Done/Cancel activities + * + * @param actionBar + * @param firstText + * @param firstDrawableId + * @param firstOnClickListener + * @param secondText + * @param secondDrawableId + * @param secondOnClickListener + */ + public static void setTwoButtonView(ActionBar actionBar, + int firstText, int firstDrawableId, OnClickListener firstOnClickListener, + int secondText, int secondDrawableId, OnClickListener secondOnClickListener) { + + // Inflate the custom action bar view + final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext() + .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater.inflate( + R.layout.actionbar_custom_view_done_cancel, null); + + 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( + 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( + secondOnClickListener); + + // 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)); + } + + /** + * Sets custom view on ActionBar for Done activities + * + * @param actionBar + * @param firstText + * @param firstOnClickListener + */ + 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 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( + firstOnClickListener); + + // 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); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java new file mode 100644 index 000000000..3f84bf490 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.StrikethroughSpan; + +public class FormattingUtils { + + public static SpannableStringBuilder strikeOutText(CharSequence text) { + SpannableStringBuilder sb = new SpannableStringBuilder(text); + sb.setSpan(new StrikethroughSpan(), 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + return sb; + } + + public static int dpToPx(Context context, int dp) { + return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5); + } + + public static int pxToDp(Context context, int px) { + return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Highlighter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Highlighter.java new file mode 100644 index 000000000..69338aa3e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Highlighter.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Thialfihar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.content.Context; +import android.text.Spannable; +import android.text.style.ForegroundColorSpan; + +import org.sufficientlysecure.keychain.R; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Highlighter { + private Context mContext; + private String mQuery; + + public Highlighter(Context context, String query) { + mContext = context; + mQuery = query; + } + + public Spannable highlight(String text) { + Spannable highlight = Spannable.Factory.getInstance().newSpannable(text); + + if (mQuery == null) { + return highlight; + } + + Pattern pattern = Pattern.compile("(?i)(" + mQuery.trim().replaceAll("\\s+", "|") + ")"); + Matcher matcher = pattern.matcher(text); + while (matcher.find()) { + highlight.setSpan( + new ForegroundColorSpan(mContext.getResources().getColor(R.color.emphasis)), + matcher.start(), + matcher.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + return highlight; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java new file mode 100644 index 000000000..dd389a587 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2010-2014 Thialfihar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.content.Context; +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.bcpg.PublicKeyAlgorithmTags; +import org.spongycastle.util.encoders.Hex; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; +import org.sufficientlysecure.keychain.util.Log; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; + +public class KeyFormattingUtils { + + public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) { + return getAlgorithmInfo(null, algorithm, keySize, oid); + } + + /** + * Based on OpenPGP Message Format + */ + public static String getAlgorithmInfo(Context context, int algorithm, Integer keySize, String oid) { + String algorithmStr; + + switch (algorithm) { + case PublicKeyAlgorithmTags.RSA_ENCRYPT: + case PublicKeyAlgorithmTags.RSA_GENERAL: + case PublicKeyAlgorithmTags.RSA_SIGN: { + algorithmStr = "RSA"; + break; + } + case PublicKeyAlgorithmTags.DSA: { + algorithmStr = "DSA"; + break; + } + + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: + case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: { + algorithmStr = "ElGamal"; + break; + } + + case PublicKeyAlgorithmTags.ECDSA: { + if (oid == null) { + return "ECDSA"; + } + String oidName = KeyFormattingUtils.getCurveInfo(context, oid); + return "ECDSA (" + oidName + ")"; + } + case PublicKeyAlgorithmTags.ECDH: { + if (oid == null) { + return "ECDH"; + } + String oidName = KeyFormattingUtils.getCurveInfo(context, oid); + return "ECDH (" + oidName + ")"; + } + + default: { + if (context != null) { + algorithmStr = context.getResources().getString(R.string.unknown_algorithm); + } else { + algorithmStr = "unknown"; + } + break; + } + } + if (keySize != null && keySize > 0) + return algorithmStr + ", " + keySize + " bit"; + else + return algorithmStr; + } + + public static String getAlgorithmInfo(Algorithm algorithm, Integer keySize, Curve curve) { + return getAlgorithmInfo(null, algorithm, keySize, curve); + } + + /** + * Based on OpenPGP Message Format + */ + public static String getAlgorithmInfo(Context context, Algorithm algorithm, Integer keySize, Curve curve) { + String algorithmStr; + + switch (algorithm) { + case RSA: { + algorithmStr = "RSA"; + break; + } + case DSA: { + algorithmStr = "DSA"; + break; + } + + case ELGAMAL: { + algorithmStr = "ElGamal"; + break; + } + + case ECDSA: { + algorithmStr = "ECDSA"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + case ECDH: { + algorithmStr = "ECDH"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + + default: { + if (context != null) { + algorithmStr = context.getResources().getString(R.string.unknown_algorithm); + } else { + algorithmStr = "unknown"; + } + break; + } + } + if (keySize != null && keySize > 0) + return algorithmStr + ", " + keySize + " bit"; + else + return algorithmStr; + } + + /** + * Return name of a curve. These are names, no need for translation + */ + public static String getCurveInfo(Context context, Curve curve) { + switch (curve) { + case NIST_P256: + return "NIST P-256"; + case NIST_P384: + return "NIST P-384"; + case NIST_P521: + return "NIST P-521"; + + /* see SaveKeyringParcel + case BRAINPOOL_P256: + return "Brainpool P-256"; + case BRAINPOOL_P384: + return "Brainpool P-384"; + case BRAINPOOL_P512: + return "Brainpool P-512"; + */ + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + + public static String getCurveInfo(Context context, String oidStr) { + ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidStr); + + String name; + name = NISTNamedCurves.getName(oid); + if (name != null) { + return name; + } + name = TeleTrusTNamedCurves.getName(oid); + if (name != null) { + return name; + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + + /** + * Converts fingerprint to hex + *

+ * Fingerprint is shown using lowercase characters. Studies have shown that humans can + * better differentiate between numbers and letters when letters are lowercase. + * + * @param fingerprint + * @return + */ + public static String convertFingerprintToHex(byte[] fingerprint) { + return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); + } + + /** + * Convert key id from long to 64 bit hex string + *

+ * V4: "The Key ID is the low-order 64 bits of the fingerprint" + *

+ * see http://tools.ietf.org/html/rfc4880#section-12.2 + * + * @param keyId + * @return + */ + public static String convertKeyIdToHex(long keyId) { + long upper = keyId >> 32; + if (upper == 0) { + // this is a short key id + return convertKeyIdToHexShort(keyId); + } + return "0x" + convertKeyIdToHex32bit(keyId >> 32) + convertKeyIdToHex32bit(keyId); + } + + public static String convertKeyIdToHexShort(long keyId) { + return "0x" + convertKeyIdToHex32bit(keyId); + } + + private static String convertKeyIdToHex32bit(long keyId) { + String hexString = Long.toHexString(keyId & 0xffffffffL).toLowerCase(Locale.ENGLISH); + while (hexString.length() < 8) { + hexString = "0" + hexString; + } + return hexString; + } + + public static SpannableStringBuilder colorizeFingerprint(String fingerprint) { + // split by 4 characters + fingerprint = fingerprint.replaceAll("(.{4})(?!$)", "$1 "); + + // add line breaks to have a consistent "image" that can be recognized + char[] chars = fingerprint.toCharArray(); + chars[24] = '\n'; + fingerprint = String.valueOf(chars); + + SpannableStringBuilder sb = new SpannableStringBuilder(fingerprint); + try { + // for each 4 characters of the fingerprint + 1 space + for (int i = 0; i < fingerprint.length(); i += 5) { + int spanEnd = Math.min(i + 4, fingerprint.length()); + String fourChars = fingerprint.substring(i, spanEnd); + + int raw = Integer.parseInt(fourChars, 16); + byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)}; + int[] color = getRgbForData(bytes); + int r = color[0]; + int g = color[1]; + int b = color[2]; + + // we cannot change black by multiplication, so adjust it to an almost-black grey, + // which will then be brightened to the minimal brightness level + if (r == 0 && g == 0 && b == 0) { + r = 1; + g = 1; + b = 1; + } + + // Convert rgb to brightness + double brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b; + + // If a color is too dark to be seen on black, + // then brighten it up to a minimal brightness. + if (brightness < 80) { + double factor = 80.0 / brightness; + r = Math.min(255, (int) (r * factor)); + g = Math.min(255, (int) (g * factor)); + b = Math.min(255, (int) (b * factor)); + + // If it is too light, then darken it to a respective maximal brightness. + } else if (brightness > 180) { + double factor = 180.0 / brightness; + r = (int) (r * factor); + g = (int) (g * factor); + b = (int) (b * factor); + } + + // Create a foreground color with the 3 digest integers as RGB + // and then converting that int to hex to use as a color + sb.setSpan(new ForegroundColorSpan(Color.rgb(r, g, b)), + i, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + } + } catch (Exception e) { + Log.e(Constants.TAG, "Colorization failed", e); + // if anything goes wrong, then just display the fingerprint without colour, + // instead of partially correct colour or wrong colours + return new SpannableStringBuilder(fingerprint); + } + + return sb; + } + + /** + * Converts the given bytes to a unique RGB color using SHA1 algorithm + * + * @param bytes + * @return an integer array containing 3 numeric color representations (Red, Green, Black) + * @throws java.security.NoSuchAlgorithmException + * @throws java.security.DigestException + */ + private static int[] getRgbForData(byte[] bytes) throws NoSuchAlgorithmException, DigestException { + MessageDigest md = MessageDigest.getInstance("SHA1"); + + md.update(bytes); + byte[] digest = md.digest(); + + return new int[]{((int) digest[0] + 256) % 256, + ((int) digest[1] + 256) % 256, + ((int) digest[2] + 256) % 256}; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java new file mode 100644 index 000000000..551ac039d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.app.Activity; +import android.content.res.Resources; + +import com.github.johnpersano.supertoasts.SuperCardToast; +import com.github.johnpersano.supertoasts.SuperToast; + +/** + * @author danielhass + * Notify wrapper which allows a more easy use of different notification libraries + */ +public class Notify { + + public static enum Style {OK, WARN, INFO, ERROR} + + /** + * Shows a simple in-layout notification with the CharSequence given as parameter + * @param activity + * @param text Text to show + * @param style Notification styling + */ + public static void showNotify(Activity activity, CharSequence text, Style style) { + + SuperCardToast st = new SuperCardToast(activity); + st.setText(text); + st.setDuration(SuperToast.Duration.MEDIUM); + switch (style){ + case OK: + st.setBackground(SuperToast.Background.GREEN); + break; + case WARN: + st.setBackground(SuperToast.Background.ORANGE); + break; + case ERROR: + st.setBackground(SuperToast.Background.RED); + break; + } + st.show(); + + } + + /** + * Shows a simple in-layout notification with the resource text from given id + * @param activity + * @param resId ResourceId of notification text + * @param style Notification styling + * @throws Resources.NotFoundException + */ + public static void showNotify(Activity activity, int resId, Style style) throws Resources.NotFoundException { + showNotify(activity, activity.getResources().getText(resId), style); + } +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java new file mode 100644 index 000000000..dd07a16b0 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013-2014 Dominik Schürmann + * Copyright (C) 2011 Andreas Schildbach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui.util; + +import android.graphics.Bitmap; +import android.graphics.Color; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Hashtable; + +/** + * Copied from Bitcoin Wallet + */ +public class QrCodeUtils { + public static final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); + + /** + * Generate Bitmap with QR Code based on input. + * + * @param input + * @param size + * @return QR Code as Bitmap + */ + public static Bitmap getQRCodeBitmap(final String input, final int size) { + try { + final Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); + final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, + size, hints); + + final int width = result.getWidth(); + final int height = result.getHeight(); + final int[] pixels = new int[width * height]; + + for (int y = 0; y < height; y++) { + final int offset = y * width; + for (int x = 0; x < width; x++) { + pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; + } + } + + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } catch (final WriterException e) { + Log.e(Constants.TAG, "QrCodeUtils", e); + return null; + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index c1045687d..2d2f80e5d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -41,9 +41,9 @@ import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -192,14 +192,14 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { public EncryptionKey(Cursor cursor) { this(cursor.getString(cursor.getColumnIndexOrThrow(KeyRings.USER_ID)), cursor.getLong(cursor.getColumnIndexOrThrow(KeyRings.KEY_ID)), - PgpKeyHelper.convertFingerprintToHex( + KeyFormattingUtils.convertFingerprintToHex( cursor.getBlob(cursor.getColumnIndexOrThrow(KeyRings.FINGERPRINT)))); } public EncryptionKey(CachedPublicKeyRing ring) throws PgpGeneralException { this(ring.getPrimaryUserId(), ring.extractOrGetMasterKeyId(), - PgpKeyHelper.convertFingerprintToHex(ring.getFingerprint())); + KeyFormattingUtils.convertFingerprintToHex(ring.getFingerprint())); } public String getUserId() { @@ -239,11 +239,11 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } public String getKeyIdHex() { - return PgpKeyHelper.convertKeyIdToHex(mKeyId); + return KeyFormattingUtils.convertKeyIdToHex(mKeyId); } public String getKeyIdHexShort() { - return PgpKeyHelper.convertKeyIdToHexShort(mKeyId); + return KeyFormattingUtils.convertKeyIdToHexShort(mKeyId); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index e7b148577..63287c799 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -36,7 +36,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; @@ -144,7 +144,7 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader TextView vKeyStatus = ((TextView) view.findViewById(R.id.keyspinner_key_status)); vKeyName.setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")")); ((TextView) view.findViewById(R.id.keyspinner_key_email)).setText(userId[1]); - ((TextView) view.findViewById(R.id.keyspinner_key_id)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); + ((TextView) view.findViewById(R.id.keyspinner_key_id)).setText(KeyFormattingUtils.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); String status = getStatus(getContext(), cursor); if (status == null) { vKeyName.setTextColor(Color.BLACK); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java new file mode 100644 index 000000000..1e2a35be2 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.annotation.TargetApi; +import android.content.ContentProviderOperation; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Build; +import android.provider.ContactsContract; +import android.util.Patterns; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.provider.KeychainContract; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ContactHelper { + + public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{ + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.FINGERPRINT, + KeychainContract.KeyRings.KEY_ID, + KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.EXPIRY, + KeychainContract.KeyRings.IS_REVOKED}; + public static final String[] USER_IDS_PROJECTION = new String[]{ + KeychainContract.UserIds.USER_ID + }; + + public static final String NON_REVOKED_SELECTION = KeychainContract.UserIds.IS_REVOKED + "=0"; + + public static final String[] ID_PROJECTION = new String[]{ContactsContract.RawContacts._ID}; + public static final String[] SOURCE_ID_PROJECTION = new String[]{ContactsContract.RawContacts.SOURCE_ID}; + + public static final String ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION = + ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?"; + public static final String ACCOUNT_TYPE_SELECTION = ContactsContract.RawContacts.ACCOUNT_TYPE + "=?"; + public static final String RAW_CONTACT_AND_MIMETYPE_SELECTION = + ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; + public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?"; + + private static final Map photoCache = new HashMap(); + + public static List getPossibleUserEmails(Context context) { + Set accountMails = getAccountEmails(context); + accountMails.addAll(getMainProfileContactEmails(context)); + // now return the Set (without duplicates) as a List + return new ArrayList(accountMails); + } + + public static List getPossibleUserNames(Context context) { + Set accountMails = getAccountEmails(context); + Set names = getContactNamesFromEmails(context, accountMails); + names.addAll(getMainProfileContactName(context)); + return new ArrayList(names); + } + + /** + * Get emails from AccountManager + * + * @param context + * @return + */ + private static Set getAccountEmails(Context context) { + final Account[] accounts = AccountManager.get(context).getAccounts(); + final Set emailSet = new HashSet(); + for (Account account : accounts) { + if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { + emailSet.add(account.name); + } + } + return emailSet; + } + + /** + * Search for contact names based on a list of emails (to find out the names of the + * device owner based on the email addresses from AccountsManager) + * + * @param context + * @param emails + * @return + */ + private static Set getContactNamesFromEmails(Context context, Set emails) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + Set names = new HashSet(); + for (String email : emails) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.Contacts.DISPLAY_NAME}, + ContactsContract.CommonDataKinds.Email.ADDRESS + "=?", + new String[]{email}, null + ); + if (profileCursor == null) return null; + + Set currNames = new HashSet(); + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(1); + Log.d(Constants.TAG, "name" + name); + if (name != null) { + currNames.add(name); + } + } + profileCursor.close(); + names.addAll(currNames); + } + return names; + } else { + return new HashSet(); + } + } + + /** + * Retrieves the emails of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static Set getMainProfileContactEmails(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + Uri.withAppendedPath( + ContactsContract.Profile.CONTENT_URI, + ContactsContract.Contacts.Data.CONTENT_DIRECTORY), + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.CommonDataKinds.Email.IS_PRIMARY}, + + // Selects only email addresses + ContactsContract.Contacts.Data.MIMETYPE + "=?", + new String[]{ + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, + }, + // Show primary rows first. Note that there won't be a primary email address if the + // user hasn't specified one. + ContactsContract.Contacts.Data.IS_PRIMARY + " DESC" + ); + if (profileCursor == null) return null; + + Set emails = new HashSet(); + while (profileCursor.moveToNext()) { + String email = profileCursor.getString(0); + if (email != null) { + emails.add(email); + } + } + profileCursor.close(); + return emails; + } else { + return new HashSet(); + } + } + + /** + * Retrieves the name of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static List getMainProfileContactName(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI, + new String[]{ContactsContract.Profile.DISPLAY_NAME}, + null, null, null); + if (profileCursor == null) return null; + + Set names = new HashSet(); + // should only contain one entry! + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(0); + if (name != null) { + names.add(name); + } + } + profileCursor.close(); + return new ArrayList(names); + } else { + return new ArrayList(); + } + } + + public static List getContactMails(Context context) { + ContentResolver resolver = context.getContentResolver(); + Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ContactsContract.CommonDataKinds.Email.DATA}, + null, null, null); + if (mailCursor == null) return new ArrayList(); + + Set mails = new HashSet(); + while (mailCursor.moveToNext()) { + String email = mailCursor.getString(0); + if (email != null) { + mails.add(email); + } + } + mailCursor.close(); + return new ArrayList(mails); + } + + public static List getContactNames(Context context) { + ContentResolver resolver = context.getContentResolver(); + Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, + new String[]{ContactsContract.Contacts.DISPLAY_NAME}, + null, null, null); + if (cursor == null) return new ArrayList(); + + Set names = new HashSet(); + while (cursor.moveToNext()) { + String name = cursor.getString(0); + if (name != null) { + names.add(name); + } + } + cursor.close(); + return new ArrayList(names); + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + public static Uri dataUriFromContactUri(Context context, Uri contactUri) { + Cursor contactMasterKey = context.getContentResolver().query(contactUri, + new String[]{ContactsContract.Data.DATA2}, null, null, null, null); + if (contactMasterKey != null) { + if (contactMasterKey.moveToNext()) { + return KeychainContract.KeyRings.buildGenericKeyRingUri(contactMasterKey.getLong(0)); + } + contactMasterKey.close(); + } + return null; + } + + public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { + if (fingerprint == null) return null; + if (!photoCache.containsKey(fingerprint)) { + photoCache.put(fingerprint, loadPhotoFromFingerprint(contentResolver, fingerprint)); + } + return photoCache.get(fingerprint); + } + + private static Bitmap loadPhotoFromFingerprint(ContentResolver contentResolver, String fingerprint) { + if (fingerprint == null) return null; + try { + int rawContactId = findRawContactId(contentResolver, fingerprint); + if (rawContactId == -1) return null; + Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); + Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri); + InputStream photoInputStream = + ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri); + if (photoInputStream == null) return null; + return BitmapFactory.decodeStream(photoInputStream); + } catch (Throwable ignored) { + return null; + } + } + + /** + * Write the current Keychain to the contact db + */ + public static void writeKeysToContacts(Context context) { + ContentResolver resolver = context.getContentResolver(); + Set contactFingerprints = getRawContactFingerprints(resolver); + + // Load all Keys from OK + Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), KEYS_TO_CONTACT_PROJECTION, + null, null, null); + if (cursor != null) { + while (cursor.moveToNext()) { + String[] primaryUserId = KeyRing.splitUserId(cursor.getString(0)); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1)); + contactFingerprints.remove(fingerprint); + String keyIdShort = KeyFormattingUtils.convertKeyIdToHexShort(cursor.getLong(2)); + long masterKeyId = cursor.getLong(3); + boolean isExpired = !cursor.isNull(4) && new Date(cursor.getLong(4) * 1000).before(new Date()); + boolean isRevoked = cursor.getInt(5) > 0; + int rawContactId = findRawContactId(resolver, fingerprint); + ArrayList ops = new ArrayList(); + + // Do not store expired or revoked keys in contact db - and remove them if they already exist + if (isExpired || isRevoked) { + if (rawContactId != -1) { + resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ID_SELECTION, + new String[]{Integer.toString(rawContactId)}); + } + } else { + + // Create a new rawcontact with corresponding key if it does not exist yet + if (rawContactId == -1) { + insertContact(ops, context, fingerprint); + writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort); + } + + // We always update the display name (which is derived from primary user id) + // and email addresses from user id + writeContactDisplayName(ops, rawContactId, primaryUserId[0]); + writeContactEmail(ops, resolver, rawContactId, masterKeyId); + try { + resolver.applyBatch(ContactsContract.AUTHORITY, ops); + } catch (Exception e) { + Log.w(Constants.TAG, e); + } + } + } + cursor.close(); + } + + // Delete fingerprints that are no longer present in OK + for (String fingerprint : contactFingerprints) { + resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, + new String[]{Constants.ACCOUNT_TYPE, fingerprint}); + } + + } + + /** + * @return a set of all key fingerprints currently present in the contact db + */ + private static Set getRawContactFingerprints(ContentResolver resolver) { + HashSet result = new HashSet(); + Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION, + ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null); + if (fingerprints != null) { + while (fingerprints.moveToNext()) { + result.add(fingerprints.getString(0)); + } + fingerprints.close(); + } + return result; + } + + /** + * This will search the contact db for a raw contact with a given fingerprint + * + * @return raw contact id or -1 if not found + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private static int findRawContactId(ContentResolver resolver, String fingerprint) { + int rawContactId = -1; + Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, ID_PROJECTION, + ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, new String[]{Constants.ACCOUNT_TYPE, fingerprint}, null, null); + if (raw != null) { + if (raw.moveToNext()) { + rawContactId = raw.getInt(0); + } + raw.close(); + } + return rawContactId; + } + + /** + * Creates a empty raw contact with a given fingerprint + */ + private static void insertContact(ArrayList ops, Context context, String fingerprint) { + ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) + .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME) + .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE) + .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint) + .build()); + } + + /** + * Adds a key id to the given raw contact. + *

+ * This creates the link to OK in contact details + */ + private static void writeContactKey(ArrayList ops, Context context, int rawContactId, + long masterKeyId, String keyIdShort) { + ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId) + .withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE) + .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyIdShort)) + .withValue(ContactsContract.Data.DATA2, masterKeyId) + .build()); + } + + /** + * Write all known email addresses of a key (derived from user ids) to a given raw contact + */ + private static void writeContactEmail(ArrayList ops, ContentResolver resolver, + int rawContactId, long masterKeyId) { + ops.add(selectByRawContactAndItemType(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI), + rawContactId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE).build()); + Cursor ids = resolver.query(KeychainContract.UserIds.buildUserIdsUri(masterKeyId), + USER_IDS_PROJECTION, NON_REVOKED_SELECTION, null, null); + if (ids != null) { + while (ids.moveToNext()) { + String[] userId = KeyRing.splitUserId(ids.getString(0)); + if (userId[1] != null) { + ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), + rawContactId) + .withValue(ContactsContract.Data.MIMETYPE, + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId[1]) + .build()); + } + } + ids.close(); + } + } + + private static void writeContactDisplayName(ArrayList ops, int rawContactId, + String displayName) { + if (displayName != null) { + ops.add(insertOrUpdateForRawContact(ContactsContract.Data.CONTENT_URI, rawContactId, + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) + .build()); + } + } + + private static ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder, + int rawContactId) { + return rawContactId == -1 ? + builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) : + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); + } + + private static ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, int rawContactId, + String itemType) { + if (rawContactId == -1) { + return referenceRawContact(ContentProviderOperation.newInsert(uri), rawContactId).withValue( + ContactsContract.Data.MIMETYPE, itemType); + } else { + return selectByRawContactAndItemType(ContentProviderOperation.newUpdate(uri), rawContactId, itemType); + } + } + + private static ContentProviderOperation.Builder selectByRawContactAndItemType( + ContentProviderOperation.Builder builder, int rawContactId, String itemType) { + return builder.withSelection(RAW_CONTACT_AND_MIMETYPE_SELECTION, + new String[]{Integer.toString(rawContactId), itemType}); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java new file mode 100644 index 000000000..33541718e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Messenger; + +import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; +import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.keyimport.Keyserver; +import org.sufficientlysecure.keychain.service.KeychainIntentService; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +public class EmailKeyHelper { + + public static void importContacts(Context context, Messenger messenger) { + importAll(context, messenger, ContactHelper.getContactMails(context)); + } + + public static void importAll(Context context, Messenger messenger, List mails) { + Set keys = new HashSet(); + for (String mail : mails) { + keys.addAll(getEmailKeys(context, mail)); + } + importKeys(context, messenger, new ArrayList(keys)); + } + + public static List getEmailKeys(Context context, String mail) { + Set keys = new HashSet(); + + // Try _hkp._tcp SRV record first + String[] mailparts = mail.split("@"); + if (mailparts.length == 2) { + HkpKeyserver hkp = HkpKeyserver.resolve(mailparts[1]); + if (hkp != null) { + keys.addAll(getEmailKeys(mail, hkp)); + } + } + + if (keys.isEmpty()) { + // Most users don't have the SRV record, so ask a default server as well + String server = Preferences.getPreferences(context).getPreferredKeyserver(); + if (server != null) { + HkpKeyserver hkp = new HkpKeyserver(server); + keys.addAll(getEmailKeys(mail, hkp)); + } + } + return new ArrayList(keys); + } + + private static void importKeys(Context context, Messenger messenger, List keys) { + Intent importIntent = new Intent(context, KeychainIntentService.class); + importIntent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); + Bundle importData = new Bundle(); + importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, + new ArrayList(keys)); + importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData); + importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + context.startService(importIntent); + } + + public static List getEmailKeys(String mail, Keyserver keyServer) { + Set keys = new HashSet(); + try { + for (ImportKeysListEntry key : keyServer.search(mail)) { + if (key.isRevoked() || key.isExpired()) continue; + for (String userId : key.getUserIds()) { + if (userId.toLowerCase().contains(mail.toLowerCase(Locale.ENGLISH))) { + keys.add(key); + } + } + } + } catch (Keyserver.QueryFailedException ignored) { + } catch (Keyserver.QueryNeedsRepairException ignored) { + } + return new ArrayList(keys); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java new file mode 100644 index 000000000..3c100e272 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.support.v7.app.ActionBarActivity; +import android.widget.Toast; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; + +import java.io.File; + +public class ExportHelper { + protected File mExportFile; + + ActionBarActivity mActivity; + + public ExportHelper(ActionBarActivity activity) { + super(); + this.mActivity = activity; + } + + public void deleteKey(Uri dataUri, Handler deleteHandler) { + try { + long masterKeyId = new ProviderHelper(mActivity).getCachedPublicKeyRing(dataUri) + .extractOrGetMasterKeyId(); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(deleteHandler); + DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, + new long[]{ masterKeyId }); + deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog"); + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "key not found!", e); + } + } + + /** + * Show dialog where to export keys + */ + public void showExportKeysDialog(final long[] masterKeyIds, final File exportFile, + final boolean showSecretCheckbox) { + mExportFile = exportFile; + + String title = null; + if (masterKeyIds == null) { + // export all keys + title = mActivity.getString(R.string.title_export_keys); + } else { + // export only key specified at data uri + title = mActivity.getString(R.string.title_export_key); + } + + String message = mActivity.getString(R.string.specify_file_to_export_to); + String checkMsg = showSecretCheckbox ? + mActivity.getString(R.string.also_export_secret_keys) : null; + + FileHelper.saveFile(new FileHelper.FileDialogCallback() { + @Override + public void onFileSelected(File file, boolean checked) { + mExportFile = file; + exportKeys(masterKeyIds, checked); + } + }, mActivity.getSupportFragmentManager() ,title, message, exportFile, checkMsg); + } + + /** + * Export keys + */ + public void exportKeys(long[] masterKeyIds, boolean exportSecret) { + Log.d(Constants.TAG, "exportKeys started"); + + // Send all information needed to service to export key in other thread + final Intent intent = new Intent(mActivity, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING); + + // fill values for this action + Bundle data = new Bundle(); + + data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFile.getAbsolutePath()); + data.putBoolean(KeychainIntentService.EXPORT_SECRET, exportSecret); + + if (masterKeyIds == null) { + data.putBoolean(KeychainIntentService.EXPORT_ALL, true); + } else { + data.putLongArray(KeychainIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, masterKeyIds); + } + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Message is received after exporting is done in KeychainIntentService + KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(mActivity, + mActivity.getString(R.string.progress_exporting), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + + int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT); + String toastMessage; + if (exported == 1) { + toastMessage = mActivity.getString(R.string.key_exported); + } else if (exported > 0) { + toastMessage = mActivity.getString(R.string.keys_exported, exported); + } else { + toastMessage = mActivity.getString(R.string.no_keys_exported); + } + Toast.makeText(mActivity, toastMessage, Toast.LENGTH_SHORT).show(); + + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(exportHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + exportHandler.showProgressDialog(mActivity); + + // start service with intent + mActivity.startService(intent); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java new file mode 100644 index 000000000..677acb1b8 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Point; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.provider.DocumentsContract; +import android.provider.OpenableColumns; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.widget.Toast; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; + +import java.io.File; +import java.text.DecimalFormat; + +public class FileHelper { + + /** + * Checks if external storage is mounted if file is located on external storage + * + * @param file + * @return true if storage is mounted + */ + public static boolean isStorageMounted(String file) { + if (file.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) { + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + return false; + } + } + + return true; + } + + /** + * Opens the preferred installed file manager on Android and shows a toast if no manager is + * installed. + * + * @param fragment + * @param last default selected Uri, not supported by all file managers + * @param mimeType can be text/plain for example + * @param requestCode requestCode used to identify the result coming back from file manager to + * onActivityResult() in your activity + */ + public static void openFile(Fragment fragment, Uri last, String mimeType, int requestCode) { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + + intent.setData(last); + intent.setType(mimeType); + + try { + fragment.startActivityForResult(intent, requestCode); + } catch (ActivityNotFoundException e) { + // No compatible file manager was found. + Toast.makeText(fragment.getActivity(), R.string.no_filemanager_installed, + Toast.LENGTH_SHORT).show(); + } + } + + public static void saveFile(final FileDialogCallback callback, final FragmentManager fragmentManager, + final String title, final String message, final File defaultFile, + final String checkMsg) { + // Message is received after file is selected + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == FileDialogFragment.MESSAGE_OKAY) { + callback.onFileSelected( + new File(message.getData().getString(FileDialogFragment.MESSAGE_DATA_FILE)), + message.getData().getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED)); + } + } + }; + + // Create a new Messenger for the communication back + final Messenger messenger = new Messenger(returnHandler); + + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + @Override + public void run() { + FileDialogFragment fileDialog = FileDialogFragment.newInstance(messenger, title, message, + defaultFile, checkMsg); + + fileDialog.show(fragmentManager, "fileDialog"); + } + }); + } + + public static void saveFile(Fragment fragment, String title, String message, File defaultFile, int requestCode) { + saveFile(fragment, title, message, defaultFile, requestCode, null); + } + + public static void saveFile(final Fragment fragment, String title, String message, File defaultFile, + final int requestCode, String checkMsg) { + saveFile(new FileDialogCallback() { + @Override + public void onFileSelected(File file, boolean checked) { + Intent intent = new Intent(); + intent.setData(Uri.fromFile(file)); + fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent); + } + }, fragment.getActivity().getSupportFragmentManager(), title, message, defaultFile, checkMsg); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + public static void openDocument(Fragment fragment, String mimeType, int requestCode) { + openDocument(fragment, mimeType, false, requestCode); + } + + /** + * Opens the storage browser on Android 4.4 or later for opening a file + * + * @param fragment + * @param mimeType can be text/plain for example + * @param multiple allow file chooser to return multiple files + * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static void openDocument(Fragment fragment, String mimeType, boolean multiple, int requestCode) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(mimeType); + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple); + + fragment.startActivityForResult(intent, requestCode); + } + + /** + * Opens the storage browser on Android 4.4 or later for saving a file + * + * @param fragment + * @param mimeType can be text/plain for example + * @param suggestedName a filename desirable for the file to be saved + * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static void saveDocument(Fragment fragment, String mimeType, String suggestedName, int requestCode) { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(mimeType); + intent.putExtra("android.content.extra.SHOW_ADVANCED", true); // Note: This is not documented, but works + intent.putExtra(Intent.EXTRA_TITLE, suggestedName); + fragment.startActivityForResult(intent, requestCode); + } + + public static String getFilename(Context context, Uri uri) { + String filename = null; + try { + Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); + + if (cursor != null) { + if (cursor.moveToNext()) { + filename = cursor.getString(0); + } + cursor.close(); + } + } catch (Exception ignored) { + // This happens in rare cases (eg: document deleted since selection) and should not cause a failure + } + if (filename == null) { + String[] split = uri.toString().split("/"); + filename = split[split.length - 1]; + } + return filename; + } + + public static long getFileSize(Context context, Uri uri) { + return getFileSize(context, uri, -1); + } + + public static long getFileSize(Context context, Uri uri, long def) { + long size = def; + try { + Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null); + + if (cursor != null) { + if (cursor.moveToNext()) { + size = cursor.getLong(0); + } + cursor.close(); + } + } catch (Exception ignored) { + // This happens in rare cases (eg: document deleted since selection) and should not cause a failure + } + return size; + } + + /** + * Retrieve thumbnail of file, document api feature and thus KitKat only + */ + public static Bitmap getThumbnail(Context context, Uri uri, Point size) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + return DocumentsContract.getDocumentThumbnail(context.getContentResolver(), uri, size, null); + } else { + return null; + } + } + + public static String readableFileSize(long size) { + if (size <= 0) return "0"; + final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"}; + int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); + return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } + + public static interface FileDialogCallback { + public void onFileSelected(File file, boolean checked); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Highlighter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Highlighter.java deleted file mode 100644 index eeeacf465..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Highlighter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2014 Thialfihar - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.util; - -import android.content.Context; -import android.text.Spannable; -import android.text.style.ForegroundColorSpan; - -import org.sufficientlysecure.keychain.R; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Highlighter { - private Context mContext; - private String mQuery; - - public Highlighter(Context context, String query) { - mContext = context; - mQuery = query; - } - - public Spannable highlight(String text) { - Spannable highlight = Spannable.Factory.getInstance().newSpannable(text); - - if (mQuery == null) { - return highlight; - } - - Pattern pattern = Pattern.compile("(?i)(" + mQuery.trim().replaceAll("\\s+", "|") + ")"); - Matcher matcher = pattern.matcher(text); - while (matcher.find()) { - highlight.setSpan( - new ForegroundColorSpan(mContext.getResources().getColor(R.color.emphasis)), - matcher.start(), - matcher.end(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - return highlight; - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java new file mode 100644 index 000000000..357a9603c --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Daniel Albert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Messenger; + +import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; + +import java.util.ArrayList; +import java.util.List; + +public class KeyUpdateHelper { + + public void updateAllKeys(Context context, KeychainIntentServiceHandler finishedHandler) { + UpdateTask updateTask = new UpdateTask(context, finishedHandler); + updateTask.execute(); + } + + private class UpdateTask extends AsyncTask { + private Context mContext; + private KeychainIntentServiceHandler mHandler; + + public UpdateTask(Context context, KeychainIntentServiceHandler handler) { + this.mContext = context; + this.mHandler = handler; + } + + @Override + protected Void doInBackground(Void... voids) { + ProviderHelper providerHelper = new ProviderHelper(mContext); + List keys = new ArrayList(); + String[] servers = Preferences.getPreferences(mContext).getKeyServers(); + + if (servers != null && servers.length > 0) { + // Load all the fingerprints in the database and prepare to import them + for (String fprint : providerHelper.getAllFingerprints(KeychainContract.KeyRings.buildUnifiedKeyRingsUri())) { + ImportKeysListEntry key = new ImportKeysListEntry(); + key.setFingerprintHex(fprint); + key.setBitStrength(1337); + key.addOrigin(servers[0]); + keys.add(key); + } + + // Start the service and update the keys + Intent importIntent = new Intent(mContext, KeychainIntentService.class); + importIntent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); + + Bundle importData = new Bundle(); + importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, + new ArrayList(keys)); + importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData); + + importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, new Messenger(mHandler)); + + mContext.startService(importIntent); + } + return null; + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java index 10c0fc4d0..4dda74ace 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java @@ -17,8 +17,13 @@ package org.sufficientlysecure.keychain.util; +import android.os.Bundle; + import org.sufficientlysecure.keychain.Constants; +import java.util.Iterator; +import java.util.Set; + /** * Wraps Android Logging to enable or disable debug output using Constants */ @@ -80,4 +85,35 @@ public final class Log { android.util.Log.e(tag, msg, tr); } + + /** + * Logs bundle content to debug for inspecting the content + * + * @param bundle + * @param bundleName + */ + public static void logDebugBundle(Bundle bundle, String bundleName) { + if (Constants.DEBUG) { + if (bundle != null) { + Set ks = bundle.keySet(); + Iterator iterator = ks.iterator(); + + Log.d(Constants.TAG, "Bundle " + bundleName + ":"); + Log.d(Constants.TAG, "------------------------------"); + while (iterator.hasNext()) { + String key = iterator.next(); + Object value = bundle.get(key); + + if (value != null) { + Log.d(Constants.TAG, key + " : " + value.toString()); + } else { + Log.d(Constants.TAG, key + " : null"); + } + } + Log.d(Constants.TAG, "------------------------------"); + } else { + Log.d(Constants.TAG, "Bundle " + bundleName + ": null"); + } + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Notify.java deleted file mode 100644 index 22e3f5d66..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Notify.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.util; - -import android.app.Activity; -import android.content.res.Resources; - -import com.github.johnpersano.supertoasts.SuperCardToast; -import com.github.johnpersano.supertoasts.SuperToast; - -/** - * @author danielhass - * Notify wrapper which allows a more easy use of different notification libraries - */ -public class Notify { - - public static enum Style {OK, WARN, INFO, ERROR} - - /** - * Shows a simple in-layout notification with the CharSequence given as parameter - * @param activity - * @param text Text to show - * @param style Notification styling - */ - public static void showNotify(Activity activity, CharSequence text, Style style) { - - SuperCardToast st = new SuperCardToast(activity); - st.setText(text); - st.setDuration(SuperToast.Duration.MEDIUM); - switch (style){ - case OK: - st.setBackground(SuperToast.Background.GREEN); - break; - case WARN: - st.setBackground(SuperToast.Background.ORANGE); - break; - case ERROR: - st.setBackground(SuperToast.Background.RED); - break; - } - st.show(); - - } - - /** - * Shows a simple in-layout notification with the resource text from given id - * @param activity - * @param resId ResourceId of notification text - * @param style Notification styling - * @throws Resources.NotFoundException - */ - public static void showNotify(Activity activity, int resId, Style style) throws Resources.NotFoundException { - showNotify(activity, activity.getResources().getText(resId), style); - } -} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java new file mode 100644 index 000000000..35570ef6e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2010-2014 Thialfihar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build; + +import org.spongycastle.bcpg.CompressionAlgorithmTags; +import org.spongycastle.bcpg.HashAlgorithmTags; +import org.spongycastle.openpgp.PGPEncryptedData; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Constants.Pref; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.ListIterator; +import java.util.Vector; + +/** + * Singleton Implementation of a Preference Helper + */ +public class Preferences { + private static Preferences sPreferences; + private SharedPreferences mSharedPreferences; + + public static synchronized Preferences getPreferences(Context context) { + return getPreferences(context, false); + } + + public static synchronized Preferences getPreferences(Context context, boolean forceNew) { + if (sPreferences == null || forceNew) { + sPreferences = new Preferences(context); + } else { + // to make it safe for multiple processes, call getSharedPreferences everytime + sPreferences.updateSharedPreferences(context); + } + return sPreferences; + } + + private Preferences(Context context) { + updateSharedPreferences(context); + } + + public void updateSharedPreferences(Context context) { + // multi-process preferences + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_MULTI_PROCESS); + } else { + mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE); + } + } + + public String getLanguage() { + return mSharedPreferences.getString(Constants.Pref.LANGUAGE, ""); + } + + public void setLanguage(String value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putString(Constants.Pref.LANGUAGE, value); + editor.commit(); + } + + public long getPassphraseCacheTtl() { + int ttl = mSharedPreferences.getInt(Constants.Pref.PASSPHRASE_CACHE_TTL, 180); + // fix the value if it was set to "never" in previous versions, which currently is not + // supported + if (ttl == 0) { + ttl = 180; + } + return (long) ttl; + } + + public void setPassphraseCacheTtl(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Constants.Pref.PASSPHRASE_CACHE_TTL, value); + editor.commit(); + } + + public int getDefaultEncryptionAlgorithm() { + return mSharedPreferences.getInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, + PGPEncryptedData.AES_256); + } + + public void setDefaultEncryptionAlgorithm(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, value); + editor.commit(); + } + + public int getDefaultHashAlgorithm() { + return mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, + HashAlgorithmTags.SHA256); + } + + public void setDefaultHashAlgorithm(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, value); + editor.commit(); + } + + public int getDefaultMessageCompression() { + return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, + CompressionAlgorithmTags.ZLIB); + } + + public void setDefaultMessageCompression(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, value); + editor.commit(); + } + + public int getDefaultFileCompression() { + return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, + CompressionAlgorithmTags.UNCOMPRESSED); + } + + public void setDefaultFileCompression(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, value); + editor.commit(); + } + + public boolean getDefaultAsciiArmor() { + return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, false); + } + + public void setDefaultAsciiArmor(boolean value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, value); + editor.commit(); + } + + public boolean getShowAdvancedTabs() { + return mSharedPreferences.getBoolean(Pref.SHOW_ADVANCED_TABS, false); + } + + public void setShowAdvancedTabs(boolean value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.SHOW_ADVANCED_TABS, value); + editor.commit(); + } + + public boolean getCachedConsolidate() { + return mSharedPreferences.getBoolean(Pref.CACHED_CONSOLIDATE, false); + } + + public void setCachedConsolidate(boolean value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.CACHED_CONSOLIDATE, value); + editor.commit(); + } + + public int getCachedConsolidateNumPublics() { + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_PUBLICS, -1); + } + + public void setCachedConsolidateNumPublics(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Pref.CACHED_CONSOLIDATE_PUBLICS, value); + editor.commit(); + } + + public int getCachedConsolidateNumSecrets() { + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_SECRETS, -1); + } + + public void setCachedConsolidateNumSecrets(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Pref.CACHED_CONSOLIDATE_SECRETS, value); + editor.commit(); + } + + public boolean isFirstTime() { + return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true); + } + + public boolean useDefaultYubikeyPin() { + return mSharedPreferences.getBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, true); + } + + public void setUseDefaultYubikeyPin(boolean useDefaultYubikeyPin) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, useDefaultYubikeyPin); + editor.commit(); + } + + public void setFirstTime(boolean value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Constants.Pref.FIRST_TIME, value); + editor.commit(); + } + + public String[] getKeyServers() { + String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS, + Constants.Defaults.KEY_SERVERS); + Vector servers = new Vector(); + String chunks[] = rawData.split(","); + for (String c : chunks) { + String tmp = c.trim(); + if (tmp.length() > 0) { + servers.add(tmp); + } + } + return servers.toArray(chunks); + } + public String getPreferredKeyserver() { + return getKeyServers()[0]; + } + + public void setKeyServers(String[] value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + String rawData = ""; + for (String v : value) { + String tmp = v.trim(); + if (tmp.length() == 0) { + continue; + } + if (!"".equals(rawData)) { + rawData += ","; + } + rawData += tmp; + } + editor.putString(Constants.Pref.KEY_SERVERS, rawData); + editor.commit(); + } + + public void setWriteVersionHeader(boolean conceal) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Constants.Pref.WRITE_VERSION_HEADER, conceal); + editor.commit(); + } + + public boolean getWriteVersionHeader() { + return mSharedPreferences.getBoolean(Constants.Pref.WRITE_VERSION_HEADER, false); + } + + public void setSearchKeyserver(boolean searchKeyserver) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver); + editor.commit(); + } + public void setSearchKeybase(boolean searchKeybase) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase); + editor.commit(); + } + + public CloudSearchPrefs getCloudSearchPrefs() { + return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true), + mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true), + getPreferredKeyserver()); + } + + public static class CloudSearchPrefs { + public final boolean searchKeyserver; + public final boolean searchKeybase; + public final String keyserver; + + public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase, String keyserver) { + this.searchKeyserver = searchKeyserver; + this.searchKeybase = searchKeybase; + this.keyserver = keyserver; + } + } + + public void updatePreferences() { + if (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0) != + Constants.Defaults.PREF_VERSION) { + switch (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0)) { + case 1: + // fall through + case 2: + // fall through + case 3: { + // migrate keyserver to hkps + String[] serversArray = getKeyServers(); + ArrayList servers = new ArrayList(Arrays.asList(serversArray)); + ListIterator it = servers.listIterator(); + while (it.hasNext()) { + String server = it.next(); + if (server == null) { + continue; + } + if (server.equals("pool.sks-keyservers.net")) { + // use HKPS! + it.set("hkps://hkps.pool.sks-keyservers.net"); + } else if (server.equals("pgp.mit.edu")) { + // use HKPS! + it.set("hkps://pgp.mit.edu"); + } else if (server.equals("subkeys.pgp.net")) { + // remove, because often down and no HKPS! + it.remove(); + } + + } + setKeyServers(servers.toArray(new String[servers.size()])); + + // migrate old uncompressed constant to new one + if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, 0) + == 0x21070001) { + setDefaultFileCompression(CompressionAlgorithmTags.UNCOMPRESSED); + } + + // migrate away from MD5 + if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) + == HashAlgorithmTags.MD5) { + setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); + } + } + // fall through + case 4: { + // for compatibility: change from SHA512 to SHA256 + if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) + == HashAlgorithmTags.SHA512) { + setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); + } + } + } + + // write new preference version + mSharedPreferences.edit() + .putInt(Constants.Pref.PREF_DEFAULT_VERSION, Constants.Defaults.PREF_VERSION) + .commit(); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/QrCodeUtils.java deleted file mode 100644 index 28e567d76..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/QrCodeUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * Copyright (C) 2011 Andreas Schildbach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.util; - -import android.graphics.Bitmap; -import android.graphics.Color; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.QRCodeWriter; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; - -import org.sufficientlysecure.keychain.Constants; - -import java.util.Hashtable; - -/** - * Copied from Bitcoin Wallet - */ -public class QrCodeUtils { - public static final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); - - /** - * Generate Bitmap with QR Code based on input. - * - * @param input - * @param size - * @return QR Code as Bitmap - */ - public static Bitmap getQRCodeBitmap(final String input, final int size) { - try { - final Hashtable hints = new Hashtable(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); - final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, - size, hints); - - final int width = result.getWidth(); - final int height = result.getHeight(); - final int[] pixels = new int[width * height]; - - for (int y = 0; y < height; y++) { - final int offset = y * width; - for (int x = 0; x < width; x++) { - pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; - } - } - - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - return bitmap; - } catch (final WriterException e) { - Log.e(Constants.TAG, "QrCodeUtils", e); - return null; - } - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java new file mode 100644 index 000000000..27f026f80 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java @@ -0,0 +1,101 @@ +package org.sufficientlysecure.keychain.util; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.LabeledIntent; +import android.content.pm.ResolveInfo; +import android.os.Build; +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class ShareHelper { + Context mContext; + + public ShareHelper(Context context) { + mContext = context; + } + + /** + * Create Intent Chooser but exclude OK's EncryptActivity. + *

+ * Put together from some stackoverflow posts... + */ + public Intent createChooserExcluding(Intent prototype, String title, String[] activityBlacklist) { + // Produced an empty list on Huawei U8860 with Android Version 4.0.3 and weird results on 2.3 + // TODO: test on 4.1, 4.2, 4.3, only tested on 4.4 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + return Intent.createChooser(prototype, title); + } + + List targetedShareIntents = new ArrayList(); + + List resInfoList = mContext.getPackageManager().queryIntentActivities(prototype, 0); + List resInfoListFiltered = new ArrayList(); + if (!resInfoList.isEmpty()) { + for (ResolveInfo resolveInfo : resInfoList) { + // do not add blacklisted ones + if (resolveInfo.activityInfo == null || Arrays.asList(activityBlacklist).contains(resolveInfo.activityInfo.name)) + continue; + + resInfoListFiltered.add(resolveInfo); + } + + if (!resInfoListFiltered.isEmpty()) { + // sorting for nice readability + Collections.sort(resInfoListFiltered, new Comparator() { + @Override + public int compare(ResolveInfo first, ResolveInfo second) { + String firstName = first.loadLabel(mContext.getPackageManager()).toString(); + String secondName = second.loadLabel(mContext.getPackageManager()).toString(); + return firstName.compareToIgnoreCase(secondName); + } + }); + + // create the custom intent list + for (ResolveInfo resolveInfo : resInfoListFiltered) { + Intent targetedShareIntent = (Intent) prototype.clone(); + targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName); + targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); + + LabeledIntent lIntent = new LabeledIntent(targetedShareIntent, + resolveInfo.activityInfo.packageName, + resolveInfo.loadLabel(mContext.getPackageManager()), + resolveInfo.activityInfo.icon); + targetedShareIntents.add(lIntent); + } + + // Create chooser with only one Intent in it + Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), title); + // append all other Intents + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{})); + return chooserIntent; + } + + } + + // fallback to Android's default chooser + return Intent.createChooser(prototype, title); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java new file mode 100644 index 000000000..9946d81aa --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2013-2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.util; + +import android.content.res.AssetManager; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.util.HashMap; +import java.util.Map; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +public class TlsHelper { + + public static class TlsHelperException extends Exception { + public TlsHelperException(Exception e) { + super(e); + } + } + + private static Map sStaticCA = new HashMap(); + + public static void addStaticCA(String domain, byte[] certificate) { + sStaticCA.put(domain, certificate); + } + + public static void addStaticCA(String domain, AssetManager assetManager, String name) { + try { + InputStream is = assetManager.open(name); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int reads = is.read(); + + while(reads != -1){ + baos.write(reads); + reads = is.read(); + } + + is.close(); + + addStaticCA(domain, baos.toByteArray()); + } catch (IOException e) { + Log.w(Constants.TAG, e); + } + } + + public static URLConnection openConnection(URL url) throws IOException, TlsHelperException { + if (url.getProtocol().equals("https")) { + for (String domain : sStaticCA.keySet()) { + if (url.getHost().endsWith(domain)) { + return openCAConnection(sStaticCA.get(domain), url); + } + } + } + return url.openConnection(); + } + + /** + * Opens a Connection that will only accept certificates signed with a specific CA and skips common name check. + * This is required for some distributed Keyserver networks like sks-keyservers.net + * + * @param certificate The X.509 certificate used to sign the servers certificate + * @param url Connection target + */ + public static HttpsURLConnection openCAConnection(byte[] certificate, URL url) + throws TlsHelperException, IOException { + try { + // Load CA + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate)); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("ca", ca); + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(keyStore); + + // Create an SSLContext that uses our TrustManager + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, tmf.getTrustManagers(), null); + + // Tell the URLConnection to use a SocketFactory from our SSLContext + HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(context.getSocketFactory()); + + return urlConnection; + } catch (CertificateException e) { + throw new TlsHelperException(e); + } catch (NoSuchAlgorithmException e) { + throw new TlsHelperException(e); + } catch (KeyStoreException e) { + throw new TlsHelperException(e); + } catch (KeyManagementException e) { + throw new TlsHelperException(e); + } + } +} -- cgit v1.2.3