From 79fb23b095fba273d77066204ee44d2b8d1edf8d Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 22 Jun 2014 16:31:28 +0200 Subject: Improve file more, Part 1 - Use Uris where it makes sense, Use File class to clarify it's a file (and not whatever else a string could be) - Show sdcard in side menu in storage API #665 - Propose filename with gpg ending when storing it using the storage API #665 - Don't show output dialog on Android 4.4 #665 - Only show filename on Android < 4.4 #665 TODO: - File deletion for Android < 4.4 - Testing (especially with Android < 4.4) - Batch-encryption - UI - Temporary content provider (see #665 discussion) --- .../org/sufficientlysecure/keychain/Constants.java | 7 +- .../keychain/KeychainApplication.java | 5 +- .../keychain/helper/ExportHelper.java | 63 +++---- .../keychain/helper/FileHelper.java | 149 +++++++++-------- .../keychain/service/KeychainIntentService.java | 21 ++- .../keychain/ui/DecryptActivity.java | 21 +-- .../keychain/ui/DecryptFileFragment.java | 171 ++++++------------- .../keychain/ui/EncryptActivity.java | 29 +--- .../keychain/ui/EncryptFileFragment.java | 181 ++++++--------------- .../keychain/ui/ImportKeysFileFragment.java | 2 +- .../keychain/ui/KeyListFragment.java | 8 +- .../keychain/ui/ViewKeyActivity.java | 4 +- .../ui/dialog/DeleteFileDialogFragment.java | 38 ++--- .../keychain/ui/dialog/FileDialogFragment.java | 87 ++++------ 14 files changed, 290 insertions(+), 496 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 319ac2873..8074ad2ee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -27,6 +27,8 @@ import org.sufficientlysecure.keychain.ui.DecryptActivity; import org.sufficientlysecure.keychain.ui.EncryptActivity; import org.sufficientlysecure.keychain.ui.KeyListActivity; +import java.io.File; + public final class Constants { public static final boolean DEBUG = BuildConfig.DEBUG; @@ -52,9 +54,8 @@ public final class Constants { public static boolean KITKAT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; public static final class Path { - public static final String APP_DIR = Environment.getExternalStorageDirectory() - + "/OpenKeychain"; - public static final String APP_DIR_FILE = APP_DIR + "/export.asc"; + public static final File APP_DIR = new File(Environment.getExternalStorageDirectory(), "OpenKeychain"); + public static final File APP_DIR_FILE = new File(APP_DIR, "export.asc"); } public static final class Pref { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 5d6a62f9c..d28c4d63c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -26,11 +26,9 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; -import java.io.File; import java.security.Provider; import java.security.Security; @@ -70,8 +68,7 @@ public class KeychainApplication extends Application { // Create APG directory on sdcard if not existing if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - File dir = new File(Constants.Path.APP_DIR); - if (!dir.exists() && !dir.mkdirs()) { + if (!Constants.Path.APP_DIR.exists() && !Constants.Path.APP_DIR.mkdirs()) { // ignore this for now, it's not crucial // that the directory doesn't exist at this point } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java index 16ef28311..ae9438148 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java @@ -30,7 +30,6 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -39,9 +38,10 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import java.io.File; + public class ExportHelper { - protected FileDialogFragment mFileDialog; - protected String mExportFilename; + protected File mExportFile; ActionBarActivity mActivity; @@ -68,47 +68,30 @@ public class ExportHelper { /** * Show dialog where to export keys */ - public void showExportKeysDialog(final long[] masterKeyIds, final String exportFilename, + public void showExportKeysDialog(final long[] masterKeyIds, final File exportFile, final boolean showSecretCheckbox) { - mExportFilename = exportFilename; - - // Message is received after file is selected - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == FileDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); - - exportKeys(masterKeyIds, data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED)); - } - } - }; + mExportFile = exportFile; - // Create a new Messenger for the communication back - final Messenger messenger = new Messenger(returnHandler); - - DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { - public void run() { - 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; + 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); + } - mFileDialog = FileDialogFragment.newInstance(messenger, title, message, - exportFilename, checkMsg); + String message = mActivity.getString(R.string.specify_file_to_export_to); + String checkMsg = showSecretCheckbox ? + mActivity.getString(R.string.also_export_secret_keys) : null; - mFileDialog.show(mActivity.getSupportFragmentManager(), "fileDialog"); + FileHelper.saveFile(new FileHelper.FileDialogCallback() { + @Override + public void onFileSelected(File file, boolean checked) { + mExportFile = file; + exportKeys(masterKeyIds, checked); } - }); + }, mActivity.getSupportFragmentManager() ,title, message, exportFile, checkMsg); } /** @@ -125,7 +108,7 @@ public class ExportHelper { // fill values for this action Bundle data = new Bundle(); - data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFilename); + data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFile.getAbsolutePath()); data.putBoolean(KeychainIntentService.EXPORT_SECRET, exportSecret); if (masterKeyIds == null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index e0c94b947..2898c7030 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -26,12 +26,19 @@ import android.database.Cursor; 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.OpenableColumns; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; import android.widget.Toast; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; + +import java.io.File; public class FileHelper { @@ -55,25 +62,18 @@ public class FileHelper { * Opens the preferred installed file manager on Android and shows a toast if no manager is * installed. * - * @param activity - * @param filename default selected file, not supported by all file managers + * @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(Activity activity, String filename, String mimeType, int requestCode) { - Intent intent = buildFileIntent(filename, mimeType); - - try { - activity.startActivityForResult(intent, requestCode); - } catch (ActivityNotFoundException e) { - // No compatible file manager was found. - Toast.makeText(activity, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show(); - } - } + 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); - public static void openFile(Fragment fragment, String filename, String mimeType, int requestCode) { - Intent intent = buildFileIntent(filename, mimeType); + intent.setData(last); + intent.setType(mimeType); try { fragment.startActivityForResult(intent, requestCode); @@ -84,19 +84,62 @@ public class FileHelper { } } + 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); + } + /** * Opens the storage browser on Android 4.4 or later for opening a file * @param fragment - * @param last default selected file * @param mimeType can be text/plain for example * @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, Uri last, String mimeType, int requestCode) { + public static void openDocument(Fragment fragment, String mimeType, int requestCode) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setData(last); intent.setType(mimeType); fragment.startActivityForResult(intent, requestCode); } @@ -104,66 +147,42 @@ public class FileHelper { /** * Opens the storage browser on Android 4.4 or later for saving a file * @param fragment - * @param last default selected file * @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, Uri last, String mimeType, int requestCode) { + 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.setData(last); 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); } - private static Intent buildFileIntent(String filename, String mimeType) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - - intent.setData(Uri.parse("file://" + filename)); - intent.setType(mimeType); - - return intent; - } + 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); - /** - * Get a file path from a Uri. - *

- * from https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/ - * afilechooser/utils/FileUtils.java - * - * @param context - * @param uri - * @return - * @author paulburke - */ - public static String getPath(Context context, Uri uri) { - Log.d(Constants.TAG + " File -", - "Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment() - + ", Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme: " - + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: " - + uri.getPathSegments().toString()); - - if ("content".equalsIgnoreCase(uri.getScheme())) { - String[] projection = {"_data"}; - Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); - try { - if (cursor != null && cursor.moveToFirst()) { - int columnIndex = cursor.getColumnIndexOrThrow("_data"); - return cursor.getString(columnIndex); - } - } catch (Exception e) { - // Eat it - } finally { - if (cursor != null) { - cursor.close(); + if (cursor != null) { + if (cursor.moveToNext()) { + filename = cursor.getString(0); } + cursor.close(); } - } else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); + } 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; + } - return null; + public static interface FileDialogCallback { + public void onFileSelected(File file, boolean checked); } } 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 e1514b16f..a2676b1a4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -139,6 +139,7 @@ public class KeychainIntentService extends IntentService // export key public static final String EXPORT_OUTPUT_STREAM = "export_output_stream"; public static final String EXPORT_FILENAME = "export_filename"; + public static final String EXPORT_URI = "export_uri"; public static final String EXPORT_SECRET = "export_secret"; public static final String EXPORT_ALL = "export_all"; public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "export_key_ring_id"; @@ -393,13 +394,16 @@ public class KeychainIntentService extends IntentService boolean exportSecret = data.getBoolean(EXPORT_SECRET, false); long[] masterKeyIds = data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID); String outputFile = data.getString(EXPORT_FILENAME); + Uri outputUri = data.getParcelable(EXPORT_URI); // If not exporting all keys get the masterKeyIds of the keys to export from the intent boolean exportAll = data.getBoolean(EXPORT_ALL); - // check if storage is ready - if (!FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready)); + if (outputFile != null) { + // check if storage is ready + if (!FileHelper.isStorageMounted(outputFile)) { + throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready)); + } } ArrayList publicMasterKeyIds = new ArrayList(); @@ -431,12 +435,19 @@ public class KeychainIntentService extends IntentService } } + OutputStream outStream; + if (outputFile != null) { + outStream = new FileOutputStream(outputFile); + } else { + outStream = getContentResolver().openOutputStream(outputUri); + } + PgpImportExport pgpImportExport = new PgpImportExport(this, this, this); Bundle resultData = pgpImportExport .exportKeyRings(publicMasterKeyIds, secretMasterKeyIds, - new FileOutputStream(outputFile)); + outStream); - if (mIsCanceled) { + if (mIsCanceled && outputFile != null) { boolean isDeleted = new File(outputFile).delete(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 5b21be6e4..33659f3e5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -23,11 +23,9 @@ import android.net.Uri; import android.os.Bundle; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; -import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.util.Log; @@ -114,7 +112,7 @@ public class DecryptActivity extends DrawerActivity { } else { // Binary via content provider (could also be files) // override uri to get stream from send - uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); + uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); action = ACTION_DECRYPT; } } else if (Intent.ACTION_VIEW.equals(action)) { @@ -155,21 +153,8 @@ public class DecryptActivity extends DrawerActivity { } } } else if (ACTION_DECRYPT.equals(action) && uri != null) { - // get file path from uri - String path = FileHelper.getPath(this, uri); - - if (path != null) { - mFileFragmentBundle.putString(DecryptFileFragment.ARG_FILENAME, path); - mSwitchToTab = PAGER_TAB_FILE; - } else { - Log.e(Constants.TAG, - "Direct binary data without actual file in filesystem is not supported. " + - "Please use the Remote Service API!"); - Toast.makeText(this, R.string.error_only_files_are_supported, Toast.LENGTH_LONG) - .show(); - // end activity - finish(); - } + mFileFragmentBundle.putParcelable(DecryptFileFragment.ARG_URI, uri); + mSwitchToTab = PAGER_TAB_FILE; } else { Log.e(Constants.TAG, "Include the extra 'text' or an Uri with setData() in your Intent!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 28a465436..3df3b24b2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -20,21 +20,17 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.os.Message; import android.os.Messenger; -import android.provider.OpenableColumns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.EditText; +import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; -import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -44,29 +40,26 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.util.Notify; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; import org.sufficientlysecure.keychain.util.Log; import java.io.File; public class DecryptFileFragment extends DecryptFragment { - public static final String ARG_FILENAME = "filename"; + public static final String ARG_URI = "uri"; - private static final int RESULT_CODE_FILE = 0x00007003; + private static final int REQUEST_CODE_INPUT = 0x00007003; + private static final int REQUEST_CODE_OUTPUT = 0x00007007; // view - private EditText mFilename; + private TextView mFilename; private CheckBox mDeleteAfter; private BootstrapButton mBrowse; private View mDecryptButton; - private String mInputFilename = null; + // model private Uri mInputUri = null; - private String mOutputFilename = null; private Uri mOutputUri = null; - private FileDialogFragment mFileDialog; - /** * Inflate the layout for this fragment */ @@ -74,17 +67,17 @@ public class DecryptFileFragment extends DecryptFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false); - mFilename = (EditText) view.findViewById(R.id.decrypt_file_filename); + mFilename = (TextView) view.findViewById(R.id.decrypt_file_filename); mBrowse = (BootstrapButton) view.findViewById(R.id.decrypt_file_browse); mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption); mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { - FileHelper.openDocument(DecryptFileFragment.this, mInputUri, "*/*", RESULT_CODE_FILE); + FileHelper.openDocument(DecryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { - FileHelper.openFile(DecryptFileFragment.this, mFilename.getText().toString(), "*/*", - RESULT_CODE_FILE); + FileHelper.openFile(DecryptFileFragment.this, mInputUri, "*/*", + REQUEST_CODE_INPUT); } } }); @@ -102,78 +95,48 @@ public class DecryptFileFragment extends DecryptFragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - String filename = getArguments().getString(ARG_FILENAME); - if (filename != null) { - mFilename.setText(filename); - } + setInputUri(getArguments().getParcelable(ARG_URI)); } - private String guessOutputFilename() { - File file = new File(mInputFilename); - String filename = file.getName(); - if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) { - filename = filename.substring(0, filename.length() - 4); + private void setInputUri(Uri inputUri) { + if (inputUri == null) { + mInputUri = null; + mFilename.setText(""); + return; } - return Constants.Path.APP_DIR + "/" + filename; + + mInputUri = inputUri; + mFilename.setText(FileHelper.getFilename(getActivity(), mInputUri)); } private void decryptAction() { - String currentFilename = mFilename.getText().toString(); - if (mInputFilename == null || !mInputFilename.equals(currentFilename)) { - mInputUri = null; - mInputFilename = mFilename.getText().toString(); - } - if (mInputUri == null) { - mOutputFilename = guessOutputFilename(); - } - - if (mInputFilename.equals("")) { //AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR); return; } - if (mInputUri == null && mInputFilename.startsWith("file")) { - File file = new File(mInputFilename); - if (!file.exists() || !file.isFile()) { - AppMsg.makeText( - getActivity(), - getString(R.string.error_message, - getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT) - .show(); - return; - } - } - askForOutputFilename(); } - private void askForOutputFilename() { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == FileDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - if (data.containsKey(FileDialogFragment.MESSAGE_DATA_URI)) { - mOutputUri = data.getParcelable(FileDialogFragment.MESSAGE_DATA_URI); - } else { - mOutputFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); - } - decryptStart(null); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - mFileDialog = FileDialogFragment.newInstance(messenger, - getString(R.string.title_decrypt_to_file), - getString(R.string.specify_file_to_decrypt_to), mOutputFilename, null); + private String removeEncryptedAppend(String name) { + if (name.endsWith(".asc") || name.endsWith(".gpg") || name.endsWith(".pgp")) { + return name.substring(0, name.length() - 4); + } + return name; + } - mFileDialog.show(getActivity().getSupportFragmentManager(), "fileDialog"); + private void askForOutputFilename() { + String targetName = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri)); + if (!Constants.KITKAT) { + File file = new File(mInputUri.getPath()); + File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; + File targetFile = new File(parentDir, targetName); + FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file), + getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT); + } else { + FileHelper.saveDocument(this, "*/*", targetName, REQUEST_CODE_OUTPUT); + } } @Override @@ -189,25 +152,13 @@ public class DecryptFileFragment extends DecryptFragment { intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY); // data - Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" - + mOutputFilename + ",mInputUri=" + mInputUri + ", mOutputUri=" - + mOutputUri); + Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - if (mInputUri != null) { - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); - } else { - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_FILE); - data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename); - } + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); + data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); - if (mOutputUri != null) { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); - } else { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_FILE); - data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename); - } + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); + data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); @@ -238,14 +189,9 @@ public class DecryptFileFragment extends DecryptFragment { if (mDeleteAfter.isChecked()) { // Create and show dialog to delete original file - DeleteFileDialogFragment deleteFileDialog; - if (mInputUri != null) { - deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - } else { - deleteFileDialog = DeleteFileDialogFragment - .newInstance(mInputFilename); - } + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); + setInputUri(null); } } } @@ -266,28 +212,17 @@ public class DecryptFileFragment extends DecryptFragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case RESULT_CODE_FILE: { + case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - if (Constants.KITKAT) { - mInputUri = data.getData(); - Cursor cursor = getActivity().getContentResolver().query(mInputUri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); - if (cursor != null) { - if (cursor.moveToNext()) { - mInputFilename = cursor.getString(0); - mFilename.setText(mInputFilename); - } - cursor.close(); - } - } else { - try { - String path = FileHelper.getPath(getActivity(), data.getData()); - Log.d(Constants.TAG, "path=" + path); - - mFilename.setText(path); - } catch (NullPointerException e) { - Log.e(Constants.TAG, "Nullpointer while retrieving path!"); - } - } + setInputUri(data.getData()); + } + return; + } + case REQUEST_CODE_OUTPUT: { + // This happens after output file was selected, so start our operation + if (resultCode == Activity.RESULT_OK && data != null) { + mOutputUri = data.getData(); + decryptStart(null); } return; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 39d4a09bc..e93a63cc8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -23,11 +23,9 @@ import android.net.Uri; import android.os.Bundle; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; -import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.util.Log; @@ -98,11 +96,7 @@ public class EncryptActivity extends DrawerActivity implements @Override public boolean isModeSymmetric() { - if (PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem()) { - return true; - } else { - return false; - } + return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); } @Override @@ -201,7 +195,7 @@ public class EncryptActivity extends DrawerActivity implements } } else { // Files via content provider, override uri and action - uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); + uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); action = ACTION_ENCRYPT; } } @@ -232,23 +226,8 @@ public class EncryptActivity extends DrawerActivity implements mSwitchToContent = PAGER_CONTENT_MESSAGE; } else if (ACTION_ENCRYPT.equals(action) && uri != null) { // encrypt file based on Uri - - // get file path from uri - String path = FileHelper.getPath(this, uri); - - if (path != null) { - mFileFragmentBundle.putString(EncryptFileFragment.ARG_FILENAME, path); - mSwitchToContent = PAGER_CONTENT_FILE; - } else { - Log.e(Constants.TAG, - "Direct binary data without actual file in filesystem is not supported " + - "by Intents. Please use the Remote Service API!" - ); - Toast.makeText(this, R.string.error_only_files_are_supported, - Toast.LENGTH_LONG).show(); - // end activity - finish(); - } + mFileFragmentBundle.putParcelable(EncryptFileFragment.ARG_URI, uri); + mSwitchToContent = PAGER_CONTENT_FILE; } else { Log.e(Constants.TAG, "Include the extra 'text' or an Uri with setData() in your Intent!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 2671e0d40..4da76bdfb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -20,21 +20,19 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; -import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckBox; -import android.widget.EditText; import android.widget.Spinner; +import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; @@ -47,7 +45,6 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; @@ -55,28 +52,25 @@ import org.sufficientlysecure.keychain.util.Log; import java.io.File; public class EncryptFileFragment extends Fragment { - public static final String ARG_FILENAME = "filename"; + public static final String ARG_URI = "uri"; public static final String ARG_ASCII_ARMOR = "ascii_armor"; - private static final int RESULT_CODE_FILE = 0x00007003; + private static final int REQUEST_CODE_INPUT = 0x00007003; + private static final int REQUEST_CODE_OUTPUT = 0x00007007; private EncryptActivityInterface mEncryptInterface; // view private CheckBox mAsciiArmor = null; private Spinner mFileCompression = null; - private EditText mFilename = null; + private TextView mFilename = null; private CheckBox mDeleteAfter = null; private CheckBox mShareAfter = null; private BootstrapButton mBrowse = null; private View mEncryptFile; - private FileDialogFragment mFileDialog; - // model - private String mInputFilename = null; private Uri mInputUri = null; - private String mOutputFilename = null; private Uri mOutputUri = null; @Override @@ -104,15 +98,15 @@ public class EncryptFileFragment extends Fragment { } }); - mFilename = (EditText) view.findViewById(R.id.filename); + mFilename = (TextView) view.findViewById(R.id.filename); mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse); mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { - FileHelper.openDocument(EncryptFileFragment.this, mInputUri, "*/*", RESULT_CODE_FILE); + FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { - FileHelper.openFile(EncryptFileFragment.this, mFilename.getText().toString(), "*/*", - RESULT_CODE_FILE); + FileHelper.openFile(EncryptFileFragment.this, mInputUri, "*/*", + REQUEST_CODE_INPUT); } } }); @@ -154,86 +148,45 @@ public class EncryptFileFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - String filename = getArguments().getString(ARG_FILENAME); - if (filename != null) { - mFilename.setText(filename); - } + setInputUri(getArguments().getParcelable(ARG_URI)); boolean asciiArmor = getArguments().getBoolean(ARG_ASCII_ARMOR); if (asciiArmor) { - mAsciiArmor.setChecked(asciiArmor); + mAsciiArmor.setChecked(true); } } - /** - * Guess output filename based on input path - * - * @param path - * @return Suggestion for output filename - */ - private String guessOutputFilename(String path) { - // output in the same directory but with additional ending - File file = new File(path); - String ending = (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); - String outputFilename = file.getParent() + File.separator + file.getName() + ending; + private void setInputUri(Uri inputUri) { + if (inputUri == null) { + mInputUri = null; + mFilename.setText(""); + return; + } - return outputFilename; + mInputUri = inputUri; + mFilename.setText(FileHelper.getFilename(getActivity(), mInputUri)); } private void showOutputFileDialog() { - // Message is received after file is selected - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == FileDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - if (data.containsKey(FileDialogFragment.MESSAGE_DATA_URI)) { - mOutputUri = data.getParcelable(FileDialogFragment.MESSAGE_DATA_URI); - } else { - mOutputFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); - } - encryptStart(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - mFileDialog = FileDialogFragment.newInstance(messenger, - getString(R.string.title_encrypt_to_file), - getString(R.string.specify_file_to_encrypt_to), mOutputFilename, null); - - mFileDialog.show(getActivity().getSupportFragmentManager(), "fileDialog"); + if (!Constants.KITKAT) { + File file = new File(mInputUri.getPath()); + File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; + String targetName = FileHelper.getFilename( + getActivity(), mInputUri) + (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); + File targetFile = new File(parentDir, targetName); + FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file), + getString(R.string.specify_file_to_encrypt_to), targetFile, REQUEST_CODE_OUTPUT); + } else { + FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), mInputUri) + + (mAsciiArmor.isChecked() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT); + } } private void encryptClicked() { - String currentFilename = mFilename.getText().toString(); - if (mInputFilename == null || !mInputFilename.equals(currentFilename)) { - mInputUri = null; - mInputFilename = mFilename.getText().toString(); - } - if (mInputUri == null) { - mOutputFilename = guessOutputFilename(mInputFilename); - } - - if (mInputFilename.equals("")) { AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); return; } - if (mInputUri == null && !mInputFilename.startsWith("content")) { - File file = new File(mInputFilename); - if (!file.exists() || !file.isFile()) { - AppMsg.makeText( - getActivity(), - getString(R.string.error_message, - getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT) - .show(); - return; - } - } - if (mEncryptInterface.isModeSymmetric()) { // symmetric encryption @@ -287,6 +240,10 @@ public class EncryptFileFragment extends Fragment { } private void encryptStart() { + if (mInputUri == null || mOutputUri == null) { + throw new IllegalStateException("Something went terribly wrong if this happens!"); + } + // Send all information needed to service to edit key in other thread Intent intent = new Intent(getActivity(), KeychainIntentService.class); @@ -295,25 +252,13 @@ public class EncryptFileFragment extends Fragment { // fill values for this action Bundle data = new Bundle(); - Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" - + mOutputFilename + ",mInputUri=" + mInputUri + ", mOutputUri=" - + mOutputUri); + Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - if (mInputUri != null) { - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); - } else { - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_FILE); - data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename); - } + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); + data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); - if (mOutputUri != null) { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); - } else { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_FILE); - data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename); - } + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); + data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); if (mEncryptInterface.isModeSymmetric()) { Log.d(Constants.TAG, "Symmetric encryption enabled!"); @@ -350,25 +295,16 @@ public class EncryptFileFragment extends Fragment { if (mDeleteAfter.isChecked()) { // Create and show dialog to delete original file - DeleteFileDialogFragment deleteFileDialog; - if (mInputUri != null) { - deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - } else { - deleteFileDialog = DeleteFileDialogFragment - .newInstance(mInputFilename); - } + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); + setInputUri(null); } if (mShareAfter.isChecked()) { // Share encrypted file Intent sendFileIntent = new Intent(Intent.ACTION_SEND); sendFileIntent.setType("*/*"); - if (mOutputUri != null) { - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); - } else { - sendFileIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(mOutputFilename)); - } + sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); startActivity(Intent.createChooser(sendFileIntent, getString(R.string.title_share_file))); } @@ -390,28 +326,17 @@ public class EncryptFileFragment extends Fragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case RESULT_CODE_FILE: { + case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - if (Constants.KITKAT) { - mInputUri = data.getData(); - Cursor cursor = getActivity().getContentResolver().query(mInputUri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); - if (cursor != null) { - if (cursor.moveToNext()) { - mInputFilename = cursor.getString(0); - mFilename.setText(mInputFilename); - } - cursor.close(); - } - } else { - try { - String path = FileHelper.getPath(getActivity(), data.getData()); - Log.d(Constants.TAG, "path=" + path); - - mFilename.setText(path); - } catch (NullPointerException e) { - Log.e(Constants.TAG, "Nullpointer while retrieving path!"); - } - } + setInputUri(data.getData()); + } + return; + } + case REQUEST_CODE_OUTPUT: { + // This happens after output file was selected, so start our operation + if (resultCode == Activity.RESULT_OK && data != null) { + mOutputUri = data.getData(); + encryptStart(); } return; } 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 60e5324c5..f24cb379e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java @@ -66,7 +66,7 @@ public class ImportKeysFileFragment extends Fragment { // open .asc or .gpg files // setting it to text/plain prevents Cyanogenmod's file manager from selecting asc // or gpg types! - FileHelper.openFile(ImportKeysFileFragment.this, Constants.Path.APP_DIR + "/", + FileHelper.openFile(ImportKeysFileFragment.this, Uri.fromFile(Constants.Path.APP_DIR), "*/*", REQUEST_CODE_FILE); } }); 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 5eb8ecb8d..48ad13425 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -181,8 +181,8 @@ public class KeyListFragment extends LoaderFragment case R.id.menu_key_list_multi_export: { ids = mAdapter.getCurrentSelectedMasterKeyIds(); ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity()); - mExportHelper.showExportKeysDialog( - ids, Constants.Path.APP_DIR_FILE, mAdapter.isAnySecretSelected()); + mExportHelper.showExportKeysDialog(ids, Constants.Path.APP_DIR_FILE, + mAdapter.isAnySecretSelected()); break; } case R.id.menu_key_list_multi_select_all: { @@ -205,7 +205,7 @@ public class KeyListFragment extends LoaderFragment public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { if (checked) { - mAdapter.setNewSelection(position, checked); + mAdapter.setNewSelection(position, true); } else { mAdapter.removeSelection(position); } @@ -452,7 +452,7 @@ public class KeyListFragment extends LoaderFragment ItemViewHolder holder = new ItemViewHolder(); holder.mMainUserId = (TextView) view.findViewById(R.id.mainUserId); holder.mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - holder.mStatusDivider = (View) view.findViewById(R.id.status_divider); + holder.mStatusDivider = view.findViewById(R.id.status_divider); holder.mStatusLayout = (FrameLayout) view.findViewById(R.id.status_layout); holder.mButton = (ImageButton) view.findViewById(R.id.edit); holder.mRevoked = (TextView) view.findViewById(R.id.revoked); 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 1912b6e7d..6dc6990e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -312,8 +311,7 @@ public class ViewKeyActivity extends ActionBarActivity implements exportHelper.showExportKeysDialog( new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)}, - Constants.Path.APP_DIR_FILE, - ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) == 1) + Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) == 1) ); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index cae6cf043..f9111d885 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -18,40 +18,20 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Dialog; -import android.app.ProgressDialog; import android.content.DialogInterface; -import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; import android.provider.DocumentsContract; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; -import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.helper.FileHelper; public class DeleteFileDialogFragment extends DialogFragment { - private static final String ARG_DELETE_FILE = "delete_file"; private static final String ARG_DELETE_URI = "delete_uri"; - /** - * Creates new instance of this delete file dialog fragment - */ - public static DeleteFileDialogFragment newInstance(String deleteFile) { - DeleteFileDialogFragment frag = new DeleteFileDialogFragment(); - Bundle args = new Bundle(); - - args.putString(ARG_DELETE_FILE, deleteFile); - - frag.setArguments(args); - - return frag; - } - /** * Creates new instance of this delete file dialog fragment */ @@ -74,14 +54,14 @@ public class DeleteFileDialogFragment extends DialogFragment { final FragmentActivity activity = getActivity(); final Uri deleteUri = getArguments().containsKey(ARG_DELETE_URI) ? getArguments().getParcelable(ARG_DELETE_URI) : null; - final String deleteFile = getArguments().getString(ARG_DELETE_FILE); + String deleteFilename = FileHelper.getFilename(getActivity(), deleteUri); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); alert.setIcon(R.drawable.ic_dialog_alert_holo_light); alert.setTitle(R.string.warning); - alert.setMessage(this.getString(R.string.file_delete_confirmation, deleteFile)); + alert.setMessage(this.getString(R.string.file_delete_confirmation, deleteFilename)); alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -89,12 +69,14 @@ public class DeleteFileDialogFragment extends DialogFragment { public void onClick(DialogInterface dialog, int id) { dismiss(); - if (deleteUri != null) { + if (Constants.KITKAT) { // We can not securely delete Documents, so just use usual delete on them - DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri); - return; + if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) return; } + // TODO!!! We can't delete files from Uri without trying to find it's real path + + /* // Send all information needed to service to edit key in other thread Intent intent = new Intent(activity, KeychainIntentService.class); @@ -102,7 +84,6 @@ public class DeleteFileDialogFragment extends DialogFragment { Bundle data = new Bundle(); intent.setAction(KeychainIntentService.ACTION_DELETE_FILE_SECURELY); - data.putString(KeychainIntentService.DELETE_FILE, deleteFile); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); ProgressDialogFragment deletingDialog = ProgressDialogFragment.newInstance( @@ -134,6 +115,7 @@ public class DeleteFileDialogFragment extends DialogFragment { // start service with intent activity.startService(intent); + */ } }); alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java index 10a24ddf0..c02c37055 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java @@ -23,13 +23,11 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; -import android.provider.OpenableColumns; import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; @@ -39,11 +37,17 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; +import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.util.Log; +import java.io.File; + +/** + * This is a file chooser dialog no longer used with KitKat + */ public class FileDialogFragment extends DialogFragment { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_TITLE = "title"; @@ -53,8 +57,7 @@ public class FileDialogFragment extends DialogFragment { public static final int MESSAGE_OKAY = 1; - public static final String MESSAGE_DATA_URI = "uri"; - public static final String MESSAGE_DATA_FILENAME = "filename"; + public static final String MESSAGE_DATA_FILE = "file"; public static final String MESSAGE_DATA_CHECKED = "checked"; private Messenger mMessenger; @@ -64,8 +67,7 @@ public class FileDialogFragment extends DialogFragment { private CheckBox mCheckBox; private TextView mMessageTextView; - private String mOutputFilename; - private Uri mOutputUri; + private File mFile; private static final int REQUEST_CODE = 0x00007004; @@ -73,14 +75,14 @@ public class FileDialogFragment extends DialogFragment { * Creates new instance of this file dialog fragment */ public static FileDialogFragment newInstance(Messenger messenger, String title, String message, - String defaultFile, String checkboxText) { + File defaultFile, String checkboxText) { FileDialogFragment frag = new FileDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); args.putString(ARG_TITLE, title); args.putString(ARG_MESSAGE, message); - args.putString(ARG_DEFAULT_FILE, defaultFile); + args.putString(ARG_DEFAULT_FILE, defaultFile.getAbsolutePath()); args.putString(ARG_CHECKBOX_TEXT, checkboxText); frag.setArguments(args); @@ -99,7 +101,11 @@ public class FileDialogFragment extends DialogFragment { String title = getArguments().getString(ARG_TITLE); String message = getArguments().getString(ARG_MESSAGE); - mOutputFilename = getArguments().getString(ARG_DEFAULT_FILE); + mFile = new File(getArguments().getString(ARG_DEFAULT_FILE)); + if (!mFile.isAbsolute()) { + // We use OK dir by default + mFile = new File(Constants.Path.APP_DIR.getAbsolutePath(), mFile.getName()); + } String checkboxText = getArguments().getString(ARG_CHECKBOX_TEXT); LayoutInflater inflater = (LayoutInflater) activity @@ -113,18 +119,14 @@ public class FileDialogFragment extends DialogFragment { mMessageTextView.setText(message); mFilename = (EditText) view.findViewById(R.id.input); - mFilename.setText(mOutputFilename); + mFilename.setText(mFile.getName()); mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse); mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // only .asc or .gpg files // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc // or gpg types! - if (Constants.KITKAT) { - FileHelper.saveDocument(FileDialogFragment.this, mOutputUri, "*/*", REQUEST_CODE); - } else { - FileHelper.openFile(FileDialogFragment.this, mOutputFilename, "*/*", REQUEST_CODE); - } + FileHelper.openFile(FileDialogFragment.this, Uri.fromFile(mFile), "*/*", REQUEST_CODE); } }); @@ -147,19 +149,23 @@ public class FileDialogFragment extends DialogFragment { dismiss(); String currentFilename = mFilename.getText().toString(); - if (mOutputFilename == null || !mOutputFilename.equals(currentFilename)) { - mOutputUri = null; - mOutputFilename = mFilename.getText().toString(); + if (currentFilename == null || currentFilename.isEmpty()) { + // No file is like pressing cancel, UI: maybe disable positive button in this case? + return; + } + + if (mFile == null || currentFilename.startsWith("/")) { + mFile = new File(currentFilename); + } else if (!mFile.getName().equals(currentFilename)) { + // We update our File object if user changed name! + mFile = new File(mFile.getParentFile(), currentFilename); } boolean checked = mCheckBox.isEnabled() && mCheckBox.isChecked(); // return resulting data back to activity Bundle data = new Bundle(); - if (mOutputUri != null) { - data.putParcelable(MESSAGE_DATA_URI, mOutputUri); - } - data.putString(MESSAGE_DATA_FILENAME, mFilename.getText().toString()); + data.putString(MESSAGE_DATA_FILE, mFile.getAbsolutePath()); data.putBoolean(MESSAGE_DATA_CHECKED, checked); sendMessageToHandler(MESSAGE_OKAY, data); @@ -176,44 +182,17 @@ public class FileDialogFragment extends DialogFragment { return alert.show(); } - /** - * Updates filename in dialog, normally called in onActivityResult in activity using the - * FileDialog - */ - private void setFilename(String filename) { - AlertDialog dialog = (AlertDialog) getDialog(); - EditText filenameEditText = (EditText) dialog.findViewById(R.id.input); - - if (filenameEditText != null) { - filenameEditText.setText(filename); - } - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode & 0xFFFF) { case REQUEST_CODE: { if (resultCode == Activity.RESULT_OK && data != null) { - if (Constants.KITKAT) { - mOutputUri = data.getData(); - Cursor cursor = getActivity().getContentResolver().query(mOutputUri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); - if (cursor != null) { - if (cursor.moveToNext()) { - mOutputFilename = cursor.getString(0); - mFilename.setText(mOutputFilename); - } - cursor.close(); - } + File file = new File(data.getData().getPath()); + if (file.getParentFile().exists()) { + mFile = file; + mFilename.setText(mFile.getName()); } else { - try { - String path = data.getData().getPath(); - Log.d(Constants.TAG, "path=" + path); - - // set filename used in export/import dialogs - setFilename(path); - } catch (NullPointerException e) { - Log.e(Constants.TAG, "Nullpointer while retrieving path!", e); - } + AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); } } -- cgit v1.2.3 From 50e72b196fa8bc97edc63198a9ad73c24770b9df Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Tue, 1 Jul 2014 01:26:50 +0200 Subject: Missing import after merge --- .../org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java index 15d50d7ed..80341aeaa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java @@ -35,6 +35,7 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; +import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; -- cgit v1.2.3 From 35647734104471a6d35bc26a77682dd5531dd5e3 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Tue, 1 Jul 2014 14:50:15 +0200 Subject: Add temporary file storage as discussed in #665 Writable from OpenKeychain, readable worldwide. Should be used to write shared files to it by first creating the file using TemporaryStorageProvider.createFile and then write to the Uri returned. --- .../org/sufficientlysecure/keychain/Constants.java | 2 + .../keychain/KeychainApplication.java | 3 + .../provider/TemporaryStorageProvider.java | 151 +++++++++++++++++++++ .../keychain/util/DatabaseUtil.java | 36 +++++ 4 files changed, 192 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index eeb9fa389..956019605 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -53,6 +53,8 @@ public final class Constants { public static boolean KITKAT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + public static int TEMPFILE_TTL = 24*60*60*1000; // 1 day + public static final class Path { public static final File APP_DIR = new File(Environment.getExternalStorageDirectory(), "OpenKeychain"); public static final File APP_DIR_FILE = new File(APP_DIR, "export.asc"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index be9c1e405..125573b53 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -28,6 +28,7 @@ import android.os.Environment; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.TlsHelper; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; @@ -85,6 +86,8 @@ public class KeychainApplication extends Application { Preferences.getPreferences(this).updateKeyServers(); TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); + + TemporaryStorageProvider.cleanUp(this); } public static void setupAccountAsNeeded(Context context) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java new file mode 100644 index 000000000..9e745215d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -0,0 +1,151 @@ +package org.sufficientlysecure.keychain.provider; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.provider.OpenableColumns; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.DatabaseUtil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class TemporaryStorageProvider extends ContentProvider { + + private static final String DB_NAME = "tempstorage.db"; + private static final String TABLE_FILES = "files"; + private static final String COLUMN_ID = "id"; + private static final String COLUMN_NAME = "name"; + private static final String COLUMN_TIME = "time"; + private static final Uri BASE_URI = Uri.parse("content://org.sufficientlysecure.keychain.tempstorage/"); + private static final int DB_VERSION = 1; + + public static Uri createFile(Context context, String targetName) { + ContentValues contentValues = new ContentValues(); + contentValues.put(COLUMN_NAME, targetName); + return context.getContentResolver().insert(BASE_URI, contentValues); + } + + public static int cleanUp(Context context) { + return context.getContentResolver().delete(BASE_URI, COLUMN_TIME + "< ?", + new String[]{Long.toString(System.currentTimeMillis() - Constants.TEMPFILE_TTL)}); + } + + private class TemporaryStorageDatabase extends SQLiteOpenHelper { + + public TemporaryStorageDatabase(Context context) { + super(context, DB_NAME, null, DB_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" + + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + COLUMN_NAME + " TEXT, " + + COLUMN_TIME + " INTEGER" + + ");"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } + } + + private TemporaryStorageDatabase db; + + private File getFile(Uri uri) throws FileNotFoundException { + try { + return getFile(Integer.parseInt(uri.getLastPathSegment())); + } catch (NumberFormatException e) { + throw new FileNotFoundException(); + } + } + + private File getFile(int id) { + return new File(getContext().getCacheDir(), "temp/" + id); + } + + @Override + public boolean onCreate() { + db = new TemporaryStorageDatabase(getContext()); + return new File(getContext().getCacheDir(), "temp").mkdirs(); + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + File file; + try { + file = getFile(uri); + } catch (FileNotFoundException e) { + return null; + } + Cursor fileName = db.getReadableDatabase().query(TABLE_FILES, new String[]{COLUMN_NAME}, COLUMN_ID + "=?", + new String[]{uri.getLastPathSegment()}, null, null, null); + if (fileName != null) { + if (fileName.moveToNext()) { + MatrixCursor cursor = + new MatrixCursor(new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE, "_data"}); + cursor.newRow().add(fileName.getString(0)).add(file.length()).add(file.getAbsolutePath()); + fileName.close(); + return cursor; + } + fileName.close(); + } + return null; + } + + @Override + public String getType(Uri uri) { + return "*/*"; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + if (!values.containsKey(COLUMN_TIME)) { + values.put(COLUMN_TIME, System.currentTimeMillis()); + } + int insert = (int) db.getWritableDatabase().insert(TABLE_FILES, null, values); + try { + getFile(insert).createNewFile(); + } catch (IOException e) { + return null; + } + return Uri.withAppendedPath(BASE_URI, Long.toString(insert)); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + if (uri.getLastPathSegment() != null) { + selection = DatabaseUtil.concatenateWhere(selection, COLUMN_ID + "=?"); + selectionArgs = DatabaseUtil.appendSelectionArgs(selectionArgs, new String[]{uri.getLastPathSegment()}); + } + Cursor files = db.getReadableDatabase().query(TABLE_FILES, new String[]{COLUMN_ID}, selection, + selectionArgs, null, null, null); + if (files != null) { + while (files.moveToNext()) { + getFile(files.getInt(0)).delete(); + } + files.close(); + return db.getWritableDatabase().delete(TABLE_FILES, selection, selectionArgs); + } + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException("Update not supported"); + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + return openFileHelper(uri, mode); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java new file mode 100644 index 000000000..c18e5cabd --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java @@ -0,0 +1,36 @@ +package org.sufficientlysecure.keychain.util; + +import android.text.TextUtils; + +/** + * Shamelessly copied from android.database.DatabaseUtils + */ +public class DatabaseUtil { + /** + * Concatenates two SQL WHERE clauses, handling empty or null values. + */ + public static String concatenateWhere(String a, String b) { + if (TextUtils.isEmpty(a)) { + return b; + } + if (TextUtils.isEmpty(b)) { + return a; + } + + return "(" + a + ") AND (" + b + ")"; + } + + /** + * Appends one set of selection args to another. This is useful when adding a selection + * argument to a user provided set. + */ + public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) { + if (originalValues == null || originalValues.length == 0) { + return newValues; + } + String[] result = new String[originalValues.length + newValues.length ]; + System.arraycopy(originalValues, 0, result, 0, originalValues.length); + System.arraycopy(newValues, 0, result, originalValues.length, newValues.length); + return result; + } +} -- cgit v1.2.3 From 93eae114eac566a9ed2da6275c147b66ca480305 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Wed, 2 Jul 2014 00:34:21 +0200 Subject: Encrypt/Decrypt UI work --- .../keychain/provider/CachedPublicKeyRing.java | 14 ++--- .../keychain/ui/DecryptFileFragment.java | 5 +- .../keychain/ui/EncryptActivity.java | 11 ++++ .../keychain/ui/EncryptActivityInterface.java | 1 + .../keychain/ui/EncryptAsymmetricFragment.java | 24 +++++++-- .../keychain/ui/EncryptFileFragment.java | 48 +++++++++++++----- .../keychain/ui/EncryptMessageFragment.java | 17 ++++++- .../ui/dialog/DeleteFileDialogFragment.java | 59 ++++++---------------- 8 files changed, 106 insertions(+), 73 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 48d40430a..52ca71679 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -62,7 +62,7 @@ public class CachedPublicKeyRing extends KeyRing { public String getPrimaryUserId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING); return (String) data; } catch(ProviderHelper.NotFoundException e) { @@ -73,7 +73,7 @@ public class CachedPublicKeyRing extends KeyRing { public boolean isRevoked() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.IS_REVOKED, ProviderHelper.FIELD_TYPE_INTEGER); return (Long) data > 0; } catch(ProviderHelper.NotFoundException e) { @@ -84,7 +84,7 @@ public class CachedPublicKeyRing extends KeyRing { public boolean canCertify() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.CAN_CERTIFY, ProviderHelper.FIELD_TYPE_INTEGER); return (Long) data > 0; } catch(ProviderHelper.NotFoundException e) { @@ -106,7 +106,7 @@ public class CachedPublicKeyRing extends KeyRing { public boolean hasEncrypt() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.HAS_ENCRYPT, ProviderHelper.FIELD_TYPE_INTEGER); return (Long) data > 0; } catch(ProviderHelper.NotFoundException e) { @@ -128,7 +128,7 @@ public class CachedPublicKeyRing extends KeyRing { public boolean hasSign() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.HAS_SIGN, ProviderHelper.FIELD_TYPE_INTEGER); return (Long) data > 0; } catch(ProviderHelper.NotFoundException e) { @@ -139,7 +139,7 @@ public class CachedPublicKeyRing extends KeyRing { public int getVerified() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.VERIFIED, ProviderHelper.FIELD_TYPE_INTEGER); return (Integer) data; } catch(ProviderHelper.NotFoundException e) { @@ -150,7 +150,7 @@ public class CachedPublicKeyRing extends KeyRing { public boolean hasAnySecret() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.HAS_ANY_SECRET, ProviderHelper.FIELD_TYPE_INTEGER); return (Long) data > 0; } catch(ProviderHelper.NotFoundException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 430f85b6f..520ef7567 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -29,7 +29,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; -import android.widget.ImageButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -52,7 +51,6 @@ public class DecryptFileFragment extends DecryptFragment { // view private TextView mFilename; private CheckBox mDeleteAfter; - private ImageButton mBrowse; private View mDecryptButton; // model @@ -67,10 +65,9 @@ public class DecryptFileFragment extends DecryptFragment { View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false); mFilename = (TextView) view.findViewById(R.id.decrypt_file_filename); - mBrowse = (ImageButton) view.findViewById(R.id.decrypt_file_browse); mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption); mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); - mBrowse.setOnClickListener(new View.OnClickListener() { + view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(DecryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index e93a63cc8..c77fe9ab8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -70,6 +70,7 @@ public class EncryptActivity extends DrawerActivity implements // model used by message and file fragments private long mEncryptionKeyIds[] = null; + private String mEncryptionUserIds[] = null; private long mSigningKeyId = Constants.key.none; private String mPassphrase; private String mPassphraseAgain; @@ -84,6 +85,11 @@ public class EncryptActivity extends DrawerActivity implements mEncryptionKeyIds = encryptionKeyIds; } + @Override + public void onEncryptionUserSelected(String[] encryptionUserIds) { + mEncryptionUserIds = encryptionUserIds; + } + @Override public void onPassphraseUpdate(String passphrase) { mPassphrase = passphrase; @@ -109,6 +115,11 @@ public class EncryptActivity extends DrawerActivity implements return mEncryptionKeyIds; } + @Override + public String[] getEncryptionUsers() { + return mEncryptionUserIds; + } + @Override public String getPassphrase() { return mPassphrase; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index 0786b3a16..ca2ee3b55 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -23,6 +23,7 @@ public interface EncryptActivityInterface { public long getSignatureKey(); public long[] getEncryptionKeys(); + public String[] getEncryptionUsers(); public String getPassphrase(); public String getPassphraseAgain(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 51963e963..be845f05e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -59,12 +59,15 @@ public class EncryptAsymmetricFragment extends Fragment { // model private long mSecretKeyId = Constants.key.none; private long mEncryptionKeyIds[] = null; + private String mEncryptionUserIds[] = null; // Container Activity must implement this interface public interface OnAsymmetricKeySelection { public void onSigningKeySelected(long signingKeyId); public void onEncryptionKeysSelected(long[] encryptionKeyIds); + + public void onEncryptionUserSelected(String[] encryptionUserIds); } @Override @@ -91,6 +94,13 @@ public class EncryptAsymmetricFragment extends Fragment { updateView(); } + private void setEncryptionUserIds(String[] encryptionUserIds) { + mEncryptionUserIds = encryptionUserIds; + // update key selection in EncryptActivity + mKeySelectionListener.onEncryptionUserSelected(encryptionUserIds); + updateView(); + } + /** * Inflate the layout for this fragment */ @@ -159,12 +169,14 @@ public class EncryptAsymmetricFragment extends Fragment { if (preselectedEncryptionKeyIds != null) { Vector goodIds = new Vector(); - for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { + Vector goodUserIds = new Vector(); + for (long preselectedId : preselectedEncryptionKeyIds) { try { - long id = providerHelper.getCachedPublicKeyRing( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - preselectedEncryptionKeyIds[i]) - ).getMasterKeyId(); + CachedPublicKeyRing ring = providerHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(preselectedId)); + long id = ring.getMasterKeyId(); + ring.getSplitPrimaryUserId(); + goodUserIds.add(ring.getPrimaryUserId()); goodIds.add(id); } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); @@ -176,6 +188,7 @@ public class EncryptAsymmetricFragment extends Fragment { keyIds[i] = goodIds.get(i); } setEncryptionKeyIds(keyIds); + setEncryptionUserIds(goodUserIds.toArray(new String[goodUserIds.size()])); } } } @@ -249,6 +262,7 @@ public class EncryptAsymmetricFragment extends Fragment { Bundle bundle = data.getExtras(); setEncryptionKeyIds(bundle .getLongArray(SelectPublicKeyActivity.RESULT_EXTRA_MASTER_KEY_IDS)); + setEncryptionUserIds(bundle.getStringArray(SelectPublicKeyActivity.RESULT_EXTRA_USER_IDS)); } break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 2fabeb82c..3111e5c3e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -33,12 +33,13 @@ import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.Spinner; import android.widget.TextView; -import android.widget.ImageButton; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -50,6 +51,8 @@ import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.io.File; +import java.util.HashSet; +import java.util.Set; public class EncryptFileFragment extends Fragment { public static final String ARG_URI = "uri"; @@ -65,8 +68,7 @@ public class EncryptFileFragment extends Fragment { private Spinner mFileCompression = null; private TextView mFilename = null; private CheckBox mDeleteAfter = null; - private CheckBox mShareAfter = null; - private ImageButton mBrowse = null; + private View mShareFile; private View mEncryptFile; // model @@ -94,13 +96,19 @@ public class EncryptFileFragment extends Fragment { mEncryptFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - encryptClicked(); + encryptClicked(false); + } + }); + mShareFile = view.findViewById(R.id.action_encrypt_share); + mShareFile.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + encryptClicked(true); } }); mFilename = (TextView) view.findViewById(R.id.filename); - mBrowse = (ImageButton) view.findViewById(R.id.btn_browse); - mBrowse.setOnClickListener(new View.OnClickListener() { + view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); @@ -136,7 +144,6 @@ public class EncryptFileFragment extends Fragment { } mDeleteAfter = (CheckBox) view.findViewById(R.id.deleteAfterEncryption); - mShareAfter = (CheckBox) view.findViewById(R.id.shareAfterEncryption); mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmor); mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmor()); @@ -181,7 +188,7 @@ public class EncryptFileFragment extends Fragment { } } - private void encryptClicked() { + private void encryptClicked(boolean share) { if (mInputUri == null) { AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); return; @@ -236,10 +243,17 @@ public class EncryptFileFragment extends Fragment { } } - showOutputFileDialog(); + if (share) { + String targetName = FileHelper.getFilename(getActivity(), mInputUri) + + (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); + mOutputUri = TemporaryStorageProvider.createFile(getActivity(), targetName); + encryptStart(true); + } else { + showOutputFileDialog(); + } } - private void encryptStart() { + private void encryptStart(final boolean share) { if (mInputUri == null || mOutputUri == null) { throw new IllegalStateException("Something went terribly wrong if this happens!"); } @@ -300,11 +314,21 @@ public class EncryptFileFragment extends Fragment { setInputUri(null); } - if (mShareAfter.isChecked()) { + if (share) { // Share encrypted file Intent sendFileIntent = new Intent(Intent.ACTION_SEND); sendFileIntent.setType("*/*"); sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); + if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { + Set users = new HashSet(); + for (String user : mEncryptInterface.getEncryptionUsers()) { + String[] userId = KeyRing.splitUserId(user); + if (userId[1] != null) { + users.add(userId[1]); + } + } + sendFileIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + } startActivity(Intent.createChooser(sendFileIntent, getString(R.string.title_share_file))); } @@ -336,7 +360,7 @@ public class EncryptFileFragment extends Fragment { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { mOutputUri = data.getData(); - encryptStart(); + encryptStart(false); } return; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index 8a6103b16..e4f63089f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -36,12 +36,17 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + public class EncryptMessageFragment extends Fragment { public static final String ARG_TEXT = "text"; @@ -235,7 +240,17 @@ public class EncryptMessageFragment extends Fragment { // Type is set to text/plain so that encrypted messages can // be sent with Whatsapp, Hangouts, SMS etc... sendIntent.setType("text/plain"); - + Log.d(Constants.TAG, "encrypt to:" + Arrays.toString(mEncryptInterface.getEncryptionUsers())); + if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { + Set users = new HashSet(); + for (String user : mEncryptInterface.getEncryptionUsers()) { + String[] userId = KeyRing.splitUserId(user); + if (userId[1] != null) { + users.add(userId[1]); + } + } + sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + } sendIntent.putExtra(Intent.EXTRA_TEXT, output); startActivity(Intent.createChooser(sendIntent, getString(R.string.title_share_with))); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index f9111d885..27ce4faee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -25,6 +25,7 @@ import android.provider.DocumentsContract; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; +import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -53,8 +54,8 @@ public class DeleteFileDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { final FragmentActivity activity = getActivity(); - final Uri deleteUri = getArguments().containsKey(ARG_DELETE_URI) ? getArguments().getParcelable(ARG_DELETE_URI) : null; - String deleteFilename = FileHelper.getFilename(getActivity(), deleteUri); + final Uri deleteUri = getArguments().getParcelable(ARG_DELETE_URI); + final String deleteFilename = FileHelper.getFilename(getActivity(), deleteUri); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); @@ -69,53 +70,23 @@ public class DeleteFileDialogFragment extends DialogFragment { public void onClick(DialogInterface dialog, int id) { dismiss(); + // We can not securely delete Uris, so just use usual delete on them if (Constants.KITKAT) { - // We can not securely delete Documents, so just use usual delete on them - if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) return; - } - - // TODO!!! We can't delete files from Uri without trying to find it's real path - - /* - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(activity, KeychainIntentService.class); - - // fill values for this action - Bundle data = new Bundle(); - - intent.setAction(KeychainIntentService.ACTION_DELETE_FILE_SECURELY); - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - ProgressDialogFragment deletingDialog = ProgressDialogFragment.newInstance( - getString(R.string.progress_deleting_securely), - ProgressDialog.STYLE_HORIZONTAL, - false, - null); - - // Message is received after deleting is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = - new KeychainIntentServiceHandler(activity, deletingDialog) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Toast.makeText(activity, R.string.file_delete_successful, - Toast.LENGTH_SHORT).show(); - } + if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) { + Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + return; } - }; + } - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) { + Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + return; + } - // show progress dialog - deletingDialog.show(activity.getSupportFragmentManager(), "deletingDialog"); + Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, deleteFilename), Toast.LENGTH_SHORT).show(); - // start service with intent - activity.startService(intent); - */ + // TODO: We can't delete that file... + // If possible we should find out if deletion is possible before even showing the option to do so. } }); alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { -- cgit v1.2.3 From 51a4b0466ba1e1c1c72d9d8112c28628d1efc84b Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 3 Jul 2014 00:34:41 +0200 Subject: Add support for multiple input/output URIs to KeychainIntentService --- .../keychain/service/KeychainIntentService.java | 91 +++++++++++++--------- 1 file changed, 56 insertions(+), 35 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 a2676b1a4..d87f98775 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -109,6 +109,9 @@ public class KeychainIntentService extends IntentService public static final int IO_BYTES = 1; public static final int IO_FILE = 2; // This was misleadingly TARGET_URI before! public static final int IO_URI = 3; + public static final int IO_URIS = 4; + + public static final String SELECTED_URI = "selected_uri"; // encrypt public static final String ENCRYPT_SIGNATURE_KEY_ID = "secret_key_id"; @@ -118,8 +121,10 @@ public class KeychainIntentService extends IntentService public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes"; public static final String ENCRYPT_INPUT_FILE = "input_file"; public static final String ENCRYPT_INPUT_URI = "input_uri"; + public static final String ENCRYPT_INPUT_URIS = "input_uris"; public static final String ENCRYPT_OUTPUT_FILE = "output_file"; public static final String ENCRYPT_OUTPUT_URI = "output_uri"; + public static final String ENCRYPT_OUTPUT_URIS = "output_uris"; public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase"; // decrypt/verify @@ -220,6 +225,7 @@ public class KeychainIntentService extends IntentService try { /* Input */ int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET); + Bundle resultData = new Bundle(); long signatureKeyId = data.getLong(ENCRYPT_SIGNATURE_KEY_ID); String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE); @@ -227,44 +233,48 @@ public class KeychainIntentService extends IntentService boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR); long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS); int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID); - InputData inputData = createEncryptInputData(data); - OutputStream outStream = createCryptOutputStream(data); - - /* Operation */ - PgpSignEncrypt.Builder builder = - new PgpSignEncrypt.Builder( - new ProviderHelper(this), - PgpHelper.getFullVersion(this), - inputData, outStream); - builder.setProgressable(this); + int urisCount = data.containsKey(ENCRYPT_INPUT_URIS) ? data.getParcelableArrayList(ENCRYPT_INPUT_URIS).size() : 1; + for (int i = 0; i < urisCount; i++) { + data.putInt(SELECTED_URI, i); + InputData inputData = createEncryptInputData(data); + OutputStream outStream = createCryptOutputStream(data); + + /* Operation */ + PgpSignEncrypt.Builder builder = + new PgpSignEncrypt.Builder( + new ProviderHelper(this), + PgpHelper.getFullVersion(this), + inputData, outStream); + builder.setProgressable(this); + + builder.setEnableAsciiArmorOutput(useAsciiArmor) + .setCompressionId(compressionId) + .setSymmetricEncryptionAlgorithm( + Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) + .setSignatureForceV3(Preferences.getPreferences(this).getForceV3Signatures()) + .setEncryptionMasterKeyIds(encryptionKeyIds) + .setSymmetricPassphrase(symmetricPassphrase) + .setSignatureMasterKeyId(signatureKeyId) + .setEncryptToSigner(true) + .setSignatureHashAlgorithm( + Preferences.getPreferences(this).getDefaultHashAlgorithm()) + .setSignaturePassphrase( + PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)); + + // this assumes that the bytes are cleartext (valid for current implementation!) + if (source == IO_BYTES) { + builder.setCleartextInput(true); + } - builder.setEnableAsciiArmorOutput(useAsciiArmor) - .setCompressionId(compressionId) - .setSymmetricEncryptionAlgorithm( - Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) - .setSignatureForceV3(Preferences.getPreferences(this).getForceV3Signatures()) - .setEncryptionMasterKeyIds(encryptionKeyIds) - .setSymmetricPassphrase(symmetricPassphrase) - .setSignatureMasterKeyId(signatureKeyId) - .setEncryptToSigner(true) - .setSignatureHashAlgorithm( - Preferences.getPreferences(this).getDefaultHashAlgorithm()) - .setSignaturePassphrase( - PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)); - - // this assumes that the bytes are cleartext (valid for current implementation!) - if (source == IO_BYTES) { - builder.setCleartextInput(true); - } + builder.build().execute(); - builder.build().execute(); + outStream.close(); - outStream.close(); + /* Output */ - /* Output */ + finalizeEncryptOutputStream(data, resultData, outStream); - Bundle resultData = new Bundle(); - finalizeEncryptOutputStream(data, resultData, outStream); + } OtherHelper.logDebugBundle(resultData, "resultData"); @@ -688,8 +698,13 @@ public class KeychainIntentService extends IntentService Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); // InputStream - InputStream in = getContentResolver().openInputStream(providerUri); - return new InputData(in, 0); + return new InputData(getContentResolver().openInputStream(providerUri), 0); + + case IO_URIS: + providerUri = data.getParcelableArrayList(ENCRYPT_INPUT_URIS).get(data.getInt(SELECTED_URI)); + + // InputStream + return new InputData(getContentResolver().openInputStream(providerUri), 0); default: throw new PgpGeneralException("No target choosen!"); @@ -719,6 +734,11 @@ public class KeychainIntentService extends IntentService return getContentResolver().openOutputStream(providerUri); + case IO_URIS: + providerUri = data.getParcelableArrayList(ENCRYPT_OUTPUT_URIS).get(data.getInt(SELECTED_URI)); + + return getContentResolver().openOutputStream(providerUri); + default: throw new PgpGeneralException("No target choosen!"); } @@ -744,6 +764,7 @@ public class KeychainIntentService extends IntentService break; case IO_URI: + case IO_URIS: // nothing, output was written, just send okay and verification bundle break; -- cgit v1.2.3 From 1b0666e9de5caea14997a3e638a6209b45c97d60 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 6 Jul 2014 02:10:35 +0200 Subject: Many changes to file ... and still incomplete - Multi file - Reworked UI --- .../keychain/helper/ContactHelper.java | 14 ++ .../keychain/helper/FileHelper.java | 41 +++++ .../keychain/provider/CachedPublicKeyRing.java | 62 ++++++- .../keychain/provider/ProviderHelper.java | 4 + .../keychain/ui/EncryptActivity.java | 77 +++++++- .../keychain/ui/EncryptActivityInterface.java | 2 + .../keychain/ui/EncryptAsymmetricFragment.java | 105 +++++++---- .../keychain/ui/EncryptFileFragment.java | 190 +++++++++++++------ .../ui/widget/EncryptKeyCompletionView.java | 204 +++++++++++++++++++++ .../ui/widget/NoSwipeWrapContentViewPager.java | 44 +++++ 10 files changed, 635 insertions(+), 108 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index e639824ec..1b9ef57b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -21,6 +21,8 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.content.*; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.provider.ContactsContract; @@ -33,6 +35,7 @@ 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.*; public class ContactHelper { @@ -232,6 +235,17 @@ public class ContactHelper { return null; } + public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { + 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); + } + /** * Write the current Keychain to the contact db */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index 2898c7030..e42c7987b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -23,22 +23,28 @@ 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.FragmentActivity; import android.support.v4.app.FragmentManager; import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; 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 { @@ -182,6 +188,41 @@ public class FileHelper { return filename; } + public static long getFileSize(Context context, Uri uri) { + long size = -1; + 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 (Constants.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/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 52ca71679..bc7221d13 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -1,5 +1,6 @@ package org.sufficientlysecure.keychain.provider; +import android.database.Cursor; import android.net.Uri; import org.sufficientlysecure.keychain.Constants; @@ -33,6 +34,7 @@ public class CachedPublicKeyRing extends KeyRing { mUri = uri; } + @Override public long getMasterKeyId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -59,6 +61,17 @@ public class CachedPublicKeyRing extends KeyRing { return getMasterKeyId(); } + public byte[] getFingerprint() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); + return (byte[]) data; + } catch (ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + @Override public String getPrimaryUserId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -70,6 +83,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public boolean isRevoked() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -81,6 +95,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public boolean canCertify() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -92,17 +107,28 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public long getEncryptId() throws PgpGeneralException { try { - Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, - ProviderHelper.FIELD_TYPE_INTEGER); - return (Long) data; - } catch(ProviderHelper.NotFoundException e) { + Cursor subkeys = getSubkeys(); + if (subkeys != null) { + try { + while (subkeys.moveToNext()) { + if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_ENCRYPT)) != 0) { + return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); + } + } + } finally { + subkeys.close(); + } + } + } catch(Exception e) { throw new PgpGeneralException(e); } + throw new PgpGeneralException("No encrypt key found"); } + @Override public boolean hasEncrypt() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -114,17 +140,28 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public long getSignId() throws PgpGeneralException { try { - Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, - ProviderHelper.FIELD_TYPE_INTEGER); - return (Long) data; - } catch(ProviderHelper.NotFoundException e) { + Cursor subkeys = getSubkeys(); + if (subkeys != null) { + try { + while (subkeys.moveToNext()) { + if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_SIGN)) != 0) { + return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); + } + } + } finally { + subkeys.close(); + } + } + } catch(Exception e) { throw new PgpGeneralException(e); } + throw new PgpGeneralException("No sign key found"); } + @Override public boolean hasSign() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -136,6 +173,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public int getVerified() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -156,6 +194,10 @@ public class CachedPublicKeyRing extends KeyRing { } catch(ProviderHelper.NotFoundException e) { throw new PgpGeneralException(e); } + } + private Cursor getSubkeys() throws PgpGeneralException { + Uri keysUri = KeychainContract.Keys.buildKeysUri(Long.toString(extractOrGetMasterKeyId())); + return mProviderHelper.getContentResolver().query(keysUri, null, null, null, null); } } 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 28495d51d..4bf3a38a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1034,4 +1034,8 @@ public class ProviderHelper { } } } + + public ContentResolver getContentResolver() { + return mContentResolver; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index c77fe9ab8..5542cccd1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -21,14 +21,21 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; +import android.view.Menu; +import android.view.MenuItem; +import android.view.ViewGroup; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.util.Log; +import java.util.ArrayList; + public class EncryptActivity extends DrawerActivity implements EncryptSymmetricFragment.OnSymmetricKeySelection, EncryptAsymmetricFragment.OnAsymmetricKeySelection, @@ -49,7 +56,7 @@ public class EncryptActivity extends DrawerActivity implements // view ViewPager mViewPagerMode; - PagerTabStrip mPagerTabStripMode; + //PagerTabStrip mPagerTabStripMode; PagerTabStripAdapter mTabsAdapterMode; ViewPager mViewPagerContent; PagerTabStrip mPagerTabStripContent; @@ -74,6 +81,9 @@ public class EncryptActivity extends DrawerActivity implements private long mSigningKeyId = Constants.key.none; private String mPassphrase; private String mPassphraseAgain; + private int mCurrentMode = PAGER_MODE_ASYMMETRIC; + private boolean mUseArmor; + private boolean mDeleteAfterEncrypt = false; @Override public void onSigningKeySelected(long signingKeyId) { @@ -102,7 +112,7 @@ public class EncryptActivity extends DrawerActivity implements @Override public boolean isModeSymmetric() { - return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); + return PAGER_MODE_SYMMETRIC == mCurrentMode; } @Override @@ -130,10 +140,19 @@ public class EncryptActivity extends DrawerActivity implements return mPassphraseAgain; } + @Override + public boolean isUseArmor() { + return mUseArmor; + } + + @Override + public boolean isDeleteAfterEncrypt() { + return mDeleteAfterEncrypt; + } private void initView() { mViewPagerMode = (ViewPager) findViewById(R.id.encrypt_pager_mode); - mPagerTabStripMode = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_mode); + //mPagerTabStripMode = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_mode); mViewPagerContent = (ViewPager) findViewById(R.id.encrypt_pager_content); mPagerTabStripContent = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_content); @@ -172,6 +191,37 @@ public class EncryptActivity extends DrawerActivity implements mTabsAdapterContent.addTab(EncryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file)); mViewPagerContent.setCurrentItem(mSwitchToContent); + + mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.encrypt_activity, menu); + menu.findItem(R.id.check_use_armor).setChecked(mUseArmor); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.isCheckable()) { + item.setChecked(!item.isChecked()); + } + switch (item.getItemId()) { + case R.id.check_use_symmetric: + mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; + mViewPagerMode.setCurrentItem(mSwitchToMode); + break; + case R.id.check_use_armor: + mUseArmor = item.isChecked(); + break; + case R.id.check_delete_after_encrypt: + mDeleteAfterEncrypt = item.isChecked(); + break; + default: + return super.onOptionsItemSelected(item); + } + return true; } /** @@ -183,12 +233,16 @@ public class EncryptActivity extends DrawerActivity implements String action = intent.getAction(); Bundle extras = intent.getExtras(); String type = intent.getType(); - Uri uri = intent.getData(); + ArrayList uris = new ArrayList(); if (extras == null) { extras = new Bundle(); } + if (intent.getData() != null) { + uris.add(intent.getData()); + } + /* * Android's Action */ @@ -206,14 +260,19 @@ public class EncryptActivity extends DrawerActivity implements } } else { // Files via content provider, override uri and action - uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); + uris.clear(); + uris.add(intent.getParcelableExtra(Intent.EXTRA_STREAM)); action = ACTION_ENCRYPT; } } + if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { + uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + action = ACTION_ENCRYPT; + } + if (extras.containsKey(EXTRA_ASCII_ARMOR)) { - boolean requestAsciiArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, true); - mFileFragmentBundle.putBoolean(EncryptFileFragment.ARG_ASCII_ARMOR, requestAsciiArmor); + mUseArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, true); } String textData = extras.getString(EXTRA_TEXT); @@ -235,9 +294,9 @@ public class EncryptActivity extends DrawerActivity implements // encrypt text based on given extra mMessageFragmentBundle.putString(EncryptMessageFragment.ARG_TEXT, textData); mSwitchToContent = PAGER_CONTENT_MESSAGE; - } else if (ACTION_ENCRYPT.equals(action) && uri != null) { + } else if (ACTION_ENCRYPT.equals(action) && uris != null && !uris.isEmpty()) { // encrypt file based on Uri - mFileFragmentBundle.putParcelable(EncryptFileFragment.ARG_URI, uri); + mFileFragmentBundle.putParcelableArrayList(EncryptFileFragment.ARG_URIS, uris); mSwitchToContent = PAGER_CONTENT_FILE; } else { Log.e(Constants.TAG, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index ca2ee3b55..6d649c32e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -28,4 +28,6 @@ public interface EncryptActivityInterface { public String getPassphrase(); public String getPassphraseAgain(); + boolean isUseArmor(); + boolean isDeleteAfterEncrypt(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index be845f05e..dc9cfe72e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -19,25 +19,30 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.content.Intent; +import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.TextView; -import android.widget.Button; +import android.widget.*; +import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; import org.sufficientlysecure.keychain.util.Log; -import java.util.Vector; +import java.util.*; public class EncryptAsymmetricFragment extends Fragment { public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; @@ -51,10 +56,8 @@ public class EncryptAsymmetricFragment extends Fragment { OnAsymmetricKeySelection mKeySelectionListener; // view - private Button mSelectKeysButton; private CheckBox mSign; - private TextView mMainUserId; - private TextView mMainUserIdRest; + private EncryptKeyCompletionView mEncryptKeyView; // model private long mSecretKeyId = Constants.key.none; @@ -108,15 +111,7 @@ public class EncryptAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSelectKeysButton = (Button) view.findViewById(R.id.btn_selectEncryptKeys); mSign = (CheckBox) view.findViewById(R.id.sign); - mMainUserId = (TextView) view.findViewById(R.id.mainUserId); - mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - mSelectKeysButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - selectPublicKeys(); - } - }); mSign.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { CheckBox checkBox = (CheckBox) v; @@ -127,6 +122,7 @@ public class EncryptAsymmetricFragment extends Fragment { } } }); + mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); return view; } @@ -140,6 +136,40 @@ public class EncryptAsymmetricFragment extends Fragment { mProviderHelper = new ProviderHelper(getActivity()); + getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(getActivity(), KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeyRings.HAS_ENCRYPT, KeyRings.KEY_ID, KeyRings.USER_ID, KeyRings.FINGERPRINT}, + null, null, null); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mEncryptKeyView.fromCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mEncryptKeyView.fromCursor(null); + } + }); + mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { + @Override + public void onTokenAdded(Object token) { + if (token instanceof EncryptKeyCompletionView.EncryptionKey) { + updateEncryptionKeys(); + } + } + + @Override + public void onTokenRemoved(Object token) { + if (token instanceof EncryptKeyCompletionView.EncryptionKey) { + updateEncryptionKeys(); + } + } + }); + // preselect keys given by arguments (given by Intent to EncryptActivity) preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); } @@ -168,44 +198,31 @@ public class EncryptAsymmetricFragment extends Fragment { } if (preselectedEncryptionKeyIds != null) { - Vector goodIds = new Vector(); - Vector goodUserIds = new Vector(); for (long preselectedId : preselectedEncryptionKeyIds) { try { CachedPublicKeyRing ring = providerHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(preselectedId)); - long id = ring.getMasterKeyId(); - ring.getSplitPrimaryUserId(); - goodUserIds.add(ring.getPrimaryUserId()); - goodIds.add(id); + mEncryptKeyView.addObject(mEncryptKeyView.new EncryptionKey(ring)); } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } - if (goodIds.size() > 0) { - long[] keyIds = new long[goodIds.size()]; - for (int i = 0; i < goodIds.size(); ++i) { - keyIds[i] = goodIds.get(i); - } - setEncryptionKeyIds(keyIds); - setEncryptionUserIds(goodUserIds.toArray(new String[goodUserIds.size()])); - } + updateEncryptionKeys(); } } private void updateView() { - if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { + /*if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { mSelectKeysButton.setText(getString(R.string.select_keys_button_default)); } else { mSelectKeysButton.setText(getResources().getQuantityString( R.plurals.select_keys_button, mEncryptionKeyIds.length, mEncryptionKeyIds.length)); - } + }*/ + /* if (mSecretKeyId == Constants.key.none) { mSign.setChecked(false); - mMainUserId.setText(""); - mMainUserIdRest.setText(""); } else { // See if we can get a user_id from a unified query String[] userId; @@ -216,7 +233,7 @@ public class EncryptAsymmetricFragment extends Fragment { userId = null; } if (userId != null && userId[0] != null) { - mMainUserId.setText(String.format("%#16x", Long.parseLong(userId[0]))); + mMainUserId.setText(userId[0]); } else { mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); } @@ -227,6 +244,26 @@ public class EncryptAsymmetricFragment extends Fragment { } mSign.setChecked(true); } + */ + } + + private void updateEncryptionKeys() { + List objects = mEncryptKeyView.getObjects(); + List keyIds = new ArrayList(); + List userIds = new ArrayList(); + for (Object object : objects) { + if (object instanceof EncryptKeyCompletionView.EncryptionKey) { + keyIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getKeyId()); + userIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getUserId()); + } + } + long[] keyIdsArr = new long[keyIds.size()]; + Iterator iterator = keyIds.iterator(); + for (int i = 0; i < keyIds.size(); i++) { + keyIdsArr[i] = iterator.next(); + } + setEncryptionKeyIds(keyIdsArr); + setEncryptionUserIds(userIds.toArray(new String[userIds.size()])); } private void selectPublicKeys() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 3111e5c3e..350bc03aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -20,6 +20,8 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Point; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -29,15 +31,13 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.Spinner; -import android.widget.TextView; +import android.widget.*; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -45,18 +45,18 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.io.File; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; public class EncryptFileFragment extends Fragment { - public static final String ARG_URI = "uri"; - public static final String ARG_ASCII_ARMOR = "ascii_armor"; + public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; @@ -64,16 +64,14 @@ public class EncryptFileFragment extends Fragment { private EncryptActivityInterface mEncryptInterface; // view - private CheckBox mAsciiArmor = null; private Spinner mFileCompression = null; - private TextView mFilename = null; - private CheckBox mDeleteAfter = null; private View mShareFile; private View mEncryptFile; + private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); // model - private Uri mInputUri = null; - private Uri mOutputUri = null; + private ArrayList mInputUri = new ArrayList(); + private ArrayList mOutputUri = new ArrayList(); @Override public void onAttach(Activity activity) { @@ -107,17 +105,33 @@ public class EncryptFileFragment extends Fragment { } }); - mFilename = (TextView) view.findViewById(R.id.filename); - view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { + //mFilename = (TextView) view.findViewById(R.id.filename); + //view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { + // public void onClick(View v) { + // if (Constants.KITKAT) { + // FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); + // } else { + // FileHelper.openFile(EncryptFileFragment.this, + // mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); + // } + // } + //}); + + View addFile = inflater.inflate(R.layout.file_list_entry_add, null); + addFile.setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { - FileHelper.openFile(EncryptFileFragment.this, mInputUri, "*/*", - REQUEST_CODE_INPUT); + FileHelper.openFile(EncryptFileFragment.this, + mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); } } }); + ListView listView = (ListView) view.findViewById(R.id.selected_files_list); + listView.addFooterView(addFile); + listView.setAdapter(mAdapter); mFileCompression = (Spinner) view.findViewById(R.id.fileCompression); Choice[] choices = new Choice[]{ @@ -143,11 +157,6 @@ public class EncryptFileFragment extends Fragment { } } - mDeleteAfter = (CheckBox) view.findViewById(R.id.deleteAfterEncryption); - - mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmor); - mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmor()); - return view; } @@ -155,43 +164,57 @@ public class EncryptFileFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - setInputUri(getArguments().getParcelable(ARG_URI)); - boolean asciiArmor = getArguments().getBoolean(ARG_ASCII_ARMOR); - if (asciiArmor) { - mAsciiArmor.setChecked(true); + addInputUris(getArguments().getParcelableArrayList(ARG_URIS)); + } + + private void addInputUris(List uris) { + if (uris != null) { + for (Uri uri : uris) { + addInputUri(uri); + } } } - private void setInputUri(Uri inputUri) { + private void addInputUri(Uri inputUri) { if (inputUri == null) { - mInputUri = null; - mFilename.setText(""); return; } - mInputUri = inputUri; - mFilename.setText(FileHelper.getFilename(getActivity(), mInputUri)); + mInputUri.add(inputUri); + mAdapter.notifyDataSetChanged(); + } + + private void delInputUri(int position) { + mInputUri.remove(position); + mAdapter.notifyDataSetChanged(); } private void showOutputFileDialog() { + if (mInputUri.size() > 1 || mInputUri.isEmpty()) { + throw new IllegalStateException(); + } + Uri inputUri = mInputUri.get(0); if (!Constants.KITKAT) { - File file = new File(mInputUri.getPath()); + File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; - String targetName = FileHelper.getFilename( - getActivity(), mInputUri) + (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); + String targetName = FileHelper.getFilename(getActivity(), inputUri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); File targetFile = new File(parentDir, targetName); FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file), getString(R.string.specify_file_to_encrypt_to), targetFile, REQUEST_CODE_OUTPUT); } else { - FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), mInputUri) + - (mAsciiArmor.isChecked() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT); + FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), inputUri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT); } } private void encryptClicked(boolean share) { - if (mInputUri == null) { + if (mInputUri.isEmpty()) { AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); return; + } else if (mInputUri.size() > 1 && !share) { + AppMsg.makeText(getActivity(), "TODO", AppMsg.STYLE_ALERT).show(); // TODO + return; } if (mEncryptInterface.isModeSymmetric()) { @@ -244,17 +267,20 @@ public class EncryptFileFragment extends Fragment { } if (share) { - String targetName = FileHelper.getFilename(getActivity(), mInputUri) + - (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); - mOutputUri = TemporaryStorageProvider.createFile(getActivity(), targetName); + mOutputUri.clear(); + for (Uri uri : mInputUri) { + String targetName = FileHelper.getFilename(getActivity(), uri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); + mOutputUri.add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + } encryptStart(true); - } else { + } else if (mInputUri.size() == 1) { showOutputFileDialog(); } } private void encryptStart(final boolean share) { - if (mInputUri == null || mOutputUri == null) { + if (mInputUri == null || mOutputUri == null || mInputUri.size() != mOutputUri.size()) { throw new IllegalStateException("Something went terribly wrong if this happens!"); } @@ -268,11 +294,11 @@ public class EncryptFileFragment extends Fragment { Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUri); - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUri); if (mEncryptInterface.isModeSymmetric()) { Log.d(Constants.TAG, "Symmetric encryption enabled!"); @@ -288,8 +314,7 @@ public class EncryptFileFragment extends Fragment { mEncryptInterface.getEncryptionKeys()); } - boolean useAsciiArmor = mAsciiArmor.isChecked(); - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, useAsciiArmor); + data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mEncryptInterface.isUseArmor()); int compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); @@ -307,18 +332,25 @@ public class EncryptFileFragment extends Fragment { AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful, AppMsg.STYLE_INFO).show(); - if (mDeleteAfter.isChecked()) { + if (mEncryptInterface.isDeleteAfterEncrypt()) { // Create and show dialog to delete original file - DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); + /*DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - setInputUri(null); + setInputUri(null);*/ } if (share) { // Share encrypted file - Intent sendFileIntent = new Intent(Intent.ACTION_SEND); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); + Intent sendFileIntent; + if (mOutputUri.size() == 1) { + sendFileIntent = new Intent(Intent.ACTION_SEND); + sendFileIntent.setType("*/*"); + sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri.get(0)); + } else { + sendFileIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); + sendFileIntent.setType("*/*"); + sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); + } if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { Set users = new HashSet(); for (String user : mEncryptInterface.getEncryptionUsers()) { @@ -352,14 +384,14 @@ public class EncryptFileFragment extends Fragment { switch (requestCode) { case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - setInputUri(data.getData()); + addInputUri(data.getData()); } return; } case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { - mOutputUri = data.getData(); + mOutputUri.add(data.getData()); encryptStart(false); } return; @@ -372,4 +404,52 @@ public class EncryptFileFragment extends Fragment { } } } + + private class SelectedFilesAdapter extends BaseAdapter { + @Override + public int getCount() { + return mInputUri.size(); + } + + @Override + public Object getItem(int position) { + return mInputUri.get(position); + } + + @Override + public long getItemId(int position) { + return getItem(position).hashCode(); + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + View view; + if (convertView == null) { + view = getActivity().getLayoutInflater().inflate(R.layout.file_list_entry, null); + } else { + view = convertView; + } + ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mInputUri.get(position))); + long size = FileHelper.getFileSize(getActivity(), mInputUri.get(position)); + if (size == -1) { + ((TextView) view.findViewById(R.id.filesize)).setText(""); + } else { + ((TextView) view.findViewById(R.id.filesize)).setText(FileHelper.readableFileSize(size)); + } + view.findViewById(R.id.action_remove_file_from_list).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + delInputUri(position); + } + }); + int px = OtherHelper.dpToPx(getActivity(), 48); + Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mInputUri.get(position), new Point(px, px)); + if (bitmap != null) { + ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap); + } else { + ((ImageView) view.findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_doc_generic_am); + } + return view; + } + } } 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 new file mode 100644 index 000000000..4566e37fd --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -0,0 +1,204 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.app.Activity; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import com.tokenautocomplete.FilteredArrayAdapter; +import com.tokenautocomplete.TokenCompleteTextView; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.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; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class EncryptKeyCompletionView extends TokenCompleteTextView { + public EncryptKeyCompletionView(Context context) { + super(context); + initView(); + } + + public EncryptKeyCompletionView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public EncryptKeyCompletionView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + fromCursor(null); + setPrefix(getContext().getString(R.string.label_to) + ": "); + allowDuplicates(false); + } + + private EncryptKeyAdapter mAdapter; + + @Override + protected View getViewForObject(Object object) { + if (object instanceof EncryptionKey) { + LayoutInflater l = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + View view = l.inflate(R.layout.recipient_box_entry, null); + ((TextView) view.findViewById(android.R.id.text1)).setText(((EncryptionKey) object).getPrimary()); + setImageByKey((ImageView) view.findViewById(android.R.id.icon), (EncryptionKey) object); + return view; + } + return null; + } + + private void setImageByKey(ImageView view, EncryptionKey key) { + Bitmap photo = ContactHelper.photoFromFingerprint(getContext().getContentResolver(), key.getFingerprint()); + + if (photo != null) { + view.setImageBitmap(photo); + } else { + view.setImageResource(R.drawable.ic_generic_man); + } + } + + @Override + protected Object defaultObject(String completionText) { + // TODO: We could try to automagically download the key if it's unknown but a key id + /*if (completionText.startsWith("0x")) { + + }*/ + return null; + } + + public void fromCursor(Cursor cursor) { + if (cursor == null) { + setAdapter(new EncryptKeyAdapter(Collections.emptyList())); + return; + } + ArrayList keys = new ArrayList(); + cursor.moveToFirst(); + while (cursor.moveToNext()) { + try { + if (cursor.getInt(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.HAS_ENCRYPT)) != 0) { + EncryptionKey key = new EncryptionKey(cursor); + keys.add(key); + } + } catch (Exception e) { + Log.w(Constants.TAG, e); + return; + } + } + setAdapter(new EncryptKeyAdapter(keys)); + } + + public class EncryptionKey { + private String mUserId; + private long mKeyId; + private String mFingerprint; + + public EncryptionKey(String userId, long keyId, String fingerprint) { + this.mUserId = userId; + this.mKeyId = keyId; + this.mFingerprint = fingerprint; + } + + public EncryptionKey(Cursor cursor) { + this(cursor.getString(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.USER_ID)), + cursor.getLong(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.KEY_ID)), + PgpKeyHelper.convertFingerprintToHex( + cursor.getBlob(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.FINGERPRINT)))); + + } + + public EncryptionKey(CachedPublicKeyRing ring) throws PgpGeneralException { + this(ring.getPrimaryUserId(), ring.extractOrGetMasterKeyId(), + PgpKeyHelper.convertFingerprintToHex(ring.getFingerprint())); + } + + public String getUserId() { + return mUserId; + } + + public String getFingerprint() { + return mFingerprint; + } + + public String getPrimary() { + String[] userId = KeyRing.splitUserId(mUserId); + if (userId[0] != null && userId[2] != null) { + return userId[0] + " (" + userId[2] + ")"; + } else if (userId[0] != null) { + return userId[0]; + } else { + return userId[1]; + } + } + + public String getSecondary() { + String[] userId = KeyRing.splitUserId(mUserId); + if (userId[0] != null) { + return userId[1] + " (" + getKeyIdHexShort() + ")"; + } else { + return getKeyIdHex(); + } + } + + public long getKeyId() { + return mKeyId; + } + + public String getKeyIdHex() { + return PgpKeyHelper.convertKeyIdToHex(mKeyId); + } + + public String getKeyIdHexShort() { + return PgpKeyHelper.convertKeyIdToHexShort(mKeyId); + } + + @Override + public String toString() { + return Long.toString(mKeyId); + } + } + + private class EncryptKeyAdapter extends FilteredArrayAdapter { + + public EncryptKeyAdapter(List objs) { + super(EncryptKeyCompletionView.this.getContext(), 0, 0, objs); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater l = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + View view; + if (convertView != null) { + view = convertView; + } else { + view = l.inflate(R.layout.recipient_selection_list_entry, null); + } + ((TextView) view.findViewById(android.R.id.title)).setText(getItem(position).getPrimary()); + ((TextView) view.findViewById(android.R.id.text1)).setText(getItem(position).getSecondary()); + setImageByKey((ImageView) view.findViewById(android.R.id.icon), getItem(position)); + return view; + } + + @Override + protected boolean keepObject(EncryptionKey obj, String mask) { + String m = mask.toLowerCase(); + return obj.getUserId().toLowerCase().contains(m) || + obj.getKeyIdHex().contains(m) || + obj.getKeyIdHexShort().startsWith(m); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java new file mode 100644 index 000000000..08f071fb2 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java @@ -0,0 +1,44 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +public class NoSwipeWrapContentViewPager extends android.support.v4.view.ViewPager { + public NoSwipeWrapContentViewPager(Context context) { + super(context); + } + + public NoSwipeWrapContentViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int height = 0; + for(int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int h = child.getMeasuredHeight(); + if(h > height) height = h; + } + + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent arg0) { + // Never allow swiping to switch between pages + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // Never allow swiping to switch between pages + return false; + } +} -- cgit v1.2.3 From 2913a78b188e81fe6bd91d26fb0ae083cf504bde Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 20 Jul 2014 17:09:34 +0200 Subject: Load of rework on EncryptActivity, still some TODOs --- .../keychain/helper/ContactHelper.java | 21 +- .../keychain/ui/EncryptActivity.java | 306 ++++++++++++++++++--- .../keychain/ui/EncryptActivityInterface.java | 34 ++- .../keychain/ui/EncryptAsymmetricFragment.java | 271 +++++++++--------- .../keychain/ui/EncryptFileFragment.java | 268 ++++-------------- .../keychain/ui/EncryptMessageFragment.java | 170 ++---------- .../keychain/ui/EncryptSymmetricFragment.java | 45 ++- .../ui/widget/EncryptKeyCompletionView.java | 4 +- 8 files changed, 554 insertions(+), 565 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 1b9ef57b3..5d1bd1bb5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -236,14 +236,19 @@ public class ContactHelper { } public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { - 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); + 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; + } } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index c98171230..ef999a449 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -18,28 +18,38 @@ package org.sufficientlysecure.keychain.ui; +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.v4.app.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; -import android.view.ViewGroup; +import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; -public class EncryptActivity extends DrawerActivity implements - EncryptSymmetricFragment.OnSymmetricKeySelection, - EncryptAsymmetricFragment.OnAsymmetricKeySelection, - EncryptActivityInterface { +public class EncryptActivity extends DrawerActivity implements EncryptActivityInterface { /* Intents */ public static final String ACTION_ENCRYPT = Constants.INTENT_PREFIX + "ENCRYPT"; @@ -79,75 +89,300 @@ public class EncryptActivity extends DrawerActivity implements private long mEncryptionKeyIds[] = null; private String mEncryptionUserIds[] = null; private long mSigningKeyId = Constants.key.none; - private String mPassphrase; - private String mPassphraseAgain; - private int mCurrentMode = PAGER_MODE_ASYMMETRIC; + private String mPassphrase = ""; private boolean mUseArmor; private boolean mDeleteAfterEncrypt = false; + private boolean mShareAfterEncrypt = false; + private ArrayList mInputUris; + private ArrayList mOutputUris; + private String mMessage; + + public boolean isModeSymmetric() { + return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); + } + + public boolean isContentMessage() { + return PAGER_CONTENT_MESSAGE == mViewPagerContent.getCurrentItem(); + } @Override - public void onSigningKeySelected(long signingKeyId) { - mSigningKeyId = signingKeyId; + public boolean isUseArmor() { + return mUseArmor; } @Override - public void onEncryptionKeysSelected(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; + public long getSignatureKey() { + return mSigningKeyId; } @Override - public void onEncryptionUserSelected(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; + public long[] getEncryptionKeys() { + return mEncryptionKeyIds; } @Override - public void onPassphraseUpdate(String passphrase) { - mPassphrase = passphrase; + public String[] getEncryptionUsers() { + return mEncryptionUserIds; } @Override - public void onPassphraseAgainUpdate(String passphrase) { - mPassphraseAgain = passphrase; + public void setSignatureKey(long signatureKey) { + mSigningKeyId = signatureKey; + notifyUpdate(); } @Override - public boolean isModeSymmetric() { - return PAGER_MODE_SYMMETRIC == mCurrentMode; + public void setEncryptionKeys(long[] encryptionKeys) { + mEncryptionKeyIds = encryptionKeys; + notifyUpdate(); } @Override - public long getSignatureKey() { - return mSigningKeyId; + public void setEncryptionUsers(String[] encryptionUsers) { + mEncryptionUserIds = encryptionUsers; + notifyUpdate(); } @Override - public long[] getEncryptionKeys() { - return mEncryptionKeyIds; + public void setPassphrase(String passphrase) { + mPassphrase = passphrase; } @Override - public String[] getEncryptionUsers() { - return mEncryptionUserIds; + public ArrayList getInputUris() { + if (mInputUris == null) mInputUris = new ArrayList(); + return mInputUris; } @Override - public String getPassphrase() { - return mPassphrase; + public ArrayList getOutputUris() { + if (mOutputUris == null) mOutputUris = new ArrayList(); + return mOutputUris; } @Override - public String getPassphraseAgain() { - return mPassphraseAgain; + public void setInputUris(ArrayList uris) { + mInputUris = uris; + notifyUpdate(); } @Override - public boolean isUseArmor() { - return mUseArmor; + public void setOutputUris(ArrayList uris) { + mOutputUris = uris; + notifyUpdate(); + } + + @Override + public String getMessage() { + return mMessage; + } + + @Override + public void setMessage(String message) { + mMessage = message; + } + + @Override + public void notifyUpdate() { + for (Fragment fragment : getSupportFragmentManager().getFragments()) { + if (fragment instanceof EncryptActivityInterface.UpdateListener) { + ((UpdateListener) fragment).onNotifyUpdate(); + } + } } @Override - public boolean isDeleteAfterEncrypt() { - return mDeleteAfterEncrypt; + public void startEncrypt(boolean share) { + mShareAfterEncrypt = share; + startEncrypt(); + } + + public void startEncrypt() { + if (!inputIsValid()) { + // AppMsg was created by inputIsValid. + return; + } + + // Send all information needed to service to edit key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); + intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle()); + + // Message is received after encrypting is done in KeychainIntentService + KeychainIntentServiceHandler serviceHandler = new KeychainIntentServiceHandler(this, + getString(R.string.progress_encrypting), ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + AppMsg.makeText(EncryptActivity.this, R.string.encrypt_sign_successful, AppMsg.STYLE_INFO).show(); + + if (!isContentMessage() && mDeleteAfterEncrypt) { + // TODO: Create and show dialog to delete original file + //DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); + //deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); + //setInputUri(null); + } + + if (mShareAfterEncrypt) { + // Share encrypted file + startActivity(Intent.createChooser(createSendIntent(message), getString(R.string.title_share_file))); + } else if (isContentMessage()) { + // Copy to clipboard + copyToClipboard(message); + AppMsg.makeText(EncryptActivity.this, + R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO).show(); + } + } + } + }; + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(serviceHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + serviceHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + + private Bundle createEncryptBundle() { + // fill values for this action + Bundle data = new Bundle(); + + if (isContentMessage()) { + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); + data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, mMessage.getBytes()); + } else { + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUris); + + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUris); + } + + // Always use armor for messages + data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mUseArmor || isContentMessage()); + + // TODO: Only default compression right now... + int compressionId = Preferences.getPreferences(this).getDefaultMessageCompression(); + data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); + + if (isModeSymmetric()) { + Log.d(Constants.TAG, "Symmetric encryption enabled!"); + String passphrase = mPassphrase; + if (passphrase.length() == 0) { + passphrase = null; + } + data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); + } else { + data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, mSigningKeyId); + data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds); + } + return data; + } + + private void copyToClipboard(Message message) { + ClipboardReflection.copyToClipboard(this, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); + } + + private Intent createSendIntent(Message message) { + Intent sendIntent; + if (isContentMessage()) { + sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.setType("text/plain"); + sendIntent.putExtra(Intent.EXTRA_TEXT, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); + } else { + // file + if (mOutputUris.size() == 1) { + sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.setType("*/*"); + sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris.get(0)); + } else { + sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); + sendIntent.setType("*/*"); + sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris); + } + } + if (!isModeSymmetric() && mEncryptionUserIds != null) { + Set users = new HashSet(); + for (String user : mEncryptionUserIds) { + String[] userId = KeyRing.splitUserId(user); + if (userId[1] != null) { + users.add(userId[1]); + } + } + sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + } + return sendIntent; + } + + private boolean inputIsValid() { + if (!isContentMessage()) { + // file checks + + if (mInputUris.isEmpty()) { + AppMsg.makeText(this, R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); + return false; + } else if (mInputUris.size() > 1 && !mShareAfterEncrypt) { + AppMsg.makeText(this, "TODO", AppMsg.STYLE_ALERT).show(); // TODO + return false; + } + + if (mInputUris.size() != mOutputUris.size()) { + throw new IllegalStateException("Something went terribly wrong if this happens!"); + } + } + + if (isModeSymmetric()) { + // symmetric encryption checks + + + if (mPassphrase == null) { + AppMsg.makeText(this, R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); + return false; + } + if (mPassphrase.isEmpty()) { + AppMsg.makeText(this, R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT).show(); + return false; + } + + } else { + // asymmetric encryption checks + + boolean gotEncryptionKeys = (mEncryptionKeyIds != null + && mEncryptionKeyIds.length > 0); + + // Files must be encrypted, only text can be signed-only right now + if (!gotEncryptionKeys && !isContentMessage()) { + AppMsg.makeText(this, R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); + return false; + } + + if (!gotEncryptionKeys && mSigningKeyId == 0) { + AppMsg.makeText(this, R.string.select_encryption_or_signature_key, + AppMsg.STYLE_ALERT).show(); + return false; + } + + if (mSigningKeyId != 0 && PassphraseCacheService.getCachedPassphrase(this, mSigningKeyId) == null) { + PassphraseDialogFragment.show(this, mSigningKeyId, + new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + // restart + startEncrypt(); + } + } + }); + + return false; + } + } + return true; } private void initView() { @@ -211,12 +446,15 @@ public class EncryptActivity extends DrawerActivity implements case R.id.check_use_symmetric: mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; mViewPagerMode.setCurrentItem(mSwitchToMode); + notifyUpdate(); break; case R.id.check_use_armor: mUseArmor = item.isChecked(); + notifyUpdate(); break; case R.id.check_delete_after_encrypt: mDeleteAfterEncrypt = item.isChecked(); + notifyUpdate(); break; default: return super.onOptionsItemSelected(item); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index 6d649c32e..54fe369a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -17,17 +17,41 @@ package org.sufficientlysecure.keychain.ui; +import android.net.Uri; + +import java.util.ArrayList; + public interface EncryptActivityInterface { - public boolean isModeSymmetric(); + public interface UpdateListener { + void onNotifyUpdate(); + } + + public boolean isUseArmor(); public long getSignatureKey(); public long[] getEncryptionKeys(); public String[] getEncryptionUsers(); + public void setSignatureKey(long signatureKey); + public void setEncryptionKeys(long[] encryptionKeys); + public void setEncryptionUsers(String[] encryptionUsers); + + public void setPassphrase(String passphrase); + + // ArrayList on purpose as only those are parcelable + public ArrayList getInputUris(); + public ArrayList getOutputUris(); + public void setInputUris(ArrayList uris); + public void setOutputUris(ArrayList uris); + + public String getMessage(); + public void setMessage(String message); - public String getPassphrase(); - public String getPassphraseAgain(); + /** + * Call this to notify the UI for changes done on the array lists or arrays, + * automatically called if setter is used + */ + public void notifyUpdate(); - boolean isUseArmor(); - boolean isDeleteAfterEncrypt(); + public void startEncrypt(boolean share); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index dc9cfe72e..9c7d7462f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -18,7 +18,7 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Intent; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -26,14 +26,15 @@ import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; - import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +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; @@ -42,9 +43,13 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; import org.sufficientlysecure.keychain.util.Log; -import java.util.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class EncryptAsymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { + private static final String SIGN_KEY_SELECTION = KeyRings.CAN_SIGN + " = 1 AND " + KeyRings.IS_REVOKED + " = 0"; -public class EncryptAsymmetricFragment extends Fragment { public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids"; @@ -53,55 +58,39 @@ public class EncryptAsymmetricFragment extends Fragment { ProviderHelper mProviderHelper; - OnAsymmetricKeySelection mKeySelectionListener; - // view - private CheckBox mSign; + private Spinner mSign; private EncryptKeyCompletionView mEncryptKeyView; + private SelectSignKeyCursorAdapter mSignAdapter = new SelectSignKeyCursorAdapter(); // model - private long mSecretKeyId = Constants.key.none; - private long mEncryptionKeyIds[] = null; - private String mEncryptionUserIds[] = null; - - // Container Activity must implement this interface - public interface OnAsymmetricKeySelection { - public void onSigningKeySelected(long signingKeyId); + private EncryptActivityInterface mEncryptInterface; - public void onEncryptionKeysSelected(long[] encryptionKeyIds); + @Override + public void onNotifyUpdate() { - public void onEncryptionUserSelected(String[] encryptionUserIds); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - mKeySelectionListener = (OnAsymmetricKeySelection) activity; + mEncryptInterface = (EncryptActivityInterface) activity; } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement OnAsymmetricKeySelection"); + throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface"); } } private void setSignatureKeyId(long signatureKeyId) { - mSecretKeyId = signatureKeyId; - // update key selection in EncryptActivity - mKeySelectionListener.onSigningKeySelected(signatureKeyId); - updateView(); + mEncryptInterface.setSignatureKey(signatureKeyId); } private void setEncryptionKeyIds(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; - // update key selection in EncryptActivity - mKeySelectionListener.onEncryptionKeysSelected(encryptionKeyIds); - updateView(); + mEncryptInterface.setEncryptionKeys(encryptionKeyIds); } private void setEncryptionUserIds(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; - // update key selection in EncryptActivity - mKeySelectionListener.onEncryptionUserSelected(encryptionUserIds); - updateView(); + mEncryptInterface.setEncryptionUsers(encryptionUserIds); } /** @@ -111,15 +100,17 @@ public class EncryptAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSign = (CheckBox) view.findViewById(R.id.sign); - mSign.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - CheckBox checkBox = (CheckBox) v; - if (checkBox.isChecked()) { - selectSecretKey(); - } else { - setSignatureKeyId(Constants.key.none); - } + mSign = (Spinner) view.findViewById(R.id.sign); + mSign.setAdapter(mSignAdapter); + mSign.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setSignatureKeyId(parent.getAdapter().getItemId(position)); + } + + @Override + public void onNothingSelected(AdapterView parent) { + setSignatureKeyId(Constants.key.none); } }); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); @@ -136,6 +127,11 @@ public class EncryptAsymmetricFragment extends Fragment { mProviderHelper = new ProviderHelper(getActivity()); + // preselect keys given by arguments (given by Intent to EncryptActivity) + preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); + + // TODO: Move this into widget! + getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { @@ -146,12 +142,55 @@ public class EncryptAsymmetricFragment extends Fragment { @Override public void onLoadFinished(Loader loader, Cursor data) { - mEncryptKeyView.fromCursor(data); + mEncryptKeyView.swapCursor(data); } @Override public void onLoaderReset(Loader loader) { - mEncryptKeyView.fromCursor(null); + mEncryptKeyView.swapCursor(null); + } + }); + getLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); + + // These are the rows that we will retrieve. + String[] projection = new String[]{ + KeyRings._ID, + KeyRings.MASTER_KEY_ID, + KeyRings.KEY_ID, + KeyRings.USER_ID, + KeyRings.EXPIRY, + KeyRings.IS_REVOKED, + // can certify info only related to master key + KeyRings.CAN_CERTIFY, + // has sign may be any subkey + KeyRings.HAS_SIGN, + KeyRings.HAS_ANY_SECRET, + KeyRings.HAS_SECRET + }; + + String where = KeyRings.HAS_ANY_SECRET + " = 1"; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, projection, where, null, null); + /*return new CursorLoader(getActivity(), KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeyRings.USER_ID, KeyRings.KEY_ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET}, SIGN_KEY_SELECTION, + null, null);*/ + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mSignAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mSignAdapter.swapCursor(null); } }); mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { @@ -169,9 +208,6 @@ public class EncryptAsymmetricFragment extends Fragment { } } }); - - // preselect keys given by arguments (given by Intent to EncryptActivity) - preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); } /** @@ -211,42 +247,6 @@ public class EncryptAsymmetricFragment extends Fragment { } } - private void updateView() { - /*if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { - mSelectKeysButton.setText(getString(R.string.select_keys_button_default)); - } else { - mSelectKeysButton.setText(getResources().getQuantityString( - R.plurals.select_keys_button, mEncryptionKeyIds.length, - mEncryptionKeyIds.length)); - }*/ - - /* - if (mSecretKeyId == Constants.key.none) { - mSign.setChecked(false); - } else { - // See if we can get a user_id from a unified query - String[] userId; - try { - userId = mProviderHelper.getCachedPublicKeyRing( - KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserId(); - } catch (PgpGeneralException e) { - userId = null; - } - if (userId != null && userId[0] != null) { - mMainUserId.setText(userId[0]); - } else { - mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); - } - if (userId != null && userId[1] != null) { - mMainUserIdRest.setText(userId[1]); - } else { - mMainUserIdRest.setText(""); - } - mSign.setChecked(true); - } - */ - } - private void updateEncryptionKeys() { List objects = mEncryptKeyView.getObjects(); List keyIds = new ArrayList(); @@ -266,58 +266,81 @@ public class EncryptAsymmetricFragment extends Fragment { setEncryptionUserIds(userIds.toArray(new String[userIds.size()])); } - private void selectPublicKeys() { - Intent intent = new Intent(getActivity(), SelectPublicKeyActivity.class); - Vector keyIds = new Vector(); - if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) { - for (int i = 0; i < mEncryptionKeyIds.length; ++i) { - keyIds.add(mEncryptionKeyIds[i]); - } + private class SelectSignKeyCursorAdapter extends BaseAdapter implements SpinnerAdapter { + private CursorAdapter inner; + private int mIndexUserId; + private int mIndexKeyId; + private int mIndexMasterKeyId; + + public SelectSignKeyCursorAdapter() { + inner = new CursorAdapter(null, null, 0) { + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return getActivity().getLayoutInflater().inflate(R.layout.encrypt_asymmetric_signkey, null); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ((TextView) view.findViewById(android.R.id.text1)).setText(cursor.getString(mIndexUserId)); + view.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); + ((TextView) view.findViewById(android.R.id.text2)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); + } + + @Override + public long getItemId(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(mIndexMasterKeyId); + } + }; } - long[] initialKeyIds = null; - if (keyIds.size() > 0) { - initialKeyIds = new long[keyIds.size()]; - for (int i = 0; i < keyIds.size(); ++i) { - initialKeyIds[i] = keyIds.get(i); + + public Cursor swapCursor(Cursor newCursor) { + if (newCursor == null) return inner.swapCursor(null); + + mIndexKeyId = newCursor.getColumnIndex(KeyRings.KEY_ID); + mIndexUserId = newCursor.getColumnIndex(KeyRings.USER_ID); + mIndexMasterKeyId = newCursor.getColumnIndex(KeyRings.MASTER_KEY_ID); + if (newCursor.moveToFirst()) { + do { + if (newCursor.getLong(mIndexMasterKeyId) == mEncryptInterface.getSignatureKey()) { + mSign.setSelection(newCursor.getPosition() + 1); + } + } while (newCursor.moveToNext()); } + return inner.swapCursor(newCursor); } - intent.putExtra(SelectPublicKeyActivity.EXTRA_SELECTED_MASTER_KEY_IDS, initialKeyIds); - startActivityForResult(intent, REQUEST_CODE_PUBLIC_KEYS); - } - private void selectSecretKey() { - Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class); - intent.putExtra(SelectSecretKeyActivity.EXTRA_FILTER_SIGN, true); - startActivityForResult(intent, REQUEST_CODE_SECRET_KEYS); - } + @Override + public int getCount() { + return inner.getCount() + 1; + } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_CODE_PUBLIC_KEYS: { - if (resultCode == Activity.RESULT_OK) { - Bundle bundle = data.getExtras(); - setEncryptionKeyIds(bundle - .getLongArray(SelectPublicKeyActivity.RESULT_EXTRA_MASTER_KEY_IDS)); - setEncryptionUserIds(bundle.getStringArray(SelectPublicKeyActivity.RESULT_EXTRA_USER_IDS)); - } - break; - } + @Override + public Object getItem(int position) { + if (position == 0) return null; + return inner.getItem(position - 1); + } + + @Override + public long getItemId(int position) { + if (position == 0) return Constants.key.none; + return inner.getItemId(position - 1); + } - case REQUEST_CODE_SECRET_KEYS: { - if (resultCode == Activity.RESULT_OK) { - Uri uriMasterKey = data.getData(); - setSignatureKeyId(Long.valueOf(uriMasterKey.getLastPathSegment())); + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (position == 0) { + View v; + if (convertView == null) { + v = inner.newView(null, null, parent); } else { - setSignatureKeyId(Constants.key.none); + v = convertView; } - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - - break; + ((TextView) v.findViewById(android.R.id.text1)).setText("None"); + v.findViewById(android.R.id.text2).setVisibility(View.GONE); + return v; + } else { + return inner.getView(position - 1, convertView, parent); } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 350bc03aa..f782b7594 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -18,44 +18,28 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Point; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; - -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.OtherHelper; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.helper.FileHelper; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.util.Choice; -import org.sufficientlysecure.keychain.util.Log; import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -public class EncryptFileFragment extends Fragment { +public class EncryptFileFragment extends Fragment implements EncryptActivityInterface.UpdateListener { public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; @@ -64,15 +48,11 @@ public class EncryptFileFragment extends Fragment { private EncryptActivityInterface mEncryptInterface; // view - private Spinner mFileCompression = null; + private View mAddView; private View mShareFile; private View mEncryptFile; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); - // model - private ArrayList mInputUri = new ArrayList(); - private ArrayList mOutputUri = new ArrayList(); - @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -105,34 +85,23 @@ public class EncryptFileFragment extends Fragment { } }); - //mFilename = (TextView) view.findViewById(R.id.filename); - //view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { - // public void onClick(View v) { - // if (Constants.KITKAT) { - // FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); - // } else { - // FileHelper.openFile(EncryptFileFragment.this, - // mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); - // } - // } - //}); - - View addFile = inflater.inflate(R.layout.file_list_entry_add, null); - addFile.setOnClickListener(new View.OnClickListener() { + mAddView = inflater.inflate(R.layout.file_list_entry_add, null); + mAddView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { FileHelper.openFile(EncryptFileFragment.this, - mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); + mEncryptInterface.getInputUris().isEmpty() ? null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1), "*/*", REQUEST_CODE_INPUT); } } }); ListView listView = (ListView) view.findViewById(R.id.selected_files_list); - listView.addFooterView(addFile); + listView.addFooterView(mAddView); listView.setAdapter(mAdapter); + /* mFileCompression = (Spinner) view.findViewById(R.id.fileCompression); Choice[] choices = new Choice[]{ new Choice(Constants.choice.compression.none, getString(R.string.choice_none) + " (" @@ -149,6 +118,7 @@ public class EncryptFileFragment extends Fragment { adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mFileCompression.setAdapter(adapter); + int defaultFileCompression = Preferences.getPreferences(getActivity()).getDefaultFileCompression(); for (int i = 0; i < choices.length; ++i) { if (choices[i].getId() == defaultFileCompression) { @@ -156,6 +126,7 @@ public class EncryptFileFragment extends Fragment { break; } } + */ return view; } @@ -180,20 +151,39 @@ public class EncryptFileFragment extends Fragment { return; } - mInputUri.add(inputUri); - mAdapter.notifyDataSetChanged(); + mEncryptInterface.getInputUris().add(inputUri); + mEncryptInterface.notifyUpdate(); + + /** + * We hide the encrypt to file button if multiple files are selected. + * + * With Android L it will be possible to select a target directory for multiple files, so we might want to + * change this later + */ + + if (mEncryptInterface.getInputUris().size() > 1) { + mEncryptFile.setVisibility(View.GONE); + } else { + mEncryptFile.setVisibility(View.VISIBLE); + } } private void delInputUri(int position) { - mInputUri.remove(position); - mAdapter.notifyDataSetChanged(); + mEncryptInterface.getInputUris().remove(position); + mEncryptInterface.notifyUpdate(); + + if (mEncryptInterface.getInputUris().size() > 1) { + mEncryptFile.setVisibility(View.GONE); + } else { + mEncryptFile.setVisibility(View.VISIBLE); + } } private void showOutputFileDialog() { - if (mInputUri.size() > 1 || mInputUri.isEmpty()) { + if (mEncryptInterface.getInputUris().size() > 1 || mEncryptInterface.getInputUris().isEmpty()) { throw new IllegalStateException(); } - Uri inputUri = mInputUri.get(0); + Uri inputUri = mEncryptInterface.getInputUris().get(0); if (!Constants.KITKAT) { File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; @@ -209,176 +199,19 @@ public class EncryptFileFragment extends Fragment { } private void encryptClicked(boolean share) { - if (mInputUri.isEmpty()) { - AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); - return; - } else if (mInputUri.size() > 1 && !share) { - AppMsg.makeText(getActivity(), "TODO", AppMsg.STYLE_ALERT).show(); // TODO - return; - } - - if (mEncryptInterface.isModeSymmetric()) { - // symmetric encryption - - boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null - && mEncryptInterface.getPassphrase().length() != 0); - if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); - return; - } - - if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); - return; - } - } else { - // asymmetric encryption - - boolean gotEncryptionKeys = (mEncryptInterface.getEncryptionKeys() != null - && mEncryptInterface.getEncryptionKeys().length > 0); - - if (!gotEncryptionKeys) { - AppMsg.makeText(getActivity(), R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); - return; - } - - if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); - return; - } - - if (mEncryptInterface.getSignatureKey() != 0 && - PassphraseCacheService.getCachedPassphrase(getActivity(), - mEncryptInterface.getSignatureKey()) == null) { - PassphraseDialogFragment.show(getActivity(), mEncryptInterface.getSignatureKey(), - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - showOutputFileDialog(); - } - } - }); - - return; - } - } - if (share) { - mOutputUri.clear(); - for (Uri uri : mInputUri) { + mEncryptInterface.getOutputUris().clear(); + for (Uri uri : mEncryptInterface.getInputUris()) { String targetName = FileHelper.getFilename(getActivity(), uri) + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); - mOutputUri.add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName)); } - encryptStart(true); - } else if (mInputUri.size() == 1) { + mEncryptInterface.startEncrypt(share); + } else if (mEncryptInterface.getInputUris().size() == 1) { showOutputFileDialog(); } } - private void encryptStart(final boolean share) { - if (mInputUri == null || mOutputUri == null || mInputUri.size() != mOutputUri.size()) { - throw new IllegalStateException("Something went terribly wrong if this happens!"); - } - - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(getActivity(), KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); - - // fill values for this action - Bundle data = new Bundle(); - - Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); - data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUri); - - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); - data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUri); - - if (mEncryptInterface.isModeSymmetric()) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - String passphrase = mEncryptInterface.getPassphrase(); - if (passphrase.length() == 0) { - passphrase = null; - } - data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); - } else { - data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, - mEncryptInterface.getSignatureKey()); - data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, - mEncryptInterface.getEncryptionKeys()); - } - - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mEncryptInterface.isUseArmor()); - - int compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); - data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after encrypting is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), - getString(R.string.progress_encrypting), ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful, - AppMsg.STYLE_INFO).show(); - - if (mEncryptInterface.isDeleteAfterEncrypt()) { - // Create and show dialog to delete original file - /*DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - setInputUri(null);*/ - } - - if (share) { - // Share encrypted file - Intent sendFileIntent; - if (mOutputUri.size() == 1) { - sendFileIntent = new Intent(Intent.ACTION_SEND); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri.get(0)); - } else { - sendFileIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); - } - if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { - Set users = new HashSet(); - for (String user : mEncryptInterface.getEncryptionUsers()) { - String[] userId = KeyRing.splitUserId(user); - if (userId[1] != null) { - users.add(userId[1]); - } - } - sendFileIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); - } - startActivity(Intent.createChooser(sendFileIntent, - getString(R.string.title_share_file))); - } - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(getActivity()); - - // start service with intent - getActivity().startService(intent); - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -391,8 +224,8 @@ public class EncryptFileFragment extends Fragment { case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { - mOutputUri.add(data.getData()); - encryptStart(false); + mEncryptInterface.getOutputUris().add(data.getData()); + mEncryptInterface.startEncrypt(false); } return; } @@ -405,15 +238,20 @@ public class EncryptFileFragment extends Fragment { } } + @Override + public void onNotifyUpdate() { + mAdapter.notifyDataSetChanged(); + } + private class SelectedFilesAdapter extends BaseAdapter { @Override public int getCount() { - return mInputUri.size(); + return mEncryptInterface.getInputUris().size(); } @Override public Object getItem(int position) { - return mInputUri.get(position); + return mEncryptInterface.getInputUris().get(position); } @Override @@ -429,8 +267,8 @@ public class EncryptFileFragment extends Fragment { } else { view = convertView; } - ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mInputUri.get(position))); - long size = FileHelper.getFileSize(getActivity(), mInputUri.get(position)); + ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mEncryptInterface.getInputUris().get(position))); + long size = FileHelper.getFileSize(getActivity(), mEncryptInterface.getInputUris().get(position)); if (size == -1) { ((TextView) view.findViewById(R.id.filesize)).setText(""); } else { @@ -443,7 +281,7 @@ public class EncryptFileFragment extends Fragment { } }); int px = OtherHelper.dpToPx(getActivity(), 48); - Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mInputUri.get(position), new Point(px, px)); + Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mEncryptInterface.getInputUris().get(position), new Point(px, px)); if (bitmap != null) { ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index e4f63089f..6aae649bd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -25,6 +25,8 @@ import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -75,18 +77,34 @@ public class EncryptMessageFragment extends Fragment { View view = inflater.inflate(R.layout.encrypt_message_fragment, container, false); mMessage = (TextView) view.findViewById(R.id.message); + mMessage.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + mEncryptInterface.setMessage(s.toString()); + } + }); mEncryptClipboard = view.findViewById(R.id.action_encrypt_clipboard); mEncryptShare = view.findViewById(R.id.action_encrypt_share); mEncryptClipboard.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - encryptClicked(true); + mEncryptInterface.startEncrypt(false); } }); mEncryptShare.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - encryptClicked(false); + mEncryptInterface.startEncrypt(true); } }); @@ -98,7 +116,7 @@ public class EncryptMessageFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - String text = getArguments().getString(ARG_TEXT); + String text = mEncryptInterface.getMessage(); if (text != null) { mMessage.setText(text); } @@ -123,150 +141,4 @@ public class EncryptMessageFragment extends Fragment { return message; } - - private void encryptClicked(final boolean toClipboard) { - if (mEncryptInterface.isModeSymmetric()) { - // symmetric encryption - - boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null - && mEncryptInterface.getPassphrase().length() != 0); - if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); - return; - } - - if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); - return; - } - - } else { - // asymmetric encryption - - boolean gotEncryptionKeys = (mEncryptInterface.getEncryptionKeys() != null - && mEncryptInterface.getEncryptionKeys().length > 0); - - if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); - return; - } - - if (mEncryptInterface.getSignatureKey() != 0 && - PassphraseCacheService.getCachedPassphrase(getActivity(), - mEncryptInterface.getSignatureKey()) == null) { - PassphraseDialogFragment.show(getActivity(), mEncryptInterface.getSignatureKey(), - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - encryptStart(toClipboard); - } - } - }); - - return; - } - } - - encryptStart(toClipboard); - } - - private void encryptStart(final boolean toClipboard) { - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(getActivity(), KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); - - // fill values for this action - Bundle data = new Bundle(); - - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); - - String message = mMessage.getText().toString(); - - if (mEncryptInterface.isModeSymmetric()) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - String passphrase = mEncryptInterface.getPassphrase(); - if (passphrase.length() == 0) { - passphrase = null; - } - data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); - } else { - data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, - mEncryptInterface.getSignatureKey()); - data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, - mEncryptInterface.getEncryptionKeys()); - - boolean signOnly = (mEncryptInterface.getEncryptionKeys() == null - || mEncryptInterface.getEncryptionKeys().length == 0); - if (signOnly) { - message = fixBadCharactersForGmail(message); - } - } - - data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, message.getBytes()); - - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, true); - - int compressionId = Preferences.getPreferences(getActivity()).getDefaultMessageCompression(); - data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after encrypting is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), - getString(R.string.progress_encrypting), 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 data = message.getData(); - - String output = new String(data.getByteArray(KeychainIntentService.RESULT_BYTES)); - Log.d(Constants.TAG, "output: " + output); - - if (toClipboard) { - ClipboardReflection.copyToClipboard(getActivity(), output); - AppMsg.makeText(getActivity(), - R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO) - .show(); - } else { - Intent sendIntent = new Intent(Intent.ACTION_SEND); - - // Type is set to text/plain so that encrypted messages can - // be sent with Whatsapp, Hangouts, SMS etc... - sendIntent.setType("text/plain"); - Log.d(Constants.TAG, "encrypt to:" + Arrays.toString(mEncryptInterface.getEncryptionUsers())); - if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { - Set users = new HashSet(); - for (String user : mEncryptInterface.getEncryptionUsers()) { - String[] userId = KeyRing.splitUserId(user); - if (userId[1] != null) { - users.add(userId[1]); - } - } - sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); - } - sendIntent.putExtra(Intent.EXTRA_TEXT, output); - startActivity(Intent.createChooser(sendIntent, - getString(R.string.title_share_with))); - } - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(getActivity()); - - // start service with intent - getActivity().startService(intent); - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java index 8efa07953..86731b162 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java @@ -29,27 +29,20 @@ import android.widget.EditText; import org.sufficientlysecure.keychain.R; -public class EncryptSymmetricFragment extends Fragment { +public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { - OnSymmetricKeySelection mPassphraseUpdateListener; + EncryptActivityInterface mEncryptInterface; private EditText mPassphrase; private EditText mPassphraseAgain; - // Container Activity must implement this interface - public interface OnSymmetricKeySelection { - public void onPassphraseUpdate(String passphrase); - - public void onPassphraseAgainUpdate(String passphrase); - } - @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - mPassphraseUpdateListener = (OnSymmetricKeySelection) activity; + mEncryptInterface = (EncryptActivityInterface) activity; } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement OnSymmetricKeySelection"); + throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface"); } } @@ -62,7 +55,7 @@ public class EncryptSymmetricFragment extends Fragment { mPassphrase = (EditText) view.findViewById(R.id.passphrase); mPassphraseAgain = (EditText) view.findViewById(R.id.passphraseAgain); - mPassphrase.addTextChangedListener(new TextWatcher() { + TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @@ -74,25 +67,21 @@ public class EncryptSymmetricFragment extends Fragment { @Override public void afterTextChanged(Editable s) { // update passphrase in EncryptActivity - mPassphraseUpdateListener.onPassphraseUpdate(s.toString()); - } - }); - mPassphraseAgain.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) { + mEncryptInterface.setPassphrase(s.toString()); + } else { + mEncryptInterface.setPassphrase(null); + } } + }; + mPassphrase.addTextChangedListener(textWatcher); + mPassphraseAgain.addTextChangedListener(textWatcher); - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } + return view; + } - @Override - public void afterTextChanged(Editable s) { - // update passphrase in EncryptActivity - mPassphraseUpdateListener.onPassphraseAgainUpdate(s.toString()); - } - }); + @Override + public void onNotifyUpdate() { - return view; } } 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 4566e37fd..2ba2e6497 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 @@ -43,7 +43,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } private void initView() { - fromCursor(null); + swapCursor(null); setPrefix(getContext().getString(R.string.label_to) + ": "); allowDuplicates(false); } @@ -81,7 +81,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { return null; } - public void fromCursor(Cursor cursor) { + public void swapCursor(Cursor cursor) { if (cursor == null) { setAdapter(new EncryptKeyAdapter(Collections.emptyList())); return; -- cgit v1.2.3 From 1e4f0c6b000167ff5a596ed0b0763141f2a2527f Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 25 Jul 2014 13:39:54 +0200 Subject: Make DecryptFragment abstract, as it should be --- .../java/org/sufficientlysecure/keychain/ui/DecryptFragment.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 6b8358538..d450bdcca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -38,7 +38,7 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -public class DecryptFragment extends Fragment { +public abstract class DecryptFragment extends Fragment { private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006; protected long mSignatureKeyId = 0; @@ -217,8 +217,6 @@ public class DecryptFragment extends Fragment { * * @param passphrase */ - protected void decryptStart(String passphrase) { - - } + protected abstract void decryptStart(String passphrase); } -- cgit v1.2.3 From 0c7eea225b7c04549e92c8c7729bf0e7a04aa5c7 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 31 Jul 2014 22:21:46 +0200 Subject: - add multi select for storage api (kitkat) - UI fixes - refactoring --- .../keychain/helper/FileHelper.java | 17 ++--- .../provider/TemporaryStorageProvider.java | 2 + .../keychain/ui/DecryptActivity.java | 2 +- .../keychain/ui/DecryptFileFragment.java | 13 +++- .../keychain/ui/DecryptMessageFragment.java | 2 - .../keychain/ui/EncryptActivity.java | 22 ++++--- .../keychain/ui/EncryptAsymmetricFragment.java | 26 -------- .../keychain/ui/EncryptFileFragment.java | 73 +++++++++++----------- .../ui/widget/EncryptKeyCompletionView.java | 32 +++++++++- .../ui/widget/NoSwipeWrapContentViewPager.java | 11 ++-- 10 files changed, 106 insertions(+), 94 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index e42c7987b..615d89e0c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -26,18 +26,12 @@ 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.os.*; import android.provider.DocumentsContract; import android.provider.OpenableColumns; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.widget.Toast; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; @@ -135,18 +129,25 @@ public class FileHelper { }, 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, int requestCode) { + 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); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java index 9e745215d..d1864f873 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -104,6 +104,8 @@ public class TemporaryStorageProvider extends ContentProvider { @Override public String getType(Uri uri) { + // Note: If we can find a files mime type, we can decrypt it to temp storage and open it after + // encryption. The mime type is needed, else UI really sucks and some apps break. return "*/*"; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 5d82fca6a..e62591b1a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.os.Bundle; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpHelper; @@ -120,6 +119,7 @@ public class DecryptActivity extends DrawerActivity { // override action action = ACTION_DECRYPT; + mFileFragmentBundle.putBoolean(DecryptFileFragment.ARG_FROM_VIEW_INTENT, true); } String textData = extras.getString(EXTRA_TEXT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 520ef7567..dd05537ef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -29,21 +29,21 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.util.Notify; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.io.File; public class DecryptFileFragment extends DecryptFragment { public static final String ARG_URI = "uri"; + public static final String ARG_FROM_VIEW_INTENT = "view_intent"; private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; @@ -189,6 +189,15 @@ public class DecryptFileFragment extends DecryptFragment { deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); setInputUri(null); } + + /* + // A future open after decryption feature + if () { + Intent viewFile = new Intent(Intent.ACTION_VIEW); + viewFile.setData(mOutputUri); + startActivity(viewFile); + } + */ } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 46462f924..2db6c232c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -27,9 +27,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.EditText; - import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index ef999a449..3dea8f227 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -28,7 +28,6 @@ import android.os.Messenger; import android.support.v4.app.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; - import android.view.Menu; import android.view.MenuItem; import com.devspark.appmsg.AppMsg; @@ -41,8 +40,8 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; +import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; @@ -220,9 +219,12 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn if (!isContentMessage() && mDeleteAfterEncrypt) { // TODO: Create and show dialog to delete original file - //DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - //deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - //setInputUri(null); + for (Uri inputUri : mInputUris) { + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUri); + deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); + } + mInputUris.clear(); + notifyUpdate(); } if (mShareAfterEncrypt) { @@ -327,12 +329,11 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn AppMsg.makeText(this, R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); return false; } else if (mInputUris.size() > 1 && !mShareAfterEncrypt) { - AppMsg.makeText(this, "TODO", AppMsg.STYLE_ALERT).show(); // TODO + // This should be impossible... + return false; + } else if (mInputUris.size() != mOutputUris.size()) { + // This as well return false; - } - - if (mInputUris.size() != mOutputUris.size()) { - throw new IllegalStateException("Something went terribly wrong if this happens!"); } } @@ -445,6 +446,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn switch (item.getItemId()) { case R.id.check_use_symmetric: mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; + mViewPagerMode.setCurrentItem(mSwitchToMode); notifyUpdate(); break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 9c7d7462f..47f4bdf59 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -37,7 +37,6 @@ import org.sufficientlysecure.keychain.R; 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; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; @@ -48,14 +47,9 @@ import java.util.Iterator; import java.util.List; public class EncryptAsymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { - private static final String SIGN_KEY_SELECTION = KeyRings.CAN_SIGN + " = 1 AND " + KeyRings.IS_REVOKED + " = 0"; - public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids"; - public static final int REQUEST_CODE_PUBLIC_KEYS = 0x00007001; - public static final int REQUEST_CODE_SECRET_KEYS = 0x00007002; - ProviderHelper mProviderHelper; // view @@ -130,26 +124,6 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi // preselect keys given by arguments (given by Intent to EncryptActivity) preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); - // TODO: Move this into widget! - - getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { - @Override - public Loader onCreateLoader(int id, Bundle args) { - return new CursorLoader(getActivity(), KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), - new String[]{KeyRings.HAS_ENCRYPT, KeyRings.KEY_ID, KeyRings.USER_ID, KeyRings.FINGERPRINT}, - null, null, null); - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - mEncryptKeyView.swapCursor(data); - } - - @Override - public void onLoaderReset(Loader loader) { - mEncryptKeyView.swapCursor(null); - } - }); getLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index f782b7594..1125dce77 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -17,24 +17,27 @@ package org.sufficientlysecure.keychain.ui; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Point; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.*; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +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.helper.Preferences; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; -import org.sufficientlysecure.keychain.util.Choice; import java.io.File; import java.util.List; @@ -89,45 +92,13 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte mAddView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (Constants.KITKAT) { - FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); - } else { - FileHelper.openFile(EncryptFileFragment.this, - mEncryptInterface.getInputUris().isEmpty() ? null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1), "*/*", REQUEST_CODE_INPUT); - } + addInputUri(); } }); ListView listView = (ListView) view.findViewById(R.id.selected_files_list); listView.addFooterView(mAddView); listView.setAdapter(mAdapter); - /* - mFileCompression = (Spinner) view.findViewById(R.id.fileCompression); - Choice[] choices = new Choice[]{ - new Choice(Constants.choice.compression.none, getString(R.string.choice_none) + " (" - + getString(R.string.compression_fast) + ")"), - new Choice(Constants.choice.compression.zip, "ZIP (" - + getString(R.string.compression_fast) + ")"), - new Choice(Constants.choice.compression.zlib, "ZLIB (" - + getString(R.string.compression_fast) + ")"), - new Choice(Constants.choice.compression.bzip2, "BZIP2 (" - + getString(R.string.compression_very_slow) + ")"), - }; - ArrayAdapter adapter = new ArrayAdapter(getActivity(), - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mFileCompression.setAdapter(adapter); - - - int defaultFileCompression = Preferences.getPreferences(getActivity()).getDefaultFileCompression(); - for (int i = 0; i < choices.length; ++i) { - if (choices[i].getId() == defaultFileCompression) { - mFileCompression.setSelection(i); - break; - } - } - */ - return view; } @@ -138,6 +109,16 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte addInputUris(getArguments().getParcelableArrayList(ARG_URIS)); } + private void addInputUri() { + if (Constants.KITKAT) { + FileHelper.openDocument(EncryptFileFragment.this, "*/*", true, REQUEST_CODE_INPUT); + } else { + FileHelper.openFile(EncryptFileFragment.this, mEncryptInterface.getInputUris().isEmpty() ? + null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1), + "*/*", REQUEST_CODE_INPUT); + } + } + private void addInputUris(List uris) { if (uris != null) { for (Uri uri : uris) { @@ -206,25 +187,41 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName)); } - mEncryptInterface.startEncrypt(share); + mEncryptInterface.startEncrypt(true); } else if (mEncryptInterface.getInputUris().size() == 1) { showOutputFileDialog(); } } + @TargetApi(Build.VERSION_CODES.KITKAT) + public boolean handleClipData(Intent data) { + if (data.getClipData() != null && data.getClipData().getItemCount() > 0) { + for (int i = 0; i < data.getClipData().getItemCount(); i++) { + Uri uri = data.getClipData().getItemAt(i).getUri(); + if (uri != null) addInputUri(uri); + } + return true; + } + return false; + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - addInputUri(data.getData()); + if (!Constants.KITKAT || !handleClipData(data)) { + addInputUri(data.getData()); + } } return; } case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { + mEncryptInterface.getOutputUris().clear(); mEncryptInterface.getOutputUris().add(data.getData()); + mEncryptInterface.notifyUpdate(); mEncryptInterface.startEncrypt(false); } return; 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 2ba2e6497..7bdaf27c7 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 @@ -4,6 +4,11 @@ import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -48,8 +53,6 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { allowDuplicates(false); } - private EncryptKeyAdapter mAdapter; - @Override protected View getViewForObject(Object object) { if (object instanceof EncryptionKey) { @@ -81,6 +84,31 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { return null; } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (getContext() instanceof FragmentActivity) { + ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(getContext(), KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeychainContract.KeyRings.HAS_ENCRYPT, KeychainContract.KeyRings.KEY_ID, KeychainContract.KeyRings.USER_ID, KeychainContract.KeyRings.FINGERPRINT}, + null, null, null); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + swapCursor(null); + } + }); + } + } + public void swapCursor(Cursor cursor) { if (cursor == null) { setAdapter(new EncryptKeyAdapter(Collections.emptyList())); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java index 08f071fb2..516e5ec39 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java @@ -17,12 +17,13 @@ public class NoSwipeWrapContentViewPager extends android.support.v4.view.ViewPag @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int height = 0; - for(int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); + int height; + View child = getChildAt(getCurrentItem()); + if (child != null) { child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - int h = child.getMeasuredHeight(); - if(h > height) height = h; + height = child.getMeasuredHeight(); + } else { + height = 0; } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); -- cgit v1.2.3 From 36d8c9f608cca5ba2f8df11008415c230825174b Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 31 Jul 2014 23:20:43 +0200 Subject: Fix merge --- .../keychain/ui/EncryptActivity.java | 30 ++++++++++++---------- .../keychain/ui/EncryptMessageFragment.java | 21 --------------- .../keychain/ui/dialog/FileDialogFragment.java | 5 ++-- 3 files changed, 19 insertions(+), 37 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 3dea8f227..e804d76a6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -30,7 +30,6 @@ import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; -import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -43,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; 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 java.util.ArrayList; import java.util.HashSet; @@ -94,7 +94,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn private boolean mShareAfterEncrypt = false; private ArrayList mInputUris; private ArrayList mOutputUris; - private String mMessage; + private String mMessage = ""; public boolean isModeSymmetric() { return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); @@ -198,7 +198,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn public void startEncrypt() { if (!inputIsValid()) { - // AppMsg was created by inputIsValid. + // Notify was created by inputIsValid. return; } @@ -215,7 +215,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(EncryptActivity.this, R.string.encrypt_sign_successful, AppMsg.STYLE_INFO).show(); + Notify.showNotify(EncryptActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO); if (!isContentMessage() && mDeleteAfterEncrypt) { // TODO: Create and show dialog to delete original file @@ -233,8 +233,8 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } else if (isContentMessage()) { // Copy to clipboard copyToClipboard(message); - AppMsg.makeText(EncryptActivity.this, - R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO).show(); + Notify.showNotify(EncryptActivity.this, + R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); } } } @@ -322,11 +322,16 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } private boolean inputIsValid() { - if (!isContentMessage()) { + if (isContentMessage()) { + if (mMessage == null) { + Notify.showNotify(this, R.string.error_message, Notify.Style.ERROR); + return false; + } + } else { // file checks if (mInputUris.isEmpty()) { - AppMsg.makeText(this, R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.no_file_selected, Notify.Style.ERROR); return false; } else if (mInputUris.size() > 1 && !mShareAfterEncrypt) { // This should be impossible... @@ -342,11 +347,11 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn if (mPassphrase == null) { - AppMsg.makeText(this, R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.passphrases_do_not_match, Notify.Style.ERROR); return false; } if (mPassphrase.isEmpty()) { - AppMsg.makeText(this, R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR); return false; } @@ -358,13 +363,12 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn // Files must be encrypted, only text can be signed-only right now if (!gotEncryptionKeys && !isContentMessage()) { - AppMsg.makeText(this, R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.select_encryption_key, Notify.Style.ERROR); return false; } if (!gotEncryptionKeys && mSigningKeyId == 0) { - AppMsg.makeText(this, R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.select_encryption_or_signature_key, Notify.Style.ERROR); return false; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index 6aae649bd..e493ad066 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -18,12 +18,7 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; @@ -31,23 +26,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; - -import com.devspark.appmsg.AppMsg; - -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; public class EncryptMessageFragment extends Fragment { public static final String ARG_TEXT = "text"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java index 80341aeaa..50f5ef7c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java @@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Activity; -import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; @@ -35,11 +34,11 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; -import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.io.File; @@ -190,7 +189,7 @@ public class FileDialogFragment extends DialogFragment { mFile = file; mFilename.setText(mFile.getName()); } else { - AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR); } } -- cgit v1.2.3 From c71cdc143238e46a10cbf6a2619801e1b4af6d29 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 31 Jul 2014 23:36:37 +0200 Subject: Fix string resources --- .../main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index e804d76a6..609ac8ab7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -429,7 +429,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn mTabsAdapterContent.addTab(EncryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message)); mTabsAdapterContent.addTab(EncryptFileFragment.class, - mFileFragmentBundle, getString(R.string.label_file)); + mFileFragmentBundle, getString(R.string.label_files)); mViewPagerContent.setCurrentItem(mSwitchToContent); mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor(); -- cgit v1.2.3 From 00f5352ddc90ab05f3d1a44534e44b015e071e18 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 1 Aug 2014 05:31:04 +0200 Subject: Fixes after merge --- .../sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index f05fec782..2295183a9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -30,9 +30,12 @@ import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; import android.widget.TextView; -import android.widget.Button; + import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; -- cgit v1.2.3 From 3a13cd5e4deebe283f8bfbc5122951e0a77b339d Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 1 Aug 2014 12:23:31 +0200 Subject: Fix first key is not used erroneously --- .../sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenKeychain/src/main/java') 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 7bdaf27c7..53731b278 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 @@ -115,7 +115,6 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { return; } ArrayList keys = new ArrayList(); - cursor.moveToFirst(); while (cursor.moveToNext()) { try { if (cursor.getInt(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.HAS_ENCRYPT)) != 0) { -- cgit v1.2.3 From 1ebb92b33638e427befa37fd2b6eef67ed3e4b88 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 1 Aug 2014 12:24:26 +0200 Subject: Cache contact photos to make UI more fluid --- .../org/sufficientlysecure/keychain/helper/ContactHelper.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 5d1bd1bb5..8fed40a86 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -63,6 +63,8 @@ public class ContactHelper { 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)); @@ -236,6 +238,14 @@ public class ContactHelper { } 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); -- cgit v1.2.3 From b206b6d351e38c96eb44d801a45c872844c1a0fd Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 1 Aug 2014 12:41:30 +0200 Subject: Cache input file thumbnail. --- .../keychain/ui/EncryptFileFragment.java | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 1125dce77..7538d2a56 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -38,9 +38,13 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; +import org.sufficientlysecure.keychain.util.Log; import java.io.File; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; public class EncryptFileFragment extends Fragment implements EncryptActivityInterface.UpdateListener { public static final String ARG_URIS = "uris"; @@ -55,6 +59,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte private View mShareFile; private View mEncryptFile; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); + private final Map thumbnailCache = new HashMap(); @Override public void onAttach(Activity activity) { @@ -237,6 +242,14 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte @Override public void onNotifyUpdate() { + // Clear cache if needed + for (Uri uri : new HashSet(thumbnailCache.keySet())) { + if (!mEncryptInterface.getInputUris().contains(uri)) { + Log.d(Constants.TAG, "Removed thumbnail for uri: "+uri); + thumbnailCache.remove(uri); + } + } + mAdapter.notifyDataSetChanged(); } @@ -258,14 +271,15 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte @Override public View getView(final int position, View convertView, ViewGroup parent) { + Uri inputUri = mEncryptInterface.getInputUris().get(position); View view; if (convertView == null) { view = getActivity().getLayoutInflater().inflate(R.layout.file_list_entry, null); } else { view = convertView; } - ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mEncryptInterface.getInputUris().get(position))); - long size = FileHelper.getFileSize(getActivity(), mEncryptInterface.getInputUris().get(position)); + ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), inputUri)); + long size = FileHelper.getFileSize(getActivity(), inputUri); if (size == -1) { ((TextView) view.findViewById(R.id.filesize)).setText(""); } else { @@ -278,7 +292,10 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte } }); int px = OtherHelper.dpToPx(getActivity(), 48); - Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mEncryptInterface.getInputUris().get(position), new Point(px, px)); + if (!thumbnailCache.containsKey(inputUri)) { + thumbnailCache.put(inputUri, FileHelper.getThumbnail(getActivity(), inputUri, new Point(px, px))); + } + Bitmap bitmap = thumbnailCache.get(inputUri); if (bitmap != null) { ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap); } else { -- cgit v1.2.3 From 80ed3464f4b3291e4c3402b2db8e78c16535274c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 1 Aug 2014 17:49:59 +0200 Subject: small fix for MSG_MF_UID_ADD log entry --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') 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 19b0d81b7..3f058d888 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -356,7 +356,7 @@ public class PgpKeyOperation { progress(R.string.progress_modify_adduid, (i-1) * (100 / saveParcel.mAddUserIds.size())); String userId = saveParcel.mAddUserIds.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent); + log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent, userId); if (userId.equals("")) { log.add(LogLevel.ERROR, LogType.MSG_MF_UID_ERROR_EMPTY, indent+1); -- cgit v1.2.3 From 9d101b4fe5ea3aa4c67264131eaaf055c0c35641 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 1 Aug 2014 23:30:31 +0200 Subject: Encrypt UI (drop downs) --- .../keychain/ui/EncryptActivity.java | 3 +- .../keychain/ui/EncryptAsymmetricFragment.java | 24 ++++++++++++---- .../keychain/ui/EncryptFileFragment.java | 1 - .../ui/widget/EncryptKeyCompletionView.java | 33 ++++++++++++++-------- 4 files changed, 40 insertions(+), 21 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 609ac8ab7..8a516e6af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -300,13 +300,12 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn // file if (mOutputUris.size() == 1) { sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.setType("*/*"); sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris.get(0)); } else { sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); - sendIntent.setType("*/*"); sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris); } + sendIntent.setType("application/pgp-encrypted"); } if (!isModeSymmetric() && mEncryptionUserIds != null) { Set users = new HashSet(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 2295183a9..ed3be0e7f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -40,6 +40,7 @@ import com.tokenautocomplete.TokenCompleteTextView; 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.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -261,8 +262,9 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi @Override public void bindView(View view, Context context, Cursor cursor) { - ((TextView) view.findViewById(android.R.id.text1)).setText(cursor.getString(mIndexUserId)); - view.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); + String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); + ((TextView) view.findViewById(android.R.id.title)).setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")")); + ((TextView) view.findViewById(android.R.id.text1)).setText(userId[1]); ((TextView) view.findViewById(android.R.id.text2)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); } @@ -309,19 +311,29 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi @Override public View getView(int position, View convertView, ViewGroup parent) { + View v = getDropDownView(position, convertView, parent); + v.findViewById(android.R.id.text1).setVisibility(View.GONE); + return v; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + View v; if (position == 0) { - View v; if (convertView == null) { v = inner.newView(null, null, parent); } else { v = convertView; } - ((TextView) v.findViewById(android.R.id.text1)).setText("None"); + ((TextView) v.findViewById(android.R.id.title)).setText("None"); + v.findViewById(android.R.id.text1).setVisibility(View.GONE); v.findViewById(android.R.id.text2).setVisibility(View.GONE); - return v; } else { - return inner.getView(position - 1, convertView, parent); + v = inner.getView(position - 1, convertView, parent); + v.findViewById(android.R.id.text1).setVisibility(View.VISIBLE); + v.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); } + return v; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 7538d2a56..7650c3954 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -245,7 +245,6 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte // Clear cache if needed for (Uri uri : new HashSet(thumbnailCache.keySet())) { if (!mEncryptInterface.getInputUris().contains(uri)) { - Log.d(Constants.TAG, "Removed thumbnail for uri: "+uri); thumbnailCache.remove(uri); } } 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 53731b278..329ef2c9b 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 @@ -130,12 +130,14 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } public class EncryptionKey { - private String mUserId; + private String mUserIdFull; + private String[] mUserId; private long mKeyId; private String mFingerprint; public EncryptionKey(String userId, long keyId, String fingerprint) { - this.mUserId = userId; + this.mUserId = KeyRing.splitUserId(userId); + this.mUserIdFull = userId; this.mKeyId = keyId; this.mFingerprint = fingerprint; } @@ -154,7 +156,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } public String getUserId() { - return mUserId; + return mUserIdFull; } public String getFingerprint() { @@ -162,25 +164,31 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } public String getPrimary() { - String[] userId = KeyRing.splitUserId(mUserId); - if (userId[0] != null && userId[2] != null) { - return userId[0] + " (" + userId[2] + ")"; - } else if (userId[0] != null) { - return userId[0]; + if (mUserId[0] != null && mUserId[2] != null) { + return mUserId[0] + " (" + mUserId[2] + ")"; + } else if (mUserId[0] != null) { + return mUserId[0]; } else { - return userId[1]; + return mUserId[1]; } } public String getSecondary() { - String[] userId = KeyRing.splitUserId(mUserId); - if (userId[0] != null) { - return userId[1] + " (" + getKeyIdHexShort() + ")"; + if (mUserId[0] != null) { + return mUserId[1]; } else { return getKeyIdHex(); } } + public String getTertiary() { + if (mUserId[0] != null) { + return getKeyIdHex(); + } else { + return null; + } + } + public long getKeyId() { return mKeyId; } @@ -216,6 +224,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } ((TextView) view.findViewById(android.R.id.title)).setText(getItem(position).getPrimary()); ((TextView) view.findViewById(android.R.id.text1)).setText(getItem(position).getSecondary()); + ((TextView) view.findViewById(android.R.id.text2)).setText(getItem(position).getTertiary()); setImageByKey((ImageView) view.findViewById(android.R.id.icon), getItem(position)); return view; } -- cgit v1.2.3 From e17c1a0cd4581adce49a9941b2f4fadbdbf5a94d Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sat, 2 Aug 2014 00:51:56 +0200 Subject: Fix focusing with To field --- .../sufficientlysecure/keychain/ui/EncryptFileFragment.java | 10 +++++++--- .../keychain/ui/widget/EncryptKeyCompletionView.java | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 7650c3954..6bbbac713 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -27,6 +27,7 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; @@ -58,6 +59,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte private View mAddView; private View mShareFile; private View mEncryptFile; + private ListView mSelectedFiles; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); private final Map thumbnailCache = new HashMap(); @@ -100,9 +102,9 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte addInputUri(); } }); - ListView listView = (ListView) view.findViewById(R.id.selected_files_list); - listView.addFooterView(mAddView); - listView.setAdapter(mAdapter); + mSelectedFiles = (ListView) view.findViewById(R.id.selected_files_list); + mSelectedFiles.addFooterView(mAddView); + mSelectedFiles.setAdapter(mAdapter); return view; } @@ -139,6 +141,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte mEncryptInterface.getInputUris().add(inputUri); mEncryptInterface.notifyUpdate(); + mSelectedFiles.requestFocus(); /** * We hide the encrypt to file button if multiple files are selected. @@ -157,6 +160,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte private void delInputUri(int position) { mEncryptInterface.getInputUris().remove(position); mEncryptInterface.notifyUpdate(); + mSelectedFiles.requestFocus(); if (mEncryptInterface.getInputUris().size() > 1) { mEncryptFile.setVisibility(View.GONE); 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 329ef2c9b..f1c17bfb5 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 @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; +import android.graphics.Rect; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; @@ -13,6 +14,7 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.TextView; import com.tokenautocomplete.FilteredArrayAdapter; @@ -109,6 +111,15 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } } + @Override + public void onFocusChanged(boolean hasFocus, int direction, Rect previous) { + super.onFocusChanged(hasFocus, direction, previous); + if (hasFocus) { + ((InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE)) + .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); + } + } + public void swapCursor(Cursor cursor) { if (cursor == null) { setAdapter(new EncryptKeyAdapter(Collections.emptyList())); -- cgit v1.2.3 From d4f2d3842b0a9e5611657ed1889154a950becc19 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sat, 2 Aug 2014 04:16:26 +0200 Subject: Minor cleanup --- .../main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 1 - .../sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 8a516e6af..303db60ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -218,7 +218,6 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn Notify.showNotify(EncryptActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO); if (!isContentMessage() && mDeleteAfterEncrypt) { - // TODO: Create and show dialog to delete original file for (Uri inputUri : mInputUris) { DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUri); deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index 27ce4faee..5e296c062 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -85,7 +85,7 @@ public class DeleteFileDialogFragment extends DialogFragment { Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, deleteFilename), Toast.LENGTH_SHORT).show(); - // TODO: We can't delete that file... + // Note: We can't delete every file... // If possible we should find out if deletion is possible before even showing the option to do so. } }); -- cgit v1.2.3 From d4240f73f5df91eaf2e7cc6bdc88a4e6b984746b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 4 Aug 2014 00:39:49 +0200 Subject: delete unused PgpConversionHelper --- .../keychain/pgp/PgpConversionHelper.java | 102 --------------------- 1 file changed, 102 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java deleted file mode 100644 index 3a5a96fbb..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java +++ /dev/null @@ -1,102 +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.pgp; - -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; - -public class PgpConversionHelper { - - /** - * Convert from byte[] to ArrayList - * - * @param keysBytes - * @return - */ - public static ArrayList BytesToPGPSecretKeyList(byte[] keysBytes) { - PGPObjectFactory factory = new PGPObjectFactory(keysBytes); - Object obj = null; - ArrayList keys = new ArrayList(); - try { - while ((obj = factory.nextObject()) != null) { - PGPSecretKey secKey = null; - if (obj instanceof PGPSecretKey) { - secKey = (PGPSecretKey) obj; - if (secKey == null) { - Log.e(Constants.TAG, "No keys given!"); - } - keys.add(new UncachedSecretKey(secKey)); - } else if (obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings - PGPSecretKeyRing keyRing = null; - keyRing = (PGPSecretKeyRing) obj; - if (keyRing == null) { - Log.e(Constants.TAG, "No keys given!"); - } - @SuppressWarnings("unchecked") - Iterator itr = keyRing.getSecretKeys(); - while (itr.hasNext()) { - keys.add(new UncachedSecretKey(itr.next())); - } - } - } - } catch (IOException e) { - } - - return keys; - } - - /** - * Convert from byte[] to PGPSecretKey - *

- * Singles keys are encoded as keyRings with one single key in it by Bouncy Castle - * - * @param keyBytes - * @return - */ - public static UncachedSecretKey BytesToPGPSecretKey(byte[] keyBytes) { - PGPObjectFactory factory = new PGPObjectFactory(keyBytes); - Object obj = null; - try { - obj = factory.nextObject(); - } catch (IOException e) { - Log.e(Constants.TAG, "Error while converting to PGPSecretKey!", e); - } - PGPSecretKey secKey = null; - if (obj instanceof PGPSecretKey) { - if ((secKey = (PGPSecretKey) obj) == null) { - Log.e(Constants.TAG, "No keys given!"); - } - } else if (obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings - PGPSecretKeyRing keyRing = null; - if ((keyRing = (PGPSecretKeyRing) obj) == null) { - Log.e(Constants.TAG, "No keys given!"); - } - secKey = keyRing.getSecretKey(); - } - - return new UncachedSecretKey(secKey); - } - -} -- cgit v1.2.3 From 4979ccd645e605f66afd9e4e6174dd7f27687e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 00:49:16 +0200 Subject: Smaller UI fixes --- .../java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 2 +- .../sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java | 1 + .../keychain/ui/dialog/AddUserIdDialogFragment.java | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 303db60ed..211802717 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -489,7 +489,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn * Android's Action */ if (Intent.ACTION_SEND.equals(action) && type != null) { - // When sending to APG Encrypt via share menu + // When sending to OpenKeychain Encrypt via share menu if ("text/plain".equals(type)) { // Plain text String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index ed3be0e7f..3de617ca0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -115,6 +115,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi } }); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); + mEncryptKeyView.setThreshold(1); // Start working from first character return view; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index d5264ae10..226bdf51e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -149,6 +149,14 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA } }); + mName.setThreshold(1); // Start working from first character + mName.setAdapter( + new ArrayAdapter + (getActivity(), android.R.layout.simple_spinner_dropdown_item, + ContactHelper.getPossibleUserNames(getActivity()) + ) + ); + alert.setNegativeButton(android.R.string.cancel, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { -- cgit v1.2.3 From c39cf197f4b1d03ff5d973441a1ffe70b2601a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 00:54:57 +0200 Subject: button language in encrypt --- .../main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index cd5671801..35170fc37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -35,7 +35,6 @@ import android.widget.TextView; import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -- cgit v1.2.3 From 7f463ae0dfcc3c0299c8ff943f8a021bfa5476f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 02:26:34 +0200 Subject: Edit key: subkey adding, not finished --- .../keychain/ui/EditKeyFragment.java | 19 +- .../keychain/ui/adapter/ImportKeysAdapter.java | 2 +- .../ui/adapter/SelectKeyCursorAdapter.java | 2 +- .../keychain/ui/adapter/SubkeysAdapter.java | 36 ++- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 323 ++++---------------- .../ui/dialog/AddSubkeyDialogFragment.java | 328 +++++++++++++++++++++ .../ui/dialog/CreateKeyDialogFragment.java | 322 -------------------- .../keychain/ui/widget/KeyEditor.java | 2 +- .../keychain/ui/widget/SectionView.java | 36 +-- 9 files changed, 434 insertions(+), 636 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java (limited to 'OpenKeychain/src/main/java') 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 b76755bb2..2d8bdad27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; +import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ChangeExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; @@ -65,7 +66,6 @@ import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.util.ArrayList; import java.util.Date; public class EditKeyFragment extends LoaderFragment implements @@ -453,8 +453,21 @@ public class EditKeyFragment extends LoaderFragment implements } private void addSubkey() { - // default values - mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); + boolean willBeMasterKey = mSubkeysAdapter.getCount() == 0 + && mSubkeysAddedAdapter.getCount() == 0; + + AddSubkeyDialogFragment addSubkeyDialogFragment = + AddSubkeyDialogFragment.newInstance(willBeMasterKey); + addSubkeyDialogFragment + .setOnAlgorithmSelectedListener( + new AddSubkeyDialogFragment.OnAlgorithmSelectedListener() { + @Override + public void onAlgorithmSelected(SaveKeyringParcel.SubkeyAdd newSubkey) { + mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); + } + } + ); + addSubkeyDialogFragment.show(getActivity().getSupportFragmentManager(), "addSubkeyDialog"); } private void cachePassphraseForEdit() { 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 7a55f9aaa..1f809cc51 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 @@ -111,7 +111,7 @@ public class ImportKeysAdapter extends ArrayAdapter { convertView = mInflater.inflate(R.layout.import_keys_list_entry, null); holder.mainUserId = (TextView) convertView.findViewById(R.id.mainUserId); holder.mainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest); - holder.keyId = (TextView) convertView.findViewById(R.id.keyId); + holder.keyId = (TextView) convertView.findViewById(R.id.subkey_item_key_id); holder.fingerprint = (TextView) convertView.findViewById(R.id.view_key_fingerprint); holder.algorithm = (TextView) convertView.findViewById(R.id.algorithm); holder.status = (TextView) convertView.findViewById(R.id.status); 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 e69a63c63..0e2177568 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 @@ -152,7 +152,7 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { holder.view = view; holder.mainUserId = (TextView) view.findViewById(R.id.mainUserId); holder.mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - holder.keyId = (TextView) view.findViewById(R.id.keyId); + holder.keyId = (TextView) view.findViewById(R.id.subkey_item_key_id); holder.status = (TextView) view.findViewById(R.id.status); holder.selected = (CheckBox) view.findViewById(R.id.selected); view.setTag(holder); 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 c2a882fdb..0d8c7240d 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 @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.content.res.ColorStateList; import android.database.Cursor; +import android.graphics.Typeface; import android.support.v4.widget.CursorAdapter; import android.text.format.DateFormat; import android.view.LayoutInflater; @@ -106,15 +107,18 @@ public class SubkeysAdapter extends CursorAdapter { @Override public void bindView(View view, Context context, Cursor cursor) { - TextView vKeyId = (TextView) view.findViewById(R.id.keyId); - TextView vKeyDetails = (TextView) view.findViewById(R.id.keyDetails); - TextView vKeyExpiry = (TextView) view.findViewById(R.id.keyExpiry); - ImageView vMasterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey); - ImageView vCertifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey); - ImageView vEncryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey); - ImageView vSignIcon = (ImageView) view.findViewById(R.id.ic_signKey); - ImageView vRevokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey); - ImageView vEditImage = (ImageView) view.findViewById(R.id.user_id_item_edit_image); + TextView vKeyId = (TextView) view.findViewById(R.id.subkey_item_key_id); + TextView vKeyDetails = (TextView) view.findViewById(R.id.subkey_item_details); + TextView vKeyExpiry = (TextView) view.findViewById(R.id.subkey_item_expiry); + ImageView vCertifyIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_certify); + ImageView vEncryptIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_encrypt); + ImageView vSignIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_sign); + ImageView vRevokedIcon = (ImageView) view.findViewById(R.id.subkey_item_ic_revoked); + ImageView vEditImage = (ImageView) view.findViewById(R.id.subkey_item_edit_image); + + // not used: + ImageView deleteImage = (ImageView) view.findViewById(R.id.subkey_item_delete_button); + deleteImage.setVisibility(View.GONE); long keyId = cursor.getLong(INDEX_KEY_ID); String keyIdStr = PgpKeyHelper.convertKeyIdToHex(keyId); @@ -133,8 +137,14 @@ public class SubkeysAdapter extends CursorAdapter { vKeyDetails.setText(algorithmStr); } + boolean isMasterKey = cursor.getInt(INDEX_RANK) == 0; + if (isMasterKey) { + vKeyId.setTypeface(null, Typeface.BOLD); + } else { + vKeyId.setTypeface(null, Typeface.NORMAL); + } + // Set icons according to properties - vMasterKeyIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE); vCertifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE); vEncryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE); vSignIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE); @@ -157,13 +167,13 @@ public class SubkeysAdapter extends CursorAdapter { } if (isRevoked) { - vRevokedKeyIcon.setVisibility(View.VISIBLE); + vRevokedIcon.setVisibility(View.VISIBLE); } else { vKeyId.setTextColor(mDefaultTextColor); vKeyDetails.setTextColor(mDefaultTextColor); vKeyExpiry.setTextColor(mDefaultTextColor); - vRevokedKeyIcon.setVisibility(View.GONE); + vRevokedIcon.setVisibility(View.GONE); } boolean isExpired; @@ -195,7 +205,7 @@ public class SubkeysAdapter extends CursorAdapter { public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = mInflater.inflate(R.layout.view_key_subkey_item, null); if (mDefaultTextColor == null) { - TextView keyId = (TextView) view.findViewById(R.id.keyId); + TextView keyId = (TextView) view.findViewById(R.id.subkey_item_key_id); mDefaultTextColor = keyId.getTextColors(); } return view; 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 25509fee5..1ec9add68 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 @@ -17,48 +17,28 @@ package org.sufficientlysecure.keychain.ui.adapter; -import android.annotation.TargetApi; import android.app.Activity; -import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; -import android.os.Build; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.Patterns; +import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.EditText; import android.widget.ImageButton; -import android.widget.Spinner; +import android.widget.ImageView; import android.widget.TextView; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment; -import org.sufficientlysecure.keychain.util.Choice; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Date; import java.util.List; -import java.util.regex.Matcher; public class SubkeysAddedAdapter extends ArrayAdapter { private LayoutInflater mInflater; private Activity mActivity; - public interface OnAlgorithmSelectedListener { - public void onAlgorithmSelected(Choice algorithmChoice, int keySize); - } - // hold a private reference to the underlying data List private List mData; @@ -70,12 +50,13 @@ public class SubkeysAddedAdapter extends ArrayAdapter parent, View view, int position, long id) { - Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem(); - // update referenced model item - holder.mModel.mAlgorithm = newKeyAlgorithmChoice.getId(); - } + holder.vKeyId = (TextView) convertView.findViewById(R.id.subkey_item_key_id); + holder.vKeyDetails = (TextView) convertView.findViewById(R.id.subkey_item_details); + holder.vKeyExpiry = (TextView) convertView.findViewById(R.id.subkey_item_expiry); + holder.vCertifyIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_certify); + holder.vEncryptIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_encrypt); + holder.vSignIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_sign); + holder.vRevokedIcon = (ImageView) convertView.findViewById(R.id.subkey_item_ic_revoked); + holder.vDelete = (ImageButton) convertView.findViewById(R.id.subkey_item_delete_button); + holder.vDelete.setVisibility(View.VISIBLE); // always visible + + // not used: + ImageView editImage = (ImageView) convertView.findViewById(R.id.subkey_item_edit_image); + editImage.setVisibility(View.GONE); - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - - holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem(); - int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), - getSelectedKeyLength(holder.mKeySizeSpinner, holder.mCustomKeyEditText)); - // update referenced model item - holder.mModel.mKeysize = newKeySize; - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); + convertView.setTag(holder); holder.vDelete.setOnClickListener(new View.OnClickListener() { @Override @@ -136,83 +97,30 @@ public class SubkeysAddedAdapter extends ArrayAdapter choices = new ArrayList(); - choices.add(new Choice(Constants.choice.algorithm.dsa, mActivity.getResources().getString( - R.string.dsa))); - if (!wouldBeMasterKey) { - choices.add(new Choice(Constants.choice.algorithm.elgamal, mActivity.getResources().getString( - R.string.elgamal))); - } - - choices.add(new Choice(Constants.choice.algorithm.rsa, mActivity.getResources().getString( - R.string.rsa))); - - ArrayAdapter adapter = new ArrayAdapter(mActivity, - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - holder.mAlgorithmSpinner.setAdapter(adapter); - // make RSA the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Constants.choice.algorithm.rsa) { - holder.mAlgorithmSpinner.setSelection(i); - break; - } - } - - // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change - ArrayAdapter keySizeAdapter = new ArrayAdapter(mActivity, android.R.layout.simple_spinner_item, - new ArrayList(Arrays.asList(mActivity.getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); - keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - holder.mKeySizeSpinner.setAdapter(keySizeAdapter); - holder.mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length - - holder.mCustomKeyEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { -// setOkButtonAvailability(alertDialog); - } - }); - - holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText, - holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView); -// setOkButtonAvailability(alertDialog); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - - holder.mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId(), - holder.mKeySizeSpinner, holder.mCustomKeyInfoTextView); - - setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText, - holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView); -// setOkButtonAvailability(alertDialog); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); + String algorithmStr = PgpKeyHelper.getAlgorithmInfo( + mActivity, + holder.mModel.mAlgorithm, + holder.mModel.mKeysize + ); + holder.vKeyId.setText("new"); + holder.vKeyDetails.setText(algorithmStr); + + // Set icons according to properties +// holder.vMasterIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE); +// holder.vCertifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE); +// holder.vEncryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE); +// holder.vSignIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE); +// if (!cursor.isNull(INDEX_EXPIRY)) { +// Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); +// isExpired = expiryDate.before(new Date()); +// +// holder.vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " +// + DateFormat.getDateFormat(context).format(expiryDate)); +// } else { +// isExpired = false; +// +// holder.vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none)); +// } // // holder.vAddress.setText(holder.mModel.address); // holder.vAddress.setThreshold(1); // Start working from first character @@ -227,135 +135,4 @@ public class SubkeysAddedAdapter extends ArrayAdapterRSA - *

for RSA algorithm, key length must be greater than 1024 (according to - * #102). Possibility to generate keys bigger - * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check - * RSA key length plot and - * Cryptographic Key Length Recommendation). Also, key length must be a - * multiplicity of 8.

- *

ElGamal

- *

For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.

- *

DSA

- *

For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.

- * - * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is - * inappropriate. - */ - private int getProperKeyLength(int algorithmId, int currentKeyLength) { - final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; - int properKeyLength = -1; - switch (algorithmId) { - case Constants.choice.algorithm.rsa: - if (currentKeyLength > 1024 && currentKeyLength <= 8192) { - properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); - } - break; - case Constants.choice.algorithm.elgamal: - int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; - for (int i = 0; i < elGamalSupportedLengths.length; i++) { - elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); - } - int minimalValue = Integer.MAX_VALUE; - int minimalIndex = -1; - for (int i = 0; i < elGammalKeyDiff.length; i++) { - if (elGammalKeyDiff[i] <= minimalValue) { - minimalValue = elGammalKeyDiff[i]; - minimalIndex = i; - } - } - properKeyLength = elGamalSupportedLengths[minimalIndex]; - break; - case Constants.choice.algorithm.dsa: - if (currentKeyLength >= 512 && currentKeyLength <= 1024) { - properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); - } - break; - } - return properKeyLength; - } - - // TODO: make this an error message on the field -// private boolean setOkButtonAvailability(AlertDialog alertDialog) { -// final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem(); -// final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem()); -// final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize); -// alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0); -// } - - private void setCustomKeyVisibility(Spinner keySizeSpinner, EditText customkeyedittext, TextView customKeyTextView, TextView customKeyInfoTextView) { - final String selectedItemString = (String) keySizeSpinner.getSelectedItem(); - final String customLengthString = mActivity.getResources().getString(R.string.key_size_custom); - final boolean customSelected = customLengthString.equals(selectedItemString); - final int visibility = customSelected ? View.VISIBLE : View.GONE; - - customkeyedittext.setVisibility(visibility); - customKeyTextView.setVisibility(visibility); - customKeyInfoTextView.setVisibility(visibility); - - // hide keyboard after setting visibility to gone - if (visibility == View.GONE) { - InputMethodManager imm = (InputMethodManager) - mActivity.getSystemService(mActivity.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(customkeyedittext.getWindowToken(), 0); - } - } - - private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId, Spinner keySizeSpinner, TextView customKeyInfoTextView) { - final ArrayAdapter keySizeAdapter = (ArrayAdapter) keySizeSpinner.getAdapter(); - final Object selectedItem = keySizeSpinner.getSelectedItem(); - keySizeAdapter.clear(); - switch (algorithmId) { - case Constants.choice.algorithm.rsa: - replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); - customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_rsa)); - break; - case Constants.choice.algorithm.elgamal: - replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); - customKeyInfoTextView.setText(""); // ElGamal does not support custom key length - break; - case Constants.choice.algorithm.dsa: - replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); - customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_dsa)); - break; - } - keySizeAdapter.notifyDataSetChanged(); - - // when switching algorithm, try to select same key length as before - for (int i = 0; i < keySizeAdapter.getCount(); i++) { - if (selectedItem.equals(keySizeAdapter.getItem(i))) { - keySizeSpinner.setSelection(i); - break; - } - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) { - final String[] spinnerValuesStringArray = mActivity.getResources().getStringArray(stringArrayResourceId); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - arrayAdapter.addAll(spinnerValuesStringArray); - } else { - for (final String value : spinnerValuesStringArray) { - arrayAdapter.add(value); - } - } - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java new file mode 100644 index 000000000..2031eae2a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2012-2013 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.dialog; + +import android.annotation.TargetApi; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; + +import org.spongycastle.bcpg.sig.KeyFlags; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.util.Choice; + +import java.util.ArrayList; +import java.util.Arrays; + +public class AddSubkeyDialogFragment extends DialogFragment { + + public interface OnAlgorithmSelectedListener { + public void onAlgorithmSelected(SaveKeyringParcel.SubkeyAdd newSubkey); + } + + private static final String ARG_WILL_BE_MASTER_KEY = "will_be_master_key"; + + private OnAlgorithmSelectedListener mAlgorithmSelectedListener; + private Spinner mAlgorithmSpinner; + private Spinner mKeySizeSpinner; + private TextView mCustomKeyTextView; + private EditText mCustomKeyEditText; + private TextView mCustomKeyInfoTextView; + + public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) { + mAlgorithmSelectedListener = listener; + } + + public static AddSubkeyDialogFragment newInstance(boolean willBeMasterKey) { + AddSubkeyDialogFragment frag = new AddSubkeyDialogFragment(); + Bundle args = new Bundle(); + + args.putBoolean(ARG_WILL_BE_MASTER_KEY, willBeMasterKey); + + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity context = getActivity(); + final LayoutInflater mInflater; + + final boolean willBeMasterKey = getArguments().getBoolean(ARG_WILL_BE_MASTER_KEY); + mInflater = context.getLayoutInflater(); + + CustomAlertDialogBuilder dialog = new CustomAlertDialogBuilder(context); + + View view = mInflater.inflate(R.layout.create_key_dialog, null); + dialog.setView(view); + dialog.setTitle(R.string.title_create_key); + + mAlgorithmSpinner = (Spinner) view.findViewById(R.id.create_key_algorithm); + ArrayList choices = new ArrayList(); + choices.add(new Choice(Constants.choice.algorithm.dsa, getResources().getString( + R.string.dsa))); + if (!willBeMasterKey) { + choices.add(new Choice(Constants.choice.algorithm.elgamal, getResources().getString( + R.string.elgamal))); + } + + choices.add(new Choice(Constants.choice.algorithm.rsa, getResources().getString( + R.string.rsa))); + + ArrayAdapter adapter = new ArrayAdapter(context, + android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mAlgorithmSpinner.setAdapter(adapter); + // make RSA the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Constants.choice.algorithm.rsa) { + mAlgorithmSpinner.setSelection(i); + break; + } + } + + mKeySizeSpinner = (Spinner) view.findViewById(R.id.create_key_size); + // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change + ArrayAdapter keySizeAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, + new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); + keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mKeySizeSpinner.setAdapter(keySizeAdapter); + mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length + + mCustomKeyTextView = (TextView) view.findViewById(R.id.custom_key_size_label); + mCustomKeyEditText = (EditText) view.findViewById(R.id.custom_key_size_input); + mCustomKeyInfoTextView = (TextView) view.findViewById(R.id.custom_key_size_info); + + dialog.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); + int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); + SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd( + newKeyAlgorithmChoice.getId(), + newKeySize, + KeyFlags.SIGN_DATA, //TODO + null + ); + mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey); + } + } + ); + + dialog.setCancelable(true); + dialog.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + } + }); + + final AlertDialog alertDialog = dialog.show(); + + mCustomKeyEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + setOkButtonAvailability(alertDialog); + } + }); + + mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setCustomKeyVisibility(); + setOkButtonAvailability(alertDialog); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId()); + + setCustomKeyVisibility(); + setOkButtonAvailability(alertDialog); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + return alertDialog; + } + + private int getSelectedKeyLength() { + final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); + final String customLengthString = getResources().getString(R.string.key_size_custom); + final boolean customSelected = customLengthString.equals(selectedItemString); + String keyLengthString = customSelected ? mCustomKeyEditText.getText().toString() : selectedItemString; + int keySize; + try { + keySize = Integer.parseInt(keyLengthString); + } catch (NumberFormatException e) { + keySize = 0; + } + return keySize; + } + + /** + *

RSA

+ *

for RSA algorithm, key length must be greater than 1024 (according to + * #102). Possibility to generate keys bigger + * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check + * RSA key length plot and + * Cryptographic Key Length Recommendation). Also, key length must be a + * multiplicity of 8.

+ *

ElGamal

+ *

For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.

+ *

DSA

+ *

For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.

+ * + * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is + * inappropriate. + */ + private int getProperKeyLength(int algorithmId, int currentKeyLength) { + final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; + int properKeyLength = -1; + switch (algorithmId) { + case Constants.choice.algorithm.rsa: + if (currentKeyLength > 1024 && currentKeyLength <= 8192) { + properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); + } + break; + case Constants.choice.algorithm.elgamal: + int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; + for (int i = 0; i < elGamalSupportedLengths.length; i++) { + elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); + } + int minimalValue = Integer.MAX_VALUE; + int minimalIndex = -1; + for (int i = 0; i < elGammalKeyDiff.length; i++) { + if (elGammalKeyDiff[i] <= minimalValue) { + minimalValue = elGammalKeyDiff[i]; + minimalIndex = i; + } + } + properKeyLength = elGamalSupportedLengths[minimalIndex]; + break; + case Constants.choice.algorithm.dsa: + if (currentKeyLength >= 512 && currentKeyLength <= 1024) { + properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); + } + break; + } + return properKeyLength; + } + + private void setOkButtonAvailability(AlertDialog alertDialog) { + final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem(); + final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem()); + final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize); + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0); + } + + private void setCustomKeyVisibility() { + final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); + final String customLengthString = getResources().getString(R.string.key_size_custom); + final boolean customSelected = customLengthString.equals(selectedItemString); + final int visibility = customSelected ? View.VISIBLE : View.GONE; + + mCustomKeyEditText.setVisibility(visibility); + mCustomKeyTextView.setVisibility(visibility); + mCustomKeyInfoTextView.setVisibility(visibility); + + // hide keyboard after setting visibility to gone + if (visibility == View.GONE) { + InputMethodManager imm = (InputMethodManager) + getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mCustomKeyEditText.getWindowToken(), 0); + } + } + + private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId) { + final ArrayAdapter keySizeAdapter = (ArrayAdapter) mKeySizeSpinner.getAdapter(); + final Object selectedItem = mKeySizeSpinner.getSelectedItem(); + keySizeAdapter.clear(); + switch (algorithmId) { + case Constants.choice.algorithm.rsa: + replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); + mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); + break; + case Constants.choice.algorithm.elgamal: + replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); + mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length + break; + case Constants.choice.algorithm.dsa: + replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); + mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); + break; + } + keySizeAdapter.notifyDataSetChanged(); + + // when switching algorithm, try to select same key length as before + for (int i = 0; i < keySizeAdapter.getCount(); i++) { + if (selectedItem.equals(keySizeAdapter.getItem(i))) { + mKeySizeSpinner.setSelection(i); + break; + } + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) { + final String[] spinnerValuesStringArray = getResources().getStringArray(stringArrayResourceId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + arrayAdapter.addAll(spinnerValuesStringArray); + } else { + for (final String value : spinnerValuesStringArray) { + arrayAdapter.add(value); + } + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java deleted file mode 100644 index 920743a9b..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2012-2013 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.dialog; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Choice; - -import java.util.ArrayList; -import java.util.Arrays; - -public class CreateKeyDialogFragment extends DialogFragment { - - public interface OnAlgorithmSelectedListener { - public void onAlgorithmSelected(Choice algorithmChoice, int keySize); - } - - private static final String ARG_EDITOR_CHILD_COUNT = "child_count"; - - private OnAlgorithmSelectedListener mAlgorithmSelectedListener; - private Spinner mAlgorithmSpinner; - private Spinner mKeySizeSpinner; - private TextView mCustomKeyTextView; - private EditText mCustomKeyEditText; - private TextView mCustomKeyInfoTextView; - - public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) { - mAlgorithmSelectedListener = listener; - } - - public static CreateKeyDialogFragment newInstance(int mEditorChildCount) { - CreateKeyDialogFragment frag = new CreateKeyDialogFragment(); - Bundle args = new Bundle(); - - args.putInt(ARG_EDITOR_CHILD_COUNT, mEditorChildCount); - - frag.setArguments(args); - - return frag; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final FragmentActivity context = getActivity(); - final LayoutInflater mInflater; - - final int childCount = getArguments().getInt(ARG_EDITOR_CHILD_COUNT); - mInflater = context.getLayoutInflater(); - - CustomAlertDialogBuilder dialog = new CustomAlertDialogBuilder(context); - - View view = mInflater.inflate(R.layout.create_key_dialog, null); - dialog.setView(view); - dialog.setTitle(R.string.title_create_key); - - boolean wouldBeMasterKey = (childCount == 0); - - mAlgorithmSpinner = (Spinner) view.findViewById(R.id.create_key_algorithm); - ArrayList choices = new ArrayList(); - choices.add(new Choice(Constants.choice.algorithm.dsa, getResources().getString( - R.string.dsa))); - if (!wouldBeMasterKey) { - choices.add(new Choice(Constants.choice.algorithm.elgamal, getResources().getString( - R.string.elgamal))); - } - - choices.add(new Choice(Constants.choice.algorithm.rsa, getResources().getString( - R.string.rsa))); - - ArrayAdapter adapter = new ArrayAdapter(context, - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mAlgorithmSpinner.setAdapter(adapter); - // make RSA the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Constants.choice.algorithm.rsa) { - mAlgorithmSpinner.setSelection(i); - break; - } - } - - mKeySizeSpinner = (Spinner) view.findViewById(R.id.create_key_size); - // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change - ArrayAdapter keySizeAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, - new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); - keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mKeySizeSpinner.setAdapter(keySizeAdapter); - mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length - - mCustomKeyTextView = (TextView) view.findViewById(R.id.custom_key_size_label); - mCustomKeyEditText = (EditText) view.findViewById(R.id.custom_key_size_input); - mCustomKeyInfoTextView = (TextView) view.findViewById(R.id.custom_key_size_info); - - dialog.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); - int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); - mAlgorithmSelectedListener.onAlgorithmSelected(newKeyAlgorithmChoice, newKeySize); - } - } - ); - - dialog.setCancelable(true); - dialog.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - } - }); - - final AlertDialog alertDialog = dialog.show(); - - mCustomKeyEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - setOkButtonAvailability(alertDialog); - } - }); - - mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - setCustomKeyVisibility(); - setOkButtonAvailability(alertDialog); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - - mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId()); - - setCustomKeyVisibility(); - setOkButtonAvailability(alertDialog); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - - return alertDialog; - } - - private int getSelectedKeyLength() { - final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); - final String customLengthString = getResources().getString(R.string.key_size_custom); - final boolean customSelected = customLengthString.equals(selectedItemString); - String keyLengthString = customSelected ? mCustomKeyEditText.getText().toString() : selectedItemString; - int keySize; - try { - keySize = Integer.parseInt(keyLengthString); - } catch (NumberFormatException e) { - keySize = 0; - } - return keySize; - } - - /** - *

RSA

- *

for RSA algorithm, key length must be greater than 1024 (according to - * #102). Possibility to generate keys bigger - * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check - * RSA key length plot and - * Cryptographic Key Length Recommendation). Also, key length must be a - * multiplicity of 8.

- *

ElGamal

- *

For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.

- *

DSA

- *

For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.

- * - * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is - * inappropriate. - */ - private int getProperKeyLength(int algorithmId, int currentKeyLength) { - final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; - int properKeyLength = -1; - switch (algorithmId) { - case Constants.choice.algorithm.rsa: - if (currentKeyLength > 1024 && currentKeyLength <= 8192) { - properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); - } - break; - case Constants.choice.algorithm.elgamal: - int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; - for (int i = 0; i < elGamalSupportedLengths.length; i++) { - elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); - } - int minimalValue = Integer.MAX_VALUE; - int minimalIndex = -1; - for (int i = 0; i < elGammalKeyDiff.length; i++) { - if (elGammalKeyDiff[i] <= minimalValue) { - minimalValue = elGammalKeyDiff[i]; - minimalIndex = i; - } - } - properKeyLength = elGamalSupportedLengths[minimalIndex]; - break; - case Constants.choice.algorithm.dsa: - if (currentKeyLength >= 512 && currentKeyLength <= 1024) { - properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); - } - break; - } - return properKeyLength; - } - - private void setOkButtonAvailability(AlertDialog alertDialog) { - final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem(); - final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem()); - final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize); - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0); - } - - private void setCustomKeyVisibility() { - final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); - final String customLengthString = getResources().getString(R.string.key_size_custom); - final boolean customSelected = customLengthString.equals(selectedItemString); - final int visibility = customSelected ? View.VISIBLE : View.GONE; - - mCustomKeyEditText.setVisibility(visibility); - mCustomKeyTextView.setVisibility(visibility); - mCustomKeyInfoTextView.setVisibility(visibility); - - // hide keyboard after setting visibility to gone - if (visibility == View.GONE) { - InputMethodManager imm = (InputMethodManager) - getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(mCustomKeyEditText.getWindowToken(), 0); - } - } - - private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId) { - final ArrayAdapter keySizeAdapter = (ArrayAdapter) mKeySizeSpinner.getAdapter(); - final Object selectedItem = mKeySizeSpinner.getSelectedItem(); - keySizeAdapter.clear(); - switch (algorithmId) { - case Constants.choice.algorithm.rsa: - replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); - mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); - break; - case Constants.choice.algorithm.elgamal: - replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); - mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length - break; - case Constants.choice.algorithm.dsa: - replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); - mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); - break; - } - keySizeAdapter.notifyDataSetChanged(); - - // when switching algorithm, try to select same key length as before - for (int i = 0; i < keySizeAdapter.getCount(); i++) { - if (selectedItem.equals(keySizeAdapter.getItem(i))) { - mKeySizeSpinner.setSelection(i); - break; - } - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) { - final String[] spinnerValuesStringArray = getResources().getStringArray(stringArrayResourceId); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - arrayAdapter.addAll(spinnerValuesStringArray); - } else { - for (final String value : spinnerValuesStringArray) { - arrayAdapter.add(value); - } - } - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java index c23b4c3ff..484ce8e47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java @@ -120,7 +120,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { setAlwaysDrawnWithCacheEnabled(true); mAlgorithm = (TextView) findViewById(R.id.algorithm); - mKeyId = (TextView) findViewById(R.id.keyId); + mKeyId = (TextView) findViewById(R.id.subkey_item_key_id); mCreationDate = (TextView) findViewById(R.id.creation); mExpiryDateButton = (Button) findViewById(R.id.expiry); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 35170fc37..190db1fe3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -17,13 +17,7 @@ package org.sufficientlysecure.keychain.ui.widget; -import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; import android.support.v7.app.ActionBarActivity; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -36,10 +30,8 @@ import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; import org.sufficientlysecure.keychain.util.Choice; @@ -280,19 +272,19 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor } case TYPE_KEY: { - CreateKeyDialogFragment mCreateKeyDialogFragment = - CreateKeyDialogFragment.newInstance(mEditors.getChildCount()); - mCreateKeyDialogFragment - .setOnAlgorithmSelectedListener( - new CreateKeyDialogFragment.OnAlgorithmSelectedListener() { - @Override - public void onAlgorithmSelected(Choice algorithmChoice, int keySize) { - mNewKeyAlgorithmChoice = algorithmChoice; - mNewKeySize = keySize; - createKey(); - } - }); - mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog"); +// AddSubkeyDialogFragment mCreateKeyDialogFragment = +// AddSubkeyDialogFragment.newInstance(mEditors.getChildCount()); +// mCreateKeyDialogFragment +// .setOnAlgorithmSelectedListener( +// new AddSubkeyDialogFragment.OnAlgorithmSelectedListener() { +// @Override +// public void onAlgorithmSelected(Choice algorithmChoice, int keySize) { +// mNewKeyAlgorithmChoice = algorithmChoice; +// mNewKeySize = keySize; +// createKey(); +// } +// }); +// mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog"); break; } -- cgit v1.2.3 From fb5c829ff7aedd87e3a190e2e17d2f1503908679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 02:31:54 +0200 Subject: Remove old edit key stuff --- .../keychain/ui/widget/KeyEditor.java | 380 ------------------- .../keychain/ui/widget/SectionView.java | 419 --------------------- .../keychain/ui/widget/UserIdEditor.java | 267 ------------- 3 files changed, 1066 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java deleted file mode 100644 index 484ce8e47..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 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.widget; - -import android.annotation.TargetApi; -import android.app.DatePickerDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.text.format.DateUtils; -import android.util.AttributeSet; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.DatePicker; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.TableLayout; -import android.widget.TableRow; -import android.widget.TextView; -import android.widget.Button; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; - -import java.text.DateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class KeyEditor extends LinearLayout implements Editor, OnClickListener { - private UncachedSecretKey mKey; - - private EditorListener mEditorListener = null; - - private boolean mIsMasterKey; - ImageButton mDeleteButton; - TextView mAlgorithm; - TextView mKeyId; - TextView mCreationDate; - Button mExpiryDateButton; - Calendar mCreatedDate; - Calendar mExpiryDate; - Calendar mOriginalExpiryDate = null; - CheckBox mChkCertify; - CheckBox mChkSign; - CheckBox mChkEncrypt; - CheckBox mChkAuthenticate; - int mUsage; - int mOriginalUsage; - boolean mIsNewKey; - - private CheckBox.OnCheckedChangeListener mCheckChanged = new CheckBox.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - }; - - - private int mDatePickerResultCount = 0; - private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = - new DatePickerDialog.OnDateSetListener() { - public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("UTC")); - date.set(year, monthOfYear, dayOfMonth); - if (mOriginalExpiryDate != null) { - long numDays = (date.getTimeInMillis() / 86400000) - - (mOriginalExpiryDate.getTimeInMillis() / 86400000); - if (numDays == 0) { - setExpiryDate(mOriginalExpiryDate); - } else { - setExpiryDate(date); - } - } else { - setExpiryDate(date); - } - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - } - }; - - public KeyEditor(Context context) { - super(context); - } - - public KeyEditor(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - setDrawingCacheEnabled(true); - setAlwaysDrawnWithCacheEnabled(true); - - mAlgorithm = (TextView) findViewById(R.id.algorithm); - mKeyId = (TextView) findViewById(R.id.subkey_item_key_id); - mCreationDate = (TextView) findViewById(R.id.creation); - mExpiryDateButton = (Button) findViewById(R.id.expiry); - - mDeleteButton = (ImageButton) findViewById(R.id.delete); - mDeleteButton.setOnClickListener(this); - mChkCertify = (CheckBox) findViewById(R.id.chkCertify); - mChkCertify.setOnCheckedChangeListener(mCheckChanged); - mChkSign = (CheckBox) findViewById(R.id.chkSign); - mChkSign.setOnCheckedChangeListener(mCheckChanged); - mChkEncrypt = (CheckBox) findViewById(R.id.chkEncrypt); - mChkEncrypt.setOnCheckedChangeListener(mCheckChanged); - mChkAuthenticate = (CheckBox) findViewById(R.id.chkAuthenticate); - mChkAuthenticate.setOnCheckedChangeListener(mCheckChanged); - - setExpiryDate(null); - - mExpiryDateButton.setOnClickListener(new OnClickListener() { - @TargetApi(11) - public void onClick(View v) { - Calendar expiryDate = mExpiryDate; - if (expiryDate == null) { - expiryDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - } - /* - * Using custom DatePickerDialog which overrides the setTitle because - * the DatePickerDialog title is buggy (unix warparound bug). - * See: https://code.google.com/p/android/issues/detail?id=49066 - */ - DatePickerDialog dialog = new ExpiryDatePickerDialog(getContext(), - mExpiryDateSetListener, expiryDate.get(Calendar.YEAR), expiryDate.get(Calendar.MONTH), - expiryDate.get(Calendar.DAY_OF_MONTH)); - mDatePickerResultCount = 0; - dialog.setCancelable(true); - dialog.setButton(Dialog.BUTTON_NEGATIVE, - getContext().getString(R.string.btn_no_date), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - setExpiryDate(null); - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - } - }); - - // setCalendarViewShown() is supported from API 11 onwards. - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // Hide calendarView in tablets because of the unix warparound bug. - dialog.getDatePicker().setCalendarViewShown(false); - } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - - // will crash with IllegalArgumentException if we set a min date - // that is not before expiry - if (mCreatedDate != null && mCreatedDate.before(expiryDate)) { - dialog.getDatePicker() - .setMinDate( - mCreatedDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS); - } else { - // When created date isn't available - dialog.getDatePicker().setMinDate(expiryDate.getTime().getTime() + DateUtils.DAY_IN_MILLIS); - } - } - - dialog.show(); - } - }); - - super.onFinishInflate(); - } - - public void setCanBeEdited(boolean canBeEdited) { - if (!canBeEdited) { - mDeleteButton.setVisibility(View.INVISIBLE); - mExpiryDateButton.setEnabled(false); - mChkSign.setEnabled(false); //certify is always disabled - mChkEncrypt.setEnabled(false); - mChkAuthenticate.setEnabled(false); - } - } - - public void setValue(UncachedSecretKey key, boolean isMasterKey, int usage, boolean isNewKey) { - mKey = key; - - mIsMasterKey = isMasterKey; - if (mIsMasterKey) { - mDeleteButton.setVisibility(View.INVISIBLE); - } - - mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(getContext(), key.getAlgorithm())); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(key.getKeyId()); - mKeyId.setText(keyIdStr); - - boolean isElGamalKey = (key.isElGamalEncrypt()); - boolean isDSAKey = (key.isDSA()); - if (isElGamalKey) { - mChkSign.setVisibility(View.INVISIBLE); - TableLayout table = (TableLayout) findViewById(R.id.table_keylayout); - TableRow row = (TableRow) findViewById(R.id.row_sign); - table.removeView(row); - } - if (isDSAKey) { - mChkEncrypt.setVisibility(View.INVISIBLE); - TableLayout table = (TableLayout) findViewById(R.id.table_keylayout); - TableRow row = (TableRow) findViewById(R.id.row_encrypt); - table.removeView(row); - } - if (!mIsMasterKey) { - mChkCertify.setVisibility(View.INVISIBLE); - TableLayout table = (TableLayout) findViewById(R.id.table_keylayout); - TableRow row = (TableRow) findViewById(R.id.row_certify); - table.removeView(row); - } else { - TextView mLabelUsage2 = (TextView) findViewById(R.id.label_usage2); - mLabelUsage2.setVisibility(View.INVISIBLE); - } - - mIsNewKey = isNewKey; - if (isNewKey) { - mUsage = usage; - mChkCertify.setChecked( - (usage & UncachedSecretKey.CERTIFY_OTHER) == UncachedSecretKey.CERTIFY_OTHER); - mChkSign.setChecked( - (usage & UncachedSecretKey.SIGN_DATA) == UncachedSecretKey.SIGN_DATA); - mChkEncrypt.setChecked( - ((usage & UncachedSecretKey.ENCRYPT_COMMS) == UncachedSecretKey.ENCRYPT_COMMS) || - ((usage & UncachedSecretKey.ENCRYPT_STORAGE) == UncachedSecretKey.ENCRYPT_STORAGE)); - mChkAuthenticate.setChecked( - (usage & UncachedSecretKey.AUTHENTICATION) == UncachedSecretKey.AUTHENTICATION); - } else { - mUsage = key.getKeyUsage(); - mOriginalUsage = mUsage; - if (key.isMasterKey()) { - mChkCertify.setChecked(key.canCertify()); - } - mChkSign.setChecked(key.canSign()); - mChkEncrypt.setChecked(key.canEncrypt()); - mChkAuthenticate.setChecked(key.canAuthenticate()); - } - - { - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - cal.setTime(key.getCreationTime()); - setCreatedDate(cal); - } - - Date expiryDate = key.getExpiryTime(); - if (expiryDate == null) { - setExpiryDate(null); - } else { - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - cal.setTime(expiryDate); - setExpiryDate(cal); - mOriginalExpiryDate = cal; - } - - } - - public UncachedSecretKey getValue() { - return mKey; - } - - public void onClick(View v) { - final ViewGroup parent = (ViewGroup) getParent(); - if (v == mDeleteButton) { - parent.removeView(this); - if (mEditorListener != null) { - mEditorListener.onDeleted(this, mIsNewKey); - } - } - } - - public void setEditorListener(EditorListener listener) { - mEditorListener = listener; - } - - private void setCreatedDate(Calendar date) { - mCreatedDate = date; - if (date == null) { - mCreationDate.setText(getContext().getString(R.string.none)); - } else { - mCreationDate.setText(DateFormat.getDateInstance().format(date.getTime())); - } - } - - private void setExpiryDate(Calendar date) { - mExpiryDate = date; - if (date == null) { - mExpiryDateButton.setText(getContext().getString(R.string.none)); - } else { - mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime())); - } - } - - public Calendar getExpiryDate() { - return mExpiryDate; - } - - public int getUsage() { - mUsage = (mUsage & ~UncachedSecretKey.CERTIFY_OTHER) | - (mChkCertify.isChecked() ? UncachedSecretKey.CERTIFY_OTHER : 0); - mUsage = (mUsage & ~UncachedSecretKey.SIGN_DATA) | - (mChkSign.isChecked() ? UncachedSecretKey.SIGN_DATA : 0); - mUsage = (mUsage & ~UncachedSecretKey.ENCRYPT_COMMS) | - (mChkEncrypt.isChecked() ? UncachedSecretKey.ENCRYPT_COMMS : 0); - mUsage = (mUsage & ~UncachedSecretKey.ENCRYPT_STORAGE) | - (mChkEncrypt.isChecked() ? UncachedSecretKey.ENCRYPT_STORAGE : 0); - mUsage = (mUsage & ~UncachedSecretKey.AUTHENTICATION) | - (mChkAuthenticate.isChecked() ? UncachedSecretKey.AUTHENTICATION : 0); - - return mUsage; - } - - public boolean needsSaving() { - if (mIsNewKey) { - return true; - } - - boolean retval = (getUsage() != mOriginalUsage); - - boolean dateChanged; - boolean mOEDNull = (mOriginalExpiryDate == null); - boolean mEDNull = (mExpiryDate == null); - if (mOEDNull != mEDNull) { - dateChanged = true; - } else { - if (mOEDNull) { - //both null, no change - dateChanged = false; - } else { - dateChanged = ((mExpiryDate.compareTo(mOriginalExpiryDate)) != 0); - } - } - retval |= dateChanged; - - return retval; - } - - public boolean getIsNewKey() { - return mIsNewKey; - } -} - -class ExpiryDatePickerDialog extends DatePickerDialog { - - public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack, - int year, int monthOfYear, int dayOfMonth) { - super(context, callBack, year, monthOfYear, dayOfMonth); - } - - //Set permanent title. - public void setTitle(CharSequence title) { - super.setTitle(getContext().getString(R.string.expiry_date_dialog_title)); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java deleted file mode 100644 index 190db1fe3..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * 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.widget; - -import android.content.Context; -import android.support.v7.app.ActionBarActivity; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.ImageButton; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; -import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; -import org.sufficientlysecure.keychain.util.Choice; - -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Editor { - private LayoutInflater mInflater; - private ImageButton mPlusButton; - private ViewGroup mEditors; - private TextView mTitle; - private int mType = 0; - private EditorListener mEditorListener = null; - - private Choice mNewKeyAlgorithmChoice; - private int mNewKeySize; - private boolean mOldItemDeleted = false; - private ArrayList mDeletedIDs = new ArrayList(); - private ArrayList mDeletedKeys = new ArrayList(); - private boolean mCanBeEdited = true; - - private ActionBarActivity mActivity; - - private ProgressDialogFragment mGeneratingDialog; - - public static final int TYPE_USER_ID = 1; - public static final int TYPE_KEY = 2; - - public void setEditorListener(EditorListener listener) { - mEditorListener = listener; - } - - public SectionView(Context context) { - super(context); - mActivity = (ActionBarActivity) context; - } - - public SectionView(Context context, AttributeSet attrs) { - super(context, attrs); - mActivity = (ActionBarActivity) context; - } - - public ViewGroup getEditors() { - return mEditors; - } - - public void setType(int type) { - mType = type; - switch (type) { - case TYPE_USER_ID: { - mTitle.setText(R.string.section_user_ids); - break; - } - - case TYPE_KEY: { - mTitle.setText(R.string.section_keys); - break; - } - - default: { - break; - } - } - } - - public void setCanBeEdited(boolean canBeEdited) { - mCanBeEdited = canBeEdited; - if (!mCanBeEdited) { - mPlusButton.setVisibility(View.INVISIBLE); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void onFinishInflate() { - mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - setDrawingCacheEnabled(true); - setAlwaysDrawnWithCacheEnabled(true); - - mPlusButton = (ImageButton) findViewById(R.id.plusbutton); - mPlusButton.setOnClickListener(this); - - mEditors = (ViewGroup) findViewById(R.id.editors); - mTitle = (TextView) findViewById(R.id.title); - - updateEditorsVisible(); - super.onFinishInflate(); - } - - /** - * {@inheritDoc} - */ - public void onDeleted(Editor editor, boolean wasNewItem) { - mOldItemDeleted |= !wasNewItem; - if (mOldItemDeleted) { - if (mType == TYPE_USER_ID) { - mDeletedIDs.add(((UserIdEditor) editor).getOriginalID()); - } else if (mType == TYPE_KEY) { - mDeletedKeys.add(((KeyEditor) editor).getValue()); - } - } - this.updateEditorsVisible(); - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - - @Override - public void onEdited() { - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - - protected void updateEditorsVisible() { - final boolean hasChildren = mEditors.getChildCount() > 0; - mEditors.setVisibility(hasChildren ? View.VISIBLE : View.GONE); - } - - public boolean needsSaving() { - //check each view for needs saving, take account of deleted items - boolean ret = mOldItemDeleted; - for (int i = 0; i < mEditors.getChildCount(); ++i) { - Editor editor = (Editor) mEditors.getChildAt(i); - ret |= editor.needsSaving(); - if (mType == TYPE_USER_ID) { - ret |= ((UserIdEditor) editor).primarySwapped(); - } - } - return ret; - } - - public boolean primaryChanged() { - boolean ret = false; - for (int i = 0; i < mEditors.getChildCount(); ++i) { - Editor editor = (Editor) mEditors.getChildAt(i); - if (mType == TYPE_USER_ID) { - ret |= ((UserIdEditor) editor).primarySwapped(); - } - } - return ret; - } - - public String getOriginalPrimaryID() { - //NB: this will have to change when we change how Primary IDs are chosen, and so we need to be - // careful about where Master key capabilities are stored... multiple primaries and - // revoked ones make this harder than the simple case we are continuing to assume here - for (int i = 0; i < mEditors.getChildCount(); ++i) { - Editor editor = (Editor) mEditors.getChildAt(i); - if (mType == TYPE_USER_ID) { - if (((UserIdEditor) editor).getIsOriginallyMainUserID()) { - return ((UserIdEditor) editor).getOriginalID(); - } - } - } - return null; - } - - public ArrayList getOriginalIDs() { - ArrayList orig = new ArrayList(); - if (mType == TYPE_USER_ID) { - for (int i = 0; i < mEditors.getChildCount(); ++i) { - UserIdEditor editor = (UserIdEditor) mEditors.getChildAt(i); - if (editor.isMainUserId()) { - orig.add(0, editor.getOriginalID()); - } else { - orig.add(editor.getOriginalID()); - } - } - return orig; - } else { - return null; - } - } - - public ArrayList getDeletedIDs() { - return mDeletedIDs; - } - - public ArrayList getDeletedKeys() { - return mDeletedKeys; - } - - public List getNeedsSavingArray() { - ArrayList mList = new ArrayList(); - for (int i = 0; i < mEditors.getChildCount(); ++i) { - Editor editor = (Editor) mEditors.getChildAt(i); - mList.add(editor.needsSaving()); - } - return mList; - } - - public List getNewIDFlags() { - ArrayList mList = new ArrayList(); - for (int i = 0; i < mEditors.getChildCount(); ++i) { - UserIdEditor editor = (UserIdEditor) mEditors.getChildAt(i); - if (editor.isMainUserId()) { - mList.add(0, editor.getIsNewID()); - } else { - mList.add(editor.getIsNewID()); - } - } - return mList; - } - - public List getNewKeysArray() { - ArrayList mList = new ArrayList(); - if (mType == TYPE_KEY) { - for (int i = 0; i < mEditors.getChildCount(); ++i) { - KeyEditor editor = (KeyEditor) mEditors.getChildAt(i); - mList.add(editor.getIsNewKey()); - } - } - return mList; - } - - /** - * {@inheritDoc} - */ - public void onClick(View v) { - if (mCanBeEdited) { - switch (mType) { - case TYPE_USER_ID: { - UserIdEditor view = (UserIdEditor) mInflater.inflate( - R.layout.edit_key_user_id_item, mEditors, false); - view.setEditorListener(this); - view.setValue("", mEditors.getChildCount() == 0, true); - mEditors.addView(view); - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - break; - } - - case TYPE_KEY: { -// AddSubkeyDialogFragment mCreateKeyDialogFragment = -// AddSubkeyDialogFragment.newInstance(mEditors.getChildCount()); -// mCreateKeyDialogFragment -// .setOnAlgorithmSelectedListener( -// new AddSubkeyDialogFragment.OnAlgorithmSelectedListener() { -// @Override -// public void onAlgorithmSelected(Choice algorithmChoice, int keySize) { -// mNewKeyAlgorithmChoice = algorithmChoice; -// mNewKeySize = keySize; -// createKey(); -// } -// }); -// mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog"); - break; - } - - default: { - break; - } - } - this.updateEditorsVisible(); - } - } - - public void setUserIds(Vector list) { - if (mType != TYPE_USER_ID) { - return; - } - - mEditors.removeAllViews(); - for (String userId : list) { - UserIdEditor view = (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item, - mEditors, false); - view.setEditorListener(this); - view.setValue(userId, mEditors.getChildCount() == 0, false); - view.setCanBeEdited(mCanBeEdited); - mEditors.addView(view); - } - - this.updateEditorsVisible(); - } - - public void setKeys(Vector list, Vector usages, boolean newKeys) { - if (mType != TYPE_KEY) { - return; - } - - mEditors.removeAllViews(); - - // go through all keys and set view based on them - for (int i = 0; i < list.size(); i++) { - KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, - false); - view.setEditorListener(this); - boolean isMasterKey = (mEditors.getChildCount() == 0); - view.setValue(list.get(i), isMasterKey, usages.get(i), newKeys); - view.setCanBeEdited(mCanBeEdited); - mEditors.addView(view); - } - - this.updateEditorsVisible(); - } - - private void createKey() { - - // fill values for this action - Boolean isMasterKey; - - String passphrase; - if (mEditors.getChildCount() > 0) { - UncachedSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); - passphrase = PassphraseCacheService - .getCachedPassphrase(mActivity, masterKey.getKeyId()); - isMasterKey = false; - } else { - passphrase = ""; - isMasterKey = true; - } - /* - data.putBoolean(KeychainIntentService.GENERATE_KEY_MASTER_KEY, isMasterKey); - data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passphrase); - data.putInt(KeychainIntentService.GENERATE_KEY_ALGORITHM, mNewKeyAlgorithmChoice.getId()); - data.putInt(KeychainIntentService.GENERATE_KEY_KEY_SIZE, mNewKeySize); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // show progress dialog - mGeneratingDialog = ProgressDialogFragment.newInstance( - getResources().getQuantityString(R.plurals.progress_generating, 1), - ProgressDialog.STYLE_SPINNER, - true, - new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - mActivity.stopService(intent); - } - }); - - // Message is received after generating is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity, - mGeneratingDialog) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get new key from data bundle returned from service - Bundle data = message.getDataAsStringList(); - UncachedSecretKey newKey = PgpConversionHelper - .BytesToPGPSecretKey(data - .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); - addGeneratedKeyToView(newKey); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - mGeneratingDialog.show(mActivity.getSupportFragmentManager(), "dialog"); - - // start service with intent - mActivity.startService(intent); - */ - - } - - private void addGeneratedKeyToView(UncachedSecretKey newKey) { - // add view with new key - KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, - mEditors, false); - view.setEditorListener(SectionView.this); - int usage = 0; - if (mEditors.getChildCount() == 0) { - usage = UncachedSecretKey.CERTIFY_OTHER; - } - view.setValue(newKey, newKey.isMasterKey(), usage, true); - mEditors.addView(view); - SectionView.this.updateEditorsVisible(); - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java deleted file mode 100644 index f50d2adc6..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 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.widget; - -import android.content.Context; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.util.Patterns; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.RadioButton; -import android.widget.ImageButton; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; -import org.sufficientlysecure.keychain.pgp.KeyRing; - -import java.util.regex.Matcher; - -public class UserIdEditor extends LinearLayout implements Editor, OnClickListener { - private EditorListener mEditorListener = null; - - private ImageButton mDeleteButton; - private RadioButton mIsMainUserId; - private String mOriginalID; - private EditText mName; - private String mOriginalName; - private AutoCompleteTextView mEmail; - private String mOriginalEmail; - private EditText mComment; - private String mOriginalComment; - private boolean mOriginallyMainUserID; - private boolean mIsNewId; - - public void setCanBeEdited(boolean canBeEdited) { - if (!canBeEdited) { - mDeleteButton.setVisibility(View.INVISIBLE); - mName.setEnabled(false); - mIsMainUserId.setEnabled(false); - mEmail.setEnabled(false); - mComment.setEnabled(false); - } - } - - public static class InvalidEmailException extends Exception { - static final long serialVersionUID = 0xf812773345L; - - public InvalidEmailException(String message) { - super(message); - } - } - - public UserIdEditor(Context context) { - super(context); - } - - public UserIdEditor(Context context, AttributeSet attrs) { - super(context, attrs); - } - - TextWatcher mTextWatcher = new TextWatcher() { - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void afterTextChanged(Editable s) { - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - }; - - @Override - protected void onFinishInflate() { - setDrawingCacheEnabled(true); - setAlwaysDrawnWithCacheEnabled(true); - - mDeleteButton = (ImageButton) findViewById(R.id.delete); - mDeleteButton.setOnClickListener(this); - mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId); - mIsMainUserId.setOnClickListener(this); - - mName = (EditText) findViewById(R.id.name); - mName.addTextChangedListener(mTextWatcher); - mEmail = (AutoCompleteTextView) findViewById(R.id.email); - mComment = (EditText) findViewById(R.id.user_id_item_comment); - mComment.addTextChangedListener(mTextWatcher); - - - mEmail.setThreshold(1); // Start working from first character - mEmail.setAdapter( - new ArrayAdapter - (this.getContext(), android.R.layout.simple_dropdown_item_1line, - ContactHelper.getPossibleUserEmails(getContext()) - )); - mEmail.addTextChangedListener(new TextWatcher(){ - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void afterTextChanged(Editable editable) { - String email = editable.toString(); - if (email.length() > 0) { - Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); - if (emailMatcher.matches()) { - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_ok, 0); - } else { - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_bad, 0); - } - } else { - // remove drawable if email is empty - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - }); - - super.onFinishInflate(); - } - - public void setValue(String userId, boolean isMainID, boolean isNewId) { - - mName.setText(""); - mOriginalName = ""; - mComment.setText(""); - mOriginalComment = ""; - mEmail.setText(""); - mOriginalEmail = ""; - mIsNewId = isNewId; - mOriginalID = userId; - - String[] result = KeyRing.splitUserId(userId); - if (result[0] != null) { - mName.setText(result[0]); - mOriginalName = result[0]; - } - if (result[1] != null) { - mEmail.setText(result[1]); - mOriginalEmail = result[1]; - } - if (result[2] != null) { - mComment.setText(result[2]); - mOriginalComment = result[2]; - } - - mOriginallyMainUserID = isMainID; - setIsMainUserId(isMainID); - } - - public String getValue() { - String name = ("" + mName.getText()).trim(); - String email = ("" + mEmail.getText()).trim(); - String comment = ("" + mComment.getText()).trim(); - - String userId = name; - if (comment.length() > 0) { - userId += " (" + comment + ")"; - } - if (email.length() > 0) { - userId += " <" + email + ">"; - } - - if (userId.equals("")) { - // ok, empty one... - return userId; - } - //TODO: check gpg accepts an entirely empty ID packet. specs say this is allowed - return userId; - } - - public void onClick(View v) { - final ViewGroup parent = (ViewGroup) getParent(); - if (v == mDeleteButton) { - boolean wasMainUserId = mIsMainUserId.isChecked(); - parent.removeView(this); - if (mEditorListener != null) { - mEditorListener.onDeleted(this, mIsNewId); - } - if (wasMainUserId && parent.getChildCount() > 0) { - UserIdEditor editor = (UserIdEditor) parent.getChildAt(0); - editor.setIsMainUserId(true); - } - } else if (v == mIsMainUserId) { - for (int i = 0; i < parent.getChildCount(); ++i) { - UserIdEditor editor = (UserIdEditor) parent.getChildAt(i); - if (editor == this) { - editor.setIsMainUserId(true); - } else { - editor.setIsMainUserId(false); - } - } - if (mEditorListener != null) { - mEditorListener.onEdited(); - } - } - } - - public void setIsMainUserId(boolean value) { - mIsMainUserId.setChecked(value); - } - - public boolean isMainUserId() { - return mIsMainUserId.isChecked(); - } - - public void setEditorListener(EditorListener listener) { - mEditorListener = listener; - } - - @Override - public boolean needsSaving() { - boolean retval = false; //(mOriginallyMainUserID != isMainUserId()); - retval |= !(mOriginalName.equals(("" + mName.getText()).trim())); - retval |= !(mOriginalEmail.equals(("" + mEmail.getText()).trim())); - retval |= !(mOriginalComment.equals(("" + mComment.getText()).trim())); - retval |= mIsNewId; - return retval; - } - - public boolean getIsOriginallyMainUserID() { - return mOriginallyMainUserID; - } - - public boolean primarySwapped() { - return (mOriginallyMainUserID != isMainUserId()); - } - - public String getOriginalID() { - return mOriginalID; - } - - public boolean getIsNewID() { return mIsNewId; } -} -- cgit v1.2.3 From b42afcd32cc082d45daf64e37d89ba88f0c3eb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 11:19:46 +0200 Subject: Fix debug backup/restore methods --- .../keychain/provider/KeychainDatabase.java | 39 ++++++++++------------ .../keychain/ui/KeyListActivity.java | 12 +++---- 2 files changed, 23 insertions(+), 28 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 7a63ec3d7..ebc53ddf6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -316,42 +316,37 @@ public class KeychainDatabase extends SQLiteOpenHelper { } private static void copy(File in, File out) throws IOException { - FileInputStream ss = new FileInputStream(in); - FileOutputStream ds = new FileOutputStream(out); + FileInputStream is = new FileInputStream(in); + FileOutputStream os = new FileOutputStream(out); byte[] buf = new byte[512]; - while (ss.available() > 0) { - int count = ss.read(buf, 0, 512); - ds.write(buf, 0, count); + while (is.available() > 0) { + int count = is.read(buf, 0, 512); + os.write(buf, 0, count); } } - public static void debugRead(Context context) throws IOException { + public static void debugBackup(Context context, boolean restore) throws IOException { if (!Constants.DEBUG) { return; } - File in = context.getDatabasePath("debug.db"); - File out = context.getDatabasePath("openkeychain.db"); - if (!in.canRead()) { - throw new IOException("Cannot read " + in.getName()); - } - if (!out.canRead()) { - throw new IOException("Cannot write " + out.getName()); - } - copy(in, out); - } - public static void debugWrite(Context context) throws IOException { - if (!Constants.DEBUG) { - return; + File in; + File out; + if (restore) { + in = context.getDatabasePath("debug_backup.db"); + out = context.getDatabasePath("openkeychain.db"); + } else { + in = context.getDatabasePath("openkeychain.db"); + out = context.getDatabasePath("debug_backup.db"); + out.createNewFile(); } - File in = context.getDatabasePath("openkeychain.db"); - File out = context.getDatabasePath("debug.db"); if (!in.canRead()) { throw new IOException("Cannot read " + in.getName()); } - if (!out.canRead()) { + if (!out.canWrite()) { throw new IOException("Cannot write " + out.getName()); } copy(in, out); } + } 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 50ff5c753..7a6e78a7d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -94,22 +94,22 @@ public class KeyListActivity extends DrawerActivity { case R.id.menu_key_list_debug_read: try { - KeychainDatabase.debugRead(this); - Notify.showNotify(this, "Restored Notify.Style backup", Notify.Style.INFO); + KeychainDatabase.debugBackup(this, true); + Notify.showNotify(this, "Restored debug_backup.db", Notify.Style.INFO); getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null); } catch (IOException e) { Log.e(Constants.TAG, "IO Error", e); - Notify.showNotify(this, "IO Notify.Style: " + e.getMessage(), Notify.Style.ERROR); + Notify.showNotify(this, "IO Error " + e.getMessage(), Notify.Style.ERROR); } return true; case R.id.menu_key_list_debug_write: try { - KeychainDatabase.debugWrite(this); - Notify.showNotify(this, "Backup Notify.Style", Notify.Style.INFO); + KeychainDatabase.debugBackup(this, false); + Notify.showNotify(this, "Backup to debug_backup.db completed", Notify.Style.INFO); } catch(IOException e) { Log.e(Constants.TAG, "IO Error", e); - Notify.showNotify(this, "IO Notify.Style: " + e.getMessage(), Notify.Style.ERROR); + Notify.showNotify(this, "IO Error: " + e.getMessage(), Notify.Style.ERROR); } return true; -- cgit v1.2.3 From 839294d27c4f8b3ac22573a1d429bc230f641bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 14:42:03 +0200 Subject: Cleanup, prevent encrypt Intent inception --- .../org/sufficientlysecure/keychain/Constants.java | 2 - .../keychain/helper/FileHelper.java | 21 +++--- .../keychain/provider/KeychainDatabase.java | 8 +-- .../keychain/ui/DecryptFileFragment.java | 5 +- .../keychain/ui/EncryptActivity.java | 76 +++++++++++++++++++++- .../keychain/ui/EncryptFileFragment.java | 8 +-- .../ui/dialog/DeleteFileDialogFragment.java | 3 +- 7 files changed, 98 insertions(+), 25 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index b679ef210..6423697cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -51,8 +51,6 @@ public final class Constants { public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key"; - public static boolean KITKAT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - public static int TEMPFILE_TTL = 24*60*60*1000; // 1 day public static final class Path { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index 615d89e0c..ca0749a4e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -32,6 +32,7 @@ import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.widget.Toast; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; @@ -136,9 +137,10 @@ public class FileHelper { /** * 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 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) @@ -153,10 +155,11 @@ public class FileHelper { /** * 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 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 + * @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) { @@ -210,7 +213,7 @@ public class FileHelper { * Retrieve thumbnail of file, document api feature and thus KitKat only */ public static Bitmap getThumbnail(Context context, Uri uri, Point size) { - if (Constants.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return DocumentsContract.getDocumentThumbnail(context.getContentResolver(), uri, size, null); } else { return null; @@ -218,10 +221,10 @@ public class FileHelper { } 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]; + 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 { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index ebc53ddf6..3a859f505 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -165,8 +165,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { // make sure this is only done once, on the first instance! boolean iAmIt = false; - synchronized(KeychainDatabase.class) { - if(!KeychainDatabase.apgHack) { + synchronized (KeychainDatabase.class) { + if (!KeychainDatabase.apgHack) { iAmIt = true; KeychainDatabase.apgHack = true; } @@ -334,9 +334,9 @@ public class KeychainDatabase extends SQLiteOpenHelper { File out; if (restore) { in = context.getDatabasePath("debug_backup.db"); - out = context.getDatabasePath("openkeychain.db"); + out = context.getDatabasePath(DATABASE_NAME); } else { - in = context.getDatabasePath("openkeychain.db"); + in = context.getDatabasePath(DATABASE_NAME); out = context.getDatabasePath("debug_backup.db"); out.createNewFile(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 5b61c3f52..51e90ea20 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.Messenger; @@ -72,7 +73,7 @@ public class DecryptFileFragment extends DecryptFragment { mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - if (Constants.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { FileHelper.openDocument(DecryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { FileHelper.openFile(DecryptFileFragment.this, mInputUri, "*/*", @@ -126,7 +127,7 @@ public class DecryptFileFragment extends DecryptFragment { private void askForOutputFilename() { String targetName = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri)); - if (!Constants.KITKAT) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { File file = new File(mInputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; File targetFile = new File(parentDir, targetName); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 211802717..f9dbb2b6b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -20,16 +20,20 @@ package org.sufficientlysecure.keychain.ui; import android.app.ProgressDialog; import android.content.Intent; +import android.content.pm.LabeledIntent; +import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; +import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -45,7 +49,11 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; +import java.util.List; import java.util.Set; public class EncryptActivity extends DrawerActivity implements EncryptActivityInterface { @@ -228,7 +236,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn if (mShareAfterEncrypt) { // Share encrypted file - startActivity(Intent.createChooser(createSendIntent(message), getString(R.string.title_share_file))); + startActivity(sendCreateChooserExcludingOpenKeychain(message)); } else if (isContentMessage()) { // Copy to clipboard copyToClipboard(message); @@ -289,6 +297,69 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn ClipboardReflection.copyToClipboard(this, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); } + /** + * Create Intent Chooser but exclude OK's EncryptActivity. + *

+ * Put together from some stackoverflow posts... + * + * @param message + * @return + */ + private Intent sendCreateChooserExcludingOpenKeychain(Message message) { + Intent prototype = createSendIntent(message); + + String[] blacklist = new String[]{Constants.PACKAGE_NAME + ".ui.EncryptActivity"}; + + List targetedShareIntents = new ArrayList(); + + List resInfoList = 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(blacklist).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(getPackageManager()).toString(); + String secondName = second.loadLabel(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(getPackageManager()), + resolveInfo.activityInfo.icon); + targetedShareIntents.add(lIntent); + } + + // Create chooser with only one Intent in it + Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), getString(R.string.title_share_file)); + // 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, getString(R.string.title_share_file)); + } + private Intent createSendIntent(Message message) { Intent sendIntent; if (isContentMessage()) { @@ -380,7 +451,8 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn startEncrypt(); } } - }); + } + ); return false; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 6bbbac713..d412df0f4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -27,7 +27,6 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; @@ -39,7 +38,6 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; -import org.sufficientlysecure.keychain.util.Log; import java.io.File; import java.util.HashMap; @@ -117,7 +115,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte } private void addInputUri() { - if (Constants.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", true, REQUEST_CODE_INPUT); } else { FileHelper.openFile(EncryptFileFragment.this, mEncryptInterface.getInputUris().isEmpty() ? @@ -174,7 +172,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte throw new IllegalStateException(); } Uri inputUri = mEncryptInterface.getInputUris().get(0); - if (!Constants.KITKAT) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; String targetName = FileHelper.getFilename(getActivity(), inputUri) + @@ -219,7 +217,7 @@ public class EncryptFileFragment extends Fragment implements EncryptActivityInte switch (requestCode) { case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - if (!Constants.KITKAT || !handleClipData(data)) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || !handleClipData(data)) { addInputUri(data.getData()); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index 5e296c062..d408349d2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Dialog; import android.content.DialogInterface; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.DocumentsContract; import android.support.v4.app.DialogFragment; @@ -71,7 +72,7 @@ public class DeleteFileDialogFragment extends DialogFragment { dismiss(); // We can not securely delete Uris, so just use usual delete on them - if (Constants.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) { Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); return; -- cgit v1.2.3 From c4311e2f52e5870ccfd67d34fa7c364ecd160753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 14:44:11 +0200 Subject: Remove support for IO_FILE, this is no longer used and was never a good practice, use IO_URI on Android! --- .../keychain/service/KeychainIntentService.java | 31 ++-------------------- 1 file changed, 2 insertions(+), 29 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 b45359a10..601f45fed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -110,9 +110,8 @@ public class KeychainIntentService extends IntentService public static final String SOURCE = "source"; // possible targets: public static final int IO_BYTES = 1; - public static final int IO_FILE = 2; // This was misleadingly TARGET_URI before! - public static final int IO_URI = 3; - public static final int IO_URIS = 4; + public static final int IO_URI = 2; + public static final int IO_URIS = 3; public static final String SELECTED_URI = "selected_uri"; @@ -716,16 +715,6 @@ public class KeychainIntentService extends IntentService byte[] bytes = data.getByteArray(bytesName); return new InputData(new ByteArrayInputStream(bytes), bytes.length); - case IO_FILE: /* encrypting file */ - String inputFile = data.getString(ENCRYPT_INPUT_FILE); - - // check if storage is ready - if (!FileHelper.isStorageMounted(inputFile)) { - throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready)); - } - - return new InputData(new FileInputStream(inputFile), new File(inputFile).length()); - case IO_URI: /* encrypting content uri */ Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); @@ -749,18 +738,6 @@ public class KeychainIntentService extends IntentService case IO_BYTES: return new ByteArrayOutputStream(); - case IO_FILE: - String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); - - // check if storage is ready - if (!FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException( - getString(R.string.error_external_storage_not_ready)); - } - - // OutputStream - return new FileOutputStream(outputFile); - case IO_URI: Uri providerUri = data.getParcelable(ENCRYPT_OUTPUT_URI); @@ -790,10 +767,6 @@ public class KeychainIntentService extends IntentService case IO_BYTES: byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); resultData.putByteArray(bytesName, output); - break; - case IO_FILE: - // nothing, file was written, just send okay and verification bundle - break; case IO_URI: case IO_URIS: -- cgit v1.2.3 From e87c69647c06740146dcbdb9ee350aeacc178a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 15:40:34 +0200 Subject: Even more smaller nitpicks --- .../keychain/ui/EncryptActivity.java | 35 ++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index f9dbb2b6b..0007d179a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.pm.LabeledIntent; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -223,20 +224,22 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Notify.showNotify(EncryptActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO); + if (!isContentMessage()) { + Notify.showNotify(EncryptActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO); - if (!isContentMessage() && mDeleteAfterEncrypt) { - for (Uri inputUri : mInputUris) { - DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUri); - deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); + if (mDeleteAfterEncrypt) { + for (Uri inputUri : mInputUris) { + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUri); + deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); + } + mInputUris.clear(); + notifyUpdate(); } - mInputUris.clear(); - notifyUpdate(); } if (mShareAfterEncrypt) { - // Share encrypted file - startActivity(sendCreateChooserExcludingOpenKeychain(message)); + // Share encrypted message/file + startActivity(sendWithChooserExcludingOpenKeychain(message)); } else if (isContentMessage()) { // Copy to clipboard copyToClipboard(message); @@ -305,9 +308,17 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn * @param message * @return */ - private Intent sendCreateChooserExcludingOpenKeychain(Message message) { + private Intent sendWithChooserExcludingOpenKeychain(Message message) { Intent prototype = createSendIntent(message); + String title = isContentMessage() ? getString(R.string.title_share_message) + : getString(R.string.title_share_file); + + // somehow this returns lists with only one entry on Android 2.3 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return Intent.createChooser(prototype, title); + } + String[] blacklist = new String[]{Constants.PACKAGE_NAME + ".ui.EncryptActivity"}; List targetedShareIntents = new ArrayList(); @@ -348,7 +359,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } // Create chooser with only one Intent in it - Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), getString(R.string.title_share_file)); + 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; @@ -357,7 +368,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } // fallback to Android's default chooser - return Intent.createChooser(prototype, getString(R.string.title_share_file)); + return Intent.createChooser(prototype, title); } private Intent createSendIntent(Message message) { -- cgit v1.2.3 From 3a6ac2a16aef9a066bf196df04c40d03f348d147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 15:49:49 +0200 Subject: More cleanup --- .../java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 0007d179a..94f828b48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -239,7 +239,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn if (mShareAfterEncrypt) { // Share encrypted message/file - startActivity(sendWithChooserExcludingOpenKeychain(message)); + startActivity(sendWithChooserExcludingEncrypt(message)); } else if (isContentMessage()) { // Copy to clipboard copyToClipboard(message); @@ -308,17 +308,18 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn * @param message * @return */ - private Intent sendWithChooserExcludingOpenKeychain(Message message) { + private Intent sendWithChooserExcludingEncrypt(Message message) { Intent prototype = createSendIntent(message); String title = isContentMessage() ? getString(R.string.title_share_message) : getString(R.string.title_share_file); - // somehow this returns lists with only one entry on Android 2.3 + // fallback on Android 2.3, otherwise we would get weird results if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { return Intent.createChooser(prototype, title); } + // prevent recursion aka Inception :P String[] blacklist = new String[]{Constants.PACKAGE_NAME + ".ui.EncryptActivity"}; List targetedShareIntents = new ArrayList(); -- cgit v1.2.3 From a2c122139702f2d792ede06c0011bc7531e40790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 16:29:16 +0200 Subject: Fixing lint complaints, removing unused resources --- .../org/sufficientlysecure/keychain/helper/EmailKeyHelper.java | 3 ++- .../sufficientlysecure/keychain/keyimport/HkpKeyserver.java | 10 +++++----- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java | 4 ++-- .../keychain/service/PassphraseCacheService.java | 4 ++-- .../org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 2 +- .../keychain/ui/widget/EncryptKeyCompletionView.java | 5 +++-- 6 files changed, 15 insertions(+), 13 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java index 5d281d5b0..7cd4f6710 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java @@ -29,6 +29,7 @@ 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 { @@ -86,7 +87,7 @@ public class EmailKeyHelper { for (ImportKeysListEntry key : keyServer.search(mail)) { if (key.isRevoked() || key.isExpired()) continue; for (String userId : key.getUserIds()) { - if (userId.toLowerCase().contains(mail.toLowerCase())) { + if (userId.toLowerCase().contains(mail.toLowerCase(Locale.ENGLISH))) { keys.add(key); } } 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 41f1e6997..eb741fc45 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -251,14 +251,14 @@ public class HkpKeyserver extends Keyserver { data = query(request); } catch (HttpError e) { if (e.getData() != null) { - Log.d(Constants.TAG, "returned error data: " + e.getData().toLowerCase(Locale.US)); + Log.d(Constants.TAG, "returned error data: " + e.getData().toLowerCase(Locale.ENGLISH)); - if (e.getData().toLowerCase(Locale.US).contains("no keys found")) { + if (e.getData().toLowerCase(Locale.ENGLISH).contains("no keys found")) { // NOTE: This is also a 404 error for some keyservers! return results; - } else if (e.getData().toLowerCase(Locale.US).contains("too many")) { + } else if (e.getData().toLowerCase(Locale.ENGLISH).contains("too many")) { throw new TooManyResponsesException(); - } else if (e.getData().toLowerCase(Locale.US).contains("insufficient")) { + } else if (e.getData().toLowerCase(Locale.ENGLISH).contains("insufficient")) { throw new QueryTooShortException(); } else if (e.getCode() == 404) { // NOTE: handle this 404 at last, maybe it was a "no keys found" error @@ -285,7 +285,7 @@ public class HkpKeyserver extends Keyserver { // group 1 contains the full fingerprint (v4) or the long key id if available // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr - String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.US); + String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.ENGLISH); if (fingerprintOrKeyId.length() > 16) { entry.setFingerprintHex(fingerprintOrKeyId); entry.setKeyIdHex("0x" + fingerprintOrKeyId.substring(fingerprintOrKeyId.length() diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index 1ba028006..7e18aa906 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -104,7 +104,7 @@ public class PgpKeyHelper { * @return */ public static String convertFingerprintToHex(byte[] fingerprint) { - String hexString = Hex.toHexString(fingerprint).toLowerCase(Locale.US); + String hexString = Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); return hexString; } @@ -133,7 +133,7 @@ public class PgpKeyHelper { } private static String convertKeyIdToHex32bit(long keyId) { - String hexString = Long.toHexString(keyId & 0xffffffffL).toLowerCase(Locale.US); + String hexString = Long.toHexString(keyId & 0xffffffffL).toLowerCase(Locale.ENGLISH); while (hexString.length() < 8) { hexString = "0" + hexString; } 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 c4ecfdec5..7789ee064 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -388,8 +388,8 @@ public class PassphraseCacheService extends Service { } else { // Fallback, since expandable notifications weren't available back then builder.setSmallIcon(R.drawable.ic_launcher) - .setContentTitle(String.format(getString(R.string.passp_cache_notif_n_keys, - mPassphraseCache.size()))) + .setContentTitle(String.format(getString(R.string.passp_cache_notif_n_keys), + mPassphraseCache.size())) .setContentText(getString(R.string.passp_cache_notif_click_to_clear)); Intent intent = new Intent(getApplicationContext(), PassphraseCacheService.class); 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 ac228c9f6..568772709 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -103,7 +103,7 @@ public class ViewKeyActivity extends ActionBarActivity implements @Override protected void onCreate(Bundle savedInstanceState) { - requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); super.onCreate(savedInstanceState); mExportHelper = new ExportHelper(this); 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 f1c17bfb5..b95dee12c 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 @@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; public class EncryptKeyCompletionView extends TokenCompleteTextView { public EncryptKeyCompletionView(Context context) { @@ -242,8 +243,8 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { @Override protected boolean keepObject(EncryptionKey obj, String mask) { - String m = mask.toLowerCase(); - return obj.getUserId().toLowerCase().contains(m) || + String m = mask.toLowerCase(Locale.ENGLISH); + return obj.getUserId().toLowerCase(Locale.ENGLISH).contains(m) || obj.getKeyIdHex().contains(m) || obj.getKeyIdHexShort().startsWith(m); } -- cgit v1.2.3 From 7eafd77e15d7d9bcbef20df593500ae679545abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 16:37:42 +0200 Subject: Fix nullpointer, remove unused window feature --- .../main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenKeychain/src/main/java') 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 568772709..e179115dc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -103,7 +103,6 @@ public class ViewKeyActivity extends ActionBarActivity implements @Override protected void onCreate(Bundle savedInstanceState) { - supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); super.onCreate(savedInstanceState); mExportHelper = new ExportHelper(this); -- cgit v1.2.3 From ce8d38d9b3eb809c9859bbdee219b76346972ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 Aug 2014 16:46:23 +0200 Subject: Add license headers --- .../keychain/keyimport/ParcelableKeyRing.java | 17 +++++++++++++++++ .../keychain/pgp/CanonicalizedKeyRing.java | 17 +++++++++++++++++ .../keychain/pgp/CanonicalizedPublicKey.java | 17 +++++++++++++++++ .../keychain/pgp/CanonicalizedPublicKeyRing.java | 17 +++++++++++++++++ .../keychain/pgp/CanonicalizedSecretKey.java | 17 +++++++++++++++++ .../keychain/pgp/CanonicalizedSecretKeyRing.java | 17 +++++++++++++++++ .../org/sufficientlysecure/keychain/pgp/KeyRing.java | 17 +++++++++++++++++ .../keychain/pgp/NullProgressable.java | 17 +++++++++++++++++ .../keychain/pgp/UncachedKeyRing.java | 17 +++++++++++++++++ .../keychain/pgp/UncachedPublicKey.java | 17 +++++++++++++++++ .../keychain/pgp/UncachedSecretKey.java | 17 +++++++++++++++++ .../keychain/pgp/WrappedSignature.java | 17 +++++++++++++++++ .../keychain/provider/CachedPublicKeyRing.java | 17 +++++++++++++++++ .../keychain/provider/TemporaryStorageProvider.java | 17 +++++++++++++++++ .../keychain/service/OperationResultParcel.java | 17 +++++++++++++++++ .../keychain/service/OperationResults.java | 17 +++++++++++++++++ .../keychain/service/SaveKeyringParcel.java | 17 +++++++++++++++++ .../keychain/ui/widget/EncryptKeyCompletionView.java | 17 +++++++++++++++++ .../keychain/ui/widget/NoSwipeWrapContentViewPager.java | 17 +++++++++++++++++ 19 files changed, 323 insertions(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java index 066c51a13..8609a7082 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.keyimport; import android.os.Parcel; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java index ee0dfefa4..1da66872d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.openpgp.PGPKeyRing; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java index 981caad49..ce6498df1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.openpgp.PGPPublicKey; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java index 70288dceb..972e45c2e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java index 2eb517697..af058b618 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.openpgp.PGPException; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java index e48fe5020..812bf2fed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.S2K; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java index 7d11a20d3..35020b815 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import android.text.TextUtils; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/NullProgressable.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/NullProgressable.java index 68312dca3..5ef4f7998 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/NullProgressable.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/NullProgressable.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; /** 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 690317170..af82495aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index 4a03d942b..341ca6d04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.sig.KeyFlags; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java index 0e14a7fd3..8dc28c2b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.sig.KeyFlags; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index 07fb4fb9e..ebd110dc5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -1,3 +1,20 @@ +/* + * 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.pgp; import org.spongycastle.bcpg.SignatureSubpacket; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index aa0207a6a..89acbd488 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -1,3 +1,20 @@ +/* + * 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.provider; import android.database.Cursor; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java index d1864f873..b8934b6c1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -1,3 +1,20 @@ +/* + * 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.provider; import android.content.ContentProvider; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index c27b3f6da..d7d98fd68 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -1,3 +1,20 @@ +/* + * 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.service; import android.app.Activity; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 11829e7b8..543b83edb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -1,3 +1,20 @@ +/* + * 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.service; import android.app.Activity; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 5e90b396e..3b55e6231 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -1,3 +1,20 @@ +/* + * 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.service; import android.os.Parcel; 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 b95dee12c..c730e5662 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 @@ -1,3 +1,20 @@ +/* + * 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.widget; import android.app.Activity; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java index 516e5ec39..a48d2a026 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java @@ -1,3 +1,20 @@ +/* + * 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.widget; import android.content.Context; -- cgit v1.2.3 From 2712c18a7a921118e6fe18563b4b38a003cd013a Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Mon, 4 Aug 2014 20:34:00 +0200 Subject: Use size of input uris for progress bar in encrypt/decrypt --- .../java/org/sufficientlysecure/keychain/helper/FileHelper.java | 6 +++++- .../sufficientlysecure/keychain/service/KeychainIntentService.java | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index ca0749a4e..1b36ba3fc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -193,7 +193,11 @@ public class FileHelper { } public static long getFileSize(Context context, Uri uri) { - long size = -1; + 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); 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 601f45fed..19f7bc9bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -719,13 +719,13 @@ public class KeychainIntentService extends IntentService Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); // InputStream - return new InputData(getContentResolver().openInputStream(providerUri), 0); + return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0)); case IO_URIS: providerUri = data.getParcelableArrayList(ENCRYPT_INPUT_URIS).get(data.getInt(SELECTED_URI)); // InputStream - return new InputData(getContentResolver().openInputStream(providerUri), 0); + return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0)); default: throw new PgpGeneralException("No target choosen!"); -- cgit v1.2.3 From 80408460a0aa16c38dc5b3269061bac85306d24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 00:23:04 +0200 Subject: KeychainContract: use longs instead of String, other fixes --- .../keychain/helper/ContactHelper.java | 2 +- .../keychain/provider/CachedPublicKeyRing.java | 2 +- .../keychain/provider/KeychainContract.java | 26 ++++++++++--------- .../keychain/provider/ProviderHelper.java | 14 +++++------ .../keychain/ui/EditKeyFragment.java | 29 ++++++++++++++-------- .../keychain/ui/ViewKeyCertsFragment.java | 2 +- .../keychain/ui/adapter/SubkeysAdapter.java | 10 ++++++++ .../ui/dialog/DeleteKeyDialogFragment.java | 2 +- .../ui/widget/EncryptKeyCompletionView.java | 2 +- 9 files changed, 55 insertions(+), 34 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 8fed40a86..1d8661bfe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -385,7 +385,7 @@ public class ContactHelper { 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(Long.toString(masterKeyId)), + Cursor ids = resolver.query(KeychainContract.UserIds.buildUserIdsUri(masterKeyId), USER_IDS_PROJECTION, NON_REVOKED_SELECTION, null, null); if (ids != null) { while (ids.moveToNext()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 89acbd488..e076fd9cc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -218,7 +218,7 @@ public class CachedPublicKeyRing extends KeyRing { } private Cursor getSubkeys() throws PgpGeneralException { - Uri keysUri = KeychainContract.Keys.buildKeysUri(Long.toString(extractOrGetMasterKeyId())); + Uri keysUri = KeychainContract.Keys.buildKeysUri(extractOrGetMasterKeyId()); return mProviderHelper.getContentResolver().query(keysUri, null, null, null, null); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 483f762f7..56168847f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -172,8 +172,8 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build(); } - public static Uri buildPublicKeyRingUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_PUBLIC).build(); + public static Uri buildPublicKeyRingUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_PUBLIC).build(); } public static Uri buildPublicKeyRingUri(Uri uri) { @@ -184,8 +184,8 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).build(); } - public static Uri buildSecretKeyRingUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_SECRET).build(); + public static Uri buildSecretKeyRingUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_SECRET).build(); } public static Uri buildSecretKeyRingUri(Uri uri) { @@ -210,8 +210,8 @@ public class KeychainContract { public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.keychain.keys"; - public static Uri buildKeysUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_KEYS).build(); + public static Uri buildKeysUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_KEYS).build(); } public static Uri buildKeysUri(Uri uri) { @@ -237,8 +237,8 @@ public class KeychainContract { public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.user_ids"; - public static Uri buildUserIdsUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_USER_IDS).build(); + public static Uri buildUserIdsUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_USER_IDS).build(); } public static Uri buildUserIdsUri(Uri uri) { @@ -304,12 +304,14 @@ public class KeychainContract { public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); - public static Uri buildCertsUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_CERTS).build(); + public static Uri buildCertsUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_CERTS).build(); } - public static Uri buildCertsSpecificUri(String masterKeyId, String rank, String certifier) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_CERTS).appendPath(rank).appendPath(certifier).build(); + public static Uri buildCertsSpecificUri(long masterKeyId, long rank, long certifier) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)) + .appendPath(PATH_CERTS).appendPath(Long.toString(rank)) + .appendPath(Long.toString(certifier)).build(); } public static Uri buildCertsUri(Uri uri) { 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 aa85577e0..e79771ed6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -299,7 +299,7 @@ public class ProviderHelper { return SaveKeyringResult.RESULT_ERROR; } - Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)); + Uri uri = KeyRingData.buildPublicKeyRingUri(masterKeyId); operations.add(ContentProviderOperation.newInsert(uri).withValues(values).build()); } @@ -307,7 +307,7 @@ public class ProviderHelper { progress.setProgress(LogType.MSG_IP_INSERT_SUBKEYS.getMsgId(), 40, 100); mIndent += 1; { // insert subkeys - Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); + Uri uri = Keys.buildKeysUri(masterKeyId); int rank = 0; for (CanonicalizedPublicKey key : keyRing.publicKeyIterator()) { long keyId = key.getKeyId(); @@ -498,7 +498,7 @@ public class ProviderHelper { try { // delete old version of this keyRing, which also deletes all keys and userIds on cascade int deleted = mContentResolver.delete( - KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null); + KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null); if (deleted > 0) { log(LogLevel.DEBUG, LogType.MSG_IP_DELETE_OLD_OK); result |= SaveKeyringResult.UPDATED; @@ -567,7 +567,7 @@ public class ProviderHelper { values.put(KeyRingData.MASTER_KEY_ID, masterKeyId); values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded()); // insert new version of this keyRing - Uri uri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); + Uri uri = KeyRingData.buildSecretKeyRingUri(masterKeyId); if (mContentResolver.insert(uri, values) == null) { log(LogLevel.ERROR, LogType.MSG_IS_DB_EXCEPTION); return SaveKeyringResult.RESULT_ERROR; @@ -579,7 +579,7 @@ public class ProviderHelper { } { - Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); + Uri uri = Keys.buildKeysUri(masterKeyId); // first, mark all keys as not available ContentValues values = new ContentValues(); @@ -836,7 +836,7 @@ public class ProviderHelper { values.put(Certs.VERIFIED, verified); values.put(Certs.DATA, cert.getEncoded()); - Uri uri = Certs.buildCertsUri(Long.toString(masterKeyId)); + Uri uri = Certs.buildCertsUri(masterKeyId); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } @@ -853,7 +853,7 @@ public class ProviderHelper { values.put(UserIds.IS_REVOKED, item.isRevoked); values.put(UserIds.RANK, rank); - Uri uri = UserIds.buildUserIdsUri(Long.toString(masterKeyId)); + Uri uri = UserIds.buildUserIdsUri(masterKeyId); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } 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 2d8bdad27..7460b73b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; 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.service.KeychainIntentService; @@ -215,8 +216,7 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - String userId = mUserIdsAdapter.getUserId(position); - editUserId(userId); + editUserId(position); } }); @@ -230,8 +230,7 @@ public class EditKeyFragment extends LoaderFragment implements mSubkeysList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - long keyId = mSubkeysAdapter.getKeyId(position); - editSubkey(keyId); + editSubkey(position); } }); @@ -320,7 +319,9 @@ public class EditKeyFragment extends LoaderFragment implements setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog"); } - private void editUserId(final String userId) { + private void editUserId(final int position) { + final String userId = mUserIdsAdapter.getUserId(position); + Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { @@ -360,13 +361,15 @@ public class EditKeyFragment extends LoaderFragment implements }); } - private void editSubkey(final long keyId) { + private void editSubkey(final int position) { + final long keyId = mSubkeysAdapter.getKeyId(position); + Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case EditSubkeyDialogFragment.MESSAGE_CHANGE_EXPIRY: - editSubkeyExpiry(keyId); + editSubkeyExpiry(position); break; case EditSubkeyDialogFragment.MESSAGE_REVOKE: // toggle @@ -394,13 +397,19 @@ public class EditKeyFragment extends LoaderFragment implements }); } - private void editSubkeyExpiry(final long keyId) { + private void editSubkeyExpiry(final int position) { + final long keyId = mSubkeysAdapter.getKeyId(position); + final Date creationDate = new Date(mSubkeysAdapter.getCreationDate(position)); + final Date expiryDate = new Date(mSubkeysAdapter.getExpiryDate(position)); + Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: - // toggle +// SaveKeyringParcel.SubkeyChange subkeyChange = new SaveKeyringParcel.SubkeyChange(); + +// mSaveKeyringParcel.mChangeSubKeys.add() // if (mSaveKeyringParcel.changePrimaryUserId != null // && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) { // mSaveKeyringParcel.changePrimaryUserId = null; @@ -419,7 +428,7 @@ public class EditKeyFragment extends LoaderFragment implements DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { public void run() { ChangeExpiryDialogFragment dialogFragment = - ChangeExpiryDialogFragment.newInstance(messenger, new Date(), new Date()); + ChangeExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog"); } 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 e98562690..5a55b0dad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java @@ -150,7 +150,7 @@ public class ViewKeyCertsFragment extends LoaderFragment Intent viewIntent = new Intent(getActivity(), ViewCertActivity.class); viewIntent.setData(Certs.buildCertsSpecificUri( - Long.toString(masterKeyId), Long.toString(rank), Long.toString(certifierId))); + masterKeyId, rank, certifierId)); startActivity(viewIntent); } } 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 0d8c7240d..25b3c0fc5 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 @@ -90,6 +90,16 @@ public class SubkeysAdapter extends CursorAdapter { return mCursor.getLong(INDEX_KEY_ID); } + public long getCreationDate(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(INDEX_CREATION); + } + + public long getExpiryDate(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(INDEX_EXPIRY); + } + @Override public Cursor swapCursor(Cursor newCursor) { hasAnySecret = false; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java index 01d2fae6a..4927a4d24 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java @@ -123,7 +123,7 @@ public class DeleteKeyDialogFragment extends DialogFragment { boolean success = false; for (long masterKeyId : masterKeyIds) { int count = activity.getContentResolver().delete( - KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null + KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null ); success = count > 0; } 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 c730e5662..03b0d658f 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 @@ -69,7 +69,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { private void initView() { swapCursor(null); - setPrefix(getContext().getString(R.string.label_to) + ": "); + setPrefix(getContext().getString(R.string.label_to)); allowDuplicates(false); } -- cgit v1.2.3 From 369f6e080c110a0446aad793886e60924afe510e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 15:07:11 +0200 Subject: Refactor expiry dialog --- .../keychain/service/SaveKeyringParcel.java | 72 +++++++- .../keychain/ui/EditKeyFragment.java | 33 ++-- .../keychain/ui/adapter/SubkeysAdapter.java | 36 ++-- .../ui/dialog/ChangeExpiryDialogFragment.java | 187 -------------------- .../ui/dialog/EditSubkeyExpiryDialogFragment.java | 189 +++++++++++++++++++++ 5 files changed, 291 insertions(+), 226 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 3b55e6231..abc377b7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -20,19 +20,23 @@ package org.sufficientlysecure.keychain.service; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + import java.io.Serializable; import java.util.ArrayList; -/** This class is a a transferable representation for a collection of changes +/** + * This class is a a transferable representation for a collection of changes * to be done on a keyring. - * + *

* This class should include all types of operations supported in the backend. - * + *

* All changes are done in a differential manner. Besides the two key * identification attributes, all attributes may be null, which indicates no * change to the keyring. This is also the reason why boxed values are used * instead of primitives in the subclasses. - * + *

* Application of operations in the backend should be fail-fast, which means an * error in any included operation (for example revocation of a non-existent * subkey) will cause the operation as a whole to fail. @@ -82,12 +86,23 @@ public class SaveKeyringParcel implements Parcelable { public int mKeysize; public int mFlags; public Long mExpiry; + public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { mAlgorithm = algorithm; mKeysize = keysize; mFlags = flags; mExpiry = expiry; } + + @Override + public String toString() { + String out = "mAlgorithm: " + mAlgorithm + ", "; + out += "mKeysize: " + mKeysize + ", "; + out += "mFlags: " + mFlags; + out += "mExpiry: " + mExpiry; + + return out; + } } public static class SubkeyChange implements Serializable { @@ -95,11 +110,46 @@ public class SaveKeyringParcel implements Parcelable { public Integer mFlags; // this is a long unix timestamp, in seconds (NOT MILLISECONDS!) public Long mExpiry; + + public SubkeyChange(long keyId) { + mKeyId = keyId; + } + public SubkeyChange(long keyId, Integer flags, Long expiry) { mKeyId = keyId; mFlags = flags; mExpiry = expiry; } + + @Override + public String toString() { + String out = "mKeyId: " + mKeyId + ", "; + out += "mFlags: " + mFlags + ", "; + out += "mExpiry: " + mExpiry; + + return out; + } + } + + public SubkeyChange getSubkeyChange(long keyId) { + for (SubkeyChange subkeyChange : mChangeSubKeys) { + if (subkeyChange.mKeyId == keyId) { + return subkeyChange; + } + } + return null; + } + + public SubkeyChange getOrCreateSubkeyChange(long keyId) { + SubkeyChange foundSubkeyChange = getSubkeyChange(keyId); + if (foundSubkeyChange != null) { + return foundSubkeyChange; + } else { + // else, create a new one + SubkeyChange newSubkeyChange = new SubkeyChange(keyId); + mChangeSubKeys.add(newSubkeyChange); + return newSubkeyChange; + } } public SaveKeyringParcel(Parcel source) { @@ -121,7 +171,7 @@ public class SaveKeyringParcel implements Parcelable { @Override public void writeToParcel(Parcel destination, int flags) { destination.writeInt(mMasterKeyId == null ? 0 : 1); - if(mMasterKeyId != null) { + if (mMasterKeyId != null) { destination.writeLong(mMasterKeyId); } destination.writeByteArray(mFingerprint); @@ -153,4 +203,16 @@ public class SaveKeyringParcel implements Parcelable { return 0; } + @Override + public String toString() { + String out = "mMasterKeyId: " + mMasterKeyId + "\n"; + out += "mNewPassphrase: " + mNewPassphrase + "\n"; + out += "mAddSubKeys: " + mAddSubKeys + "\n"; + out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; + out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; + out += "mRevokeUserIds: " + mRevokeUserIds + "\n"; + out += "mRevokeSubKeys: " + mRevokeSubKeys; + + return out; + } } 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 7460b73b4..6b062af59 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -45,7 +45,6 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; 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.service.KeychainIntentService; @@ -60,15 +59,13 @@ import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.ChangeExpiryDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.util.Date; - public class EditKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { @@ -96,8 +93,8 @@ public class EditKeyFragment extends LoaderFragment implements private Uri mDataUri; private SaveKeyringParcel mSaveKeyringParcel; - private String mPrimaryUserId; + private String mPrimaryUserId; private String mCurrentPassphrase; /** @@ -399,23 +396,17 @@ public class EditKeyFragment extends LoaderFragment implements private void editSubkeyExpiry(final int position) { final long keyId = mSubkeysAdapter.getKeyId(position); - final Date creationDate = new Date(mSubkeysAdapter.getCreationDate(position)); - final Date expiryDate = new Date(mSubkeysAdapter.getExpiryDate(position)); + final long creationDate = mSubkeysAdapter.getCreationDate(position); + final long expiryDate = mSubkeysAdapter.getExpiryDate(position); Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { - case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: -// SaveKeyringParcel.SubkeyChange subkeyChange = new SaveKeyringParcel.SubkeyChange(); - -// mSaveKeyringParcel.mChangeSubKeys.add() -// if (mSaveKeyringParcel.changePrimaryUserId != null -// && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) { -// mSaveKeyringParcel.changePrimaryUserId = null; -// } else { -// mSaveKeyringParcel.changePrimaryUserId = userId; -// } + case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: + long expiry = message.getData().getLong(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); + Log.d(Constants.TAG, "new expiry: " + expiry); + mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry; break; } getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); @@ -427,8 +418,8 @@ public class EditKeyFragment extends LoaderFragment implements DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { public void run() { - ChangeExpiryDialogFragment dialogFragment = - ChangeExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); + EditSubkeyExpiryDialogFragment dialogFragment = + EditSubkeyExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog"); } @@ -501,9 +492,7 @@ public class EditKeyFragment extends LoaderFragment implements } private void save(String passphrase) { - Log.d(Constants.TAG, "mSaveKeyringParcel.mAddUserIds: " + mSaveKeyringParcel.mAddUserIds); - Log.d(Constants.TAG, "mSaveKeyringParcel.mNewPassphrase: " + mSaveKeyringParcel.mNewPassphrase); - Log.d(Constants.TAG, "mSaveKeyringParcel.mRevokeUserIds: " + mSaveKeyringParcel.mRevokeUserIds); + Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString()); // Message is received after importing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( 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 25b3c0fc5..dd972866c 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 @@ -161,6 +161,11 @@ public class SubkeysAdapter extends CursorAdapter { boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; + Date expiryDate = null; + if (!cursor.isNull(INDEX_EXPIRY)) { + expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); + } + // for edit key if (mSaveKeyringParcel != null) { boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)); @@ -171,24 +176,21 @@ public class SubkeysAdapter extends CursorAdapter { } } + SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); + if (subkeyChange != null) { + // 0 is "no expiry" + if (subkeyChange.mExpiry != null && subkeyChange.mExpiry != 0) { + expiryDate = new Date(subkeyChange.mExpiry * 1000); + } + } + vEditImage.setVisibility(View.VISIBLE); } else { vEditImage.setVisibility(View.GONE); } - if (isRevoked) { - vRevokedIcon.setVisibility(View.VISIBLE); - } else { - vKeyId.setTextColor(mDefaultTextColor); - vKeyDetails.setTextColor(mDefaultTextColor); - vKeyExpiry.setTextColor(mDefaultTextColor); - - vRevokedIcon.setVisibility(View.GONE); - } - boolean isExpired; - if (!cursor.isNull(INDEX_EXPIRY)) { - Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); + if (expiryDate != null) { isExpired = expiryDate.before(new Date()); vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " @@ -199,6 +201,16 @@ public class SubkeysAdapter extends CursorAdapter { vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none)); } + if (isRevoked) { + vRevokedIcon.setVisibility(View.VISIBLE); + } else { + vKeyId.setTextColor(mDefaultTextColor); + vKeyDetails.setTextColor(mDefaultTextColor); + vKeyExpiry.setTextColor(mDefaultTextColor); + + vRevokedIcon.setVisibility(View.GONE); + } + // if key is expired or revoked, strike through text boolean isInvalid = isRevoked || isExpired; if (isInvalid) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java deleted file mode 100644 index d5354a9f6..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java +++ /dev/null @@ -1,187 +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.ui.dialog; - -import android.app.DatePickerDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.DialogFragment; -import android.text.format.DateUtils; -import android.widget.DatePicker; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class ChangeExpiryDialogFragment extends DialogFragment { - private static final String ARG_MESSENGER = "messenger"; - private static final String ARG_CREATION_DATE = "creation_date"; - private static final String ARG_EXPIRY_DATE = "expiry_date"; - - public static final int MESSAGE_NEW_EXPIRY_DATE = 1; - public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; - - private Messenger mMessenger; - private Calendar mCreationCal; - private Calendar mExpiryCal; - - private int mDatePickerResultCount = 0; - private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = - new DatePickerDialog.OnDateSetListener() { - public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - selectedCal.set(year, monthOfYear, dayOfMonth); - if (mExpiryCal != null) { - long numDays = (selectedCal.getTimeInMillis() / 86400000) - - (mExpiryCal.getTimeInMillis() / 86400000); - if (numDays > 0) { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } else { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } - } - }; - - public class ExpiryDatePickerDialog extends DatePickerDialog { - - public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack, - int year, int monthOfYear, int dayOfMonth) { - super(context, callBack, year, monthOfYear, dayOfMonth); - } - - // set permanent title - public void setTitle(CharSequence title) { - super.setTitle(getContext().getString(R.string.expiry_date_dialog_title)); - } - } - - /** - * Creates new instance of this dialog fragment - */ - public static ChangeExpiryDialogFragment newInstance(Messenger messenger, - Date creationDate, Date expiryDate) { - ChangeExpiryDialogFragment frag = new ChangeExpiryDialogFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_MESSENGER, messenger); - args.putSerializable(ARG_CREATION_DATE, creationDate); - args.putSerializable(ARG_EXPIRY_DATE, expiryDate); - - frag.setArguments(args); - - return frag; - } - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - mMessenger = getArguments().getParcelable(ARG_MESSENGER); - Date creationDate = (Date) getArguments().getSerializable(ARG_CREATION_DATE); - Date expiryDate = (Date) getArguments().getSerializable(ARG_EXPIRY_DATE); - - mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mCreationCal.setTime(creationDate); - mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mExpiryCal.setTime(expiryDate); - - /* - * Using custom DatePickerDialog which overrides the setTitle because - * the DatePickerDialog title is buggy (unix warparound bug). - * See: https://code.google.com/p/android/issues/detail?id=49066 - */ - DatePickerDialog dialog = new ExpiryDatePickerDialog(getActivity(), - mExpiryDateSetListener, mExpiryCal.get(Calendar.YEAR), mExpiryCal.get(Calendar.MONTH), - mExpiryCal.get(Calendar.DAY_OF_MONTH)); - mDatePickerResultCount = 0; - dialog.setCancelable(true); - dialog.setButton(Dialog.BUTTON_NEGATIVE, - getActivity().getString(R.string.btn_no_date), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - // none expiry dates corresponds to a null message - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } - } - ); - - // setCalendarViewShown() is supported from API 11 onwards. - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // Hide calendarView in tablets because of the unix warparound bug. - dialog.getDatePicker().setCalendarViewShown(false); - } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // will crash with IllegalArgumentException if we set a min date - // that is not before expiry - if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { - dialog.getDatePicker().setMinDate(mCreationCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } else { - // When created date isn't available - dialog.getDatePicker().setMinDate(mExpiryCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } - } - - return dialog; - } - - /** - * Send message back to handler which is initialized in a activity - * - * @param what Message integer you want to send - */ - private void sendMessageToHandler(Integer what, Bundle data) { - Message msg = Message.obtain(); - msg.what = what; - if (data != null) { - msg.setData(data); - } - - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java new file mode 100644 index 000000000..1712b922f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -0,0 +1,189 @@ +/* + * 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.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.DialogFragment; +import android.text.format.DateUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.DatePicker; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +public class EditSubkeyExpiryDialogFragment extends DialogFragment { + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_CREATION_DATE = "creation_date"; + private static final String ARG_EXPIRY_DATE = "expiry_date"; + + public static final int MESSAGE_NEW_EXPIRY_DATE = 1; + public static final int MESSAGE_CANCEL = 2; + public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; + + private Messenger mMessenger; + private Calendar mCreationCal; + private Calendar mExpiryCal; + + private DatePicker mDatePicker; + + /** + * Creates new instance of this dialog fragment + */ + public static EditSubkeyExpiryDialogFragment newInstance(Messenger messenger, + long creationDate, long expiryDate) { + EditSubkeyExpiryDialogFragment frag = new EditSubkeyExpiryDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_MESSENGER, messenger); + args.putLong(ARG_CREATION_DATE, creationDate); + args.putLong(ARG_EXPIRY_DATE, expiryDate); + + frag.setArguments(args); + + return frag; + } + + /** + * Creates dialog + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + mMessenger = getArguments().getParcelable(ARG_MESSENGER); + Date creationDate = new Date(getArguments().getLong(ARG_CREATION_DATE) * 1000); + Date expiryDate = new Date(getArguments().getLong(ARG_EXPIRY_DATE) * 1000); + + mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + mCreationCal.setTime(creationDate); + mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + mExpiryCal.setTime(expiryDate); + + Log.d(Constants.TAG, "onCreateDialog"); + + // Explicitly not using DatePickerDialog here! + // DatePickerDialog is difficult to customize and has many problems (see old git versions) + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); + + alert.setTitle(R.string.expiry_date_dialog_title); + + LayoutInflater inflater = activity.getLayoutInflater(); + View view = inflater.inflate(R.layout.expiry_dialog, null); + alert.setView(view); + + mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { + // will crash with IllegalArgumentException if we set a min date + // that is not before expiry + if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { + mDatePicker.setMinDate(mCreationCal.getTime().getTime() + + DateUtils.DAY_IN_MILLIS); + } else { + // When created date isn't available + mDatePicker.setMinDate(mExpiryCal.getTime().getTime() + + DateUtils.DAY_IN_MILLIS); + } + } + + alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + + Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + //noinspection ResourceType + selectedCal.set(mDatePicker.getYear(), mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); + + if (mExpiryCal != null) { + long numDays = (selectedCal.getTimeInMillis() / 86400000) + - (mExpiryCal.getTimeInMillis() / 86400000); + if (numDays > 0) { + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + } else { + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + } + }); + + alert.setNeutralButton(R.string.btn_no_date, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + + // "no expiry" corresponds to a 0 + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, 0); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + }); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + } + }); + + return alert.show(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + dismiss(); + sendMessageToHandler(MESSAGE_CANCEL, null); + } + + /** + * Send message back to handler which is initialized in a activity + * + * @param what Message integer you want to send + */ + private void sendMessageToHandler(Integer what, Bundle data) { + Message msg = Message.obtain(); + msg.what = what; + if (data != null) { + msg.setData(data); + } + + try { + mMessenger.send(msg); + } catch (RemoteException e) { + Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); + } catch (NullPointerException e) { + Log.w(Constants.TAG, "Messenger is null!", e); + } + } +} -- cgit v1.2.3 From 160e6972d8366e4b0b8d72fa838434629588c930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 17:25:22 +0200 Subject: Create key: make single user id primary user id, other cleanup --- .../keychain/service/SaveKeyringParcel.java | 1 + .../keychain/ui/CreateKeyFinalFragment.java | 1 + .../keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java | 11 +++++------ 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index abc377b7e..442746feb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -207,6 +207,7 @@ public class SaveKeyringParcel implements Parcelable { public String toString() { String out = "mMasterKeyId: " + mMasterKeyId + "\n"; out += "mNewPassphrase: " + mNewPassphrase + "\n"; + out += "mAddUserIds: " + mAddUserIds + "\n"; out += "mAddSubKeys: " + mAddSubKeys + "\n"; out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; 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 662ba4ce1..abbc3f199 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -174,6 +174,7 @@ public class CreateKeyFinalFragment extends Fragment { parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); String userId = KeyRing.createUserId(mName, mEmail, null); parcel.mAddUserIds.add(userId); + parcel.mChangePrimaryUserId = userId; parcel.mNewPassphrase = mPassphrase; // get selected key entries diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index 1712b922f..8482c0b37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -48,7 +48,6 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; private Messenger mMessenger; - private Calendar mCreationCal; private Calendar mExpiryCal; private DatePicker mDatePicker; @@ -79,8 +78,8 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { Date creationDate = new Date(getArguments().getLong(ARG_CREATION_DATE) * 1000); Date expiryDate = new Date(getArguments().getLong(ARG_EXPIRY_DATE) * 1000); - mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mCreationCal.setTime(creationDate); + Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + creationCal.setTime(creationDate); mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); mExpiryCal.setTime(expiryDate); @@ -101,11 +100,11 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { // will crash with IllegalArgumentException if we set a min date // that is not before expiry - if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { - mDatePicker.setMinDate(mCreationCal.getTime().getTime() + if (creationCal.before(mExpiryCal)) { + mDatePicker.setMinDate(creationCal.getTime().getTime() + DateUtils.DAY_IN_MILLIS); } else { - // When created date isn't available + // when creation date isn't available mDatePicker.setMinDate(mExpiryCal.getTime().getTime() + DateUtils.DAY_IN_MILLIS); } -- cgit v1.2.3 From d377d1f23d75ad78982419e9ca9633cd5b6813e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 17:59:05 +0200 Subject: Better handling of user id revocation in UI code --- .../keychain/ui/EditKeyFragment.java | 5 +- .../keychain/ui/adapter/UserIdsAdapter.java | 20 +++++++ .../ui/dialog/EditUserIdDialogFragment.java | 64 ++++++++++++++++------ 3 files changed, 70 insertions(+), 19 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 6b062af59..7697f736c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -318,6 +318,8 @@ public class EditKeyFragment extends LoaderFragment implements private void editUserId(final int position) { final String userId = mUserIdsAdapter.getUserId(position); + final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); + final boolean isRevokedPending = mUserIdsAdapter.getIsRevokedPending(position); Handler returnHandler = new Handler() { @Override @@ -351,8 +353,7 @@ public class EditKeyFragment extends LoaderFragment implements DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { public void run() { EditUserIdDialogFragment dialogFragment = - EditUserIdDialogFragment.newInstance(messenger); - + EditUserIdDialogFragment.newInstance(messenger, isRevoked, isRevokedPending); dialogFragment.show(getActivity().getSupportFragmentManager(), "editUserIdDialog"); } }); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index ee3341c08..9bf47a387 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -252,6 +252,26 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC return mCursor.getString(INDEX_USER_ID); } + public boolean getIsRevoked(int position) { + mCursor.moveToPosition(position); + return mCursor.getInt(INDEX_IS_REVOKED) > 0; + } + + public boolean getIsRevokedPending(int position) { + mCursor.moveToPosition(position); + String userId = mCursor.getString(INDEX_USER_ID); + + boolean isRevokedPending = false; + if (mSaveKeyringParcel != null) { + if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) { + isRevokedPending = true; + } + + } + + return isRevokedPending; + } + @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = mInflater.inflate(R.layout.view_key_user_id_item, null); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java index 5eba3a463..8a31b7f64 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java @@ -29,9 +29,14 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; +import java.util.Arrays; + public class EditUserIdDialogFragment extends DialogFragment { private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_IS_REVOKED = "is_revoked"; + private static final String ARG_IS_REVOKED_PENDING = "is_revoked_pending"; + public static final int MESSAGE_CHANGE_PRIMARY_USER_ID = 1; public static final int MESSAGE_REVOKE = 2; @@ -40,10 +45,13 @@ public class EditUserIdDialogFragment extends DialogFragment { /** * Creates new instance of this dialog fragment */ - public static EditUserIdDialogFragment newInstance(Messenger messenger) { + public static EditUserIdDialogFragment newInstance(Messenger messenger, boolean isRevoked, + boolean isRevokedPending) { EditUserIdDialogFragment frag = new EditUserIdDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); + args.putBoolean(ARG_IS_REVOKED, isRevoked); + args.putBoolean(ARG_IS_REVOKED_PENDING, isRevokedPending); frag.setArguments(args); @@ -56,27 +64,49 @@ public class EditUserIdDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { mMessenger = getArguments().getParcelable(ARG_MESSENGER); + boolean isRevoked = getArguments().getBoolean(ARG_IS_REVOKED); + boolean isRevokedPending = getArguments().getBoolean(ARG_IS_REVOKED_PENDING); CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); - CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_user_id); - builder.setTitle(R.string.edit_key_edit_user_id_title); - builder.setItems(array, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case 0: - sendMessageToHandler(MESSAGE_CHANGE_PRIMARY_USER_ID, null); - break; - case 1: - sendMessageToHandler(MESSAGE_REVOKE, null); - break; - default: - break; + if (isRevokedPending) { + CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_user_id_revert_revocation); + + builder.setItems(array, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case 0: + sendMessageToHandler(MESSAGE_REVOKE, null); + break; + default: + break; + } } - } - }); + }); + } else if (isRevoked) { + builder.setMessage(R.string.edit_key_edit_user_id_revoked); + } else { + CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_user_id); + + builder.setItems(array, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case 0: + sendMessageToHandler(MESSAGE_CHANGE_PRIMARY_USER_ID, null); + break; + case 1: + sendMessageToHandler(MESSAGE_REVOKE, null); + break; + default: + break; + } + } + }); + } + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { -- cgit v1.2.3 From 04cdd45e1aceb940fe74051a0015e5ab85b18314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 18:35:48 +0200 Subject: Work on add subkey dialog design --- .../ui/dialog/AddSubkeyDialogFragment.java | 46 +++++++++++++++++----- .../ui/dialog/EditSubkeyExpiryDialogFragment.java | 4 +- .../ui/dialog/EditUserIdDialogFragment.java | 2 - 3 files changed, 39 insertions(+), 13 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index 2031eae2a..c085adf40 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -32,6 +32,9 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.DatePicker; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; @@ -54,11 +57,18 @@ public class AddSubkeyDialogFragment extends DialogFragment { private static final String ARG_WILL_BE_MASTER_KEY = "will_be_master_key"; private OnAlgorithmSelectedListener mAlgorithmSelectedListener; + + private CheckBox mNoExpiryCheckBox; + private DatePicker mExpiryDatePicker; private Spinner mAlgorithmSpinner; private Spinner mKeySizeSpinner; private TextView mCustomKeyTextView; private EditText mCustomKeyEditText; private TextView mCustomKeyInfoTextView; + private CheckBox mFlagCertify; + private CheckBox mFlagSign; + private CheckBox mFlagEncrypt; + private CheckBox mFlagAuthenticate; public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) { mAlgorithmSelectedListener = listener; @@ -85,11 +95,33 @@ public class AddSubkeyDialogFragment extends DialogFragment { CustomAlertDialogBuilder dialog = new CustomAlertDialogBuilder(context); - View view = mInflater.inflate(R.layout.create_key_dialog, null); + View view = mInflater.inflate(R.layout.add_subkey_dialog, null); dialog.setView(view); dialog.setTitle(R.string.title_create_key); - mAlgorithmSpinner = (Spinner) view.findViewById(R.id.create_key_algorithm); + mNoExpiryCheckBox = (CheckBox) view.findViewById(R.id.add_subkey_no_expiry); + mExpiryDatePicker = (DatePicker) view.findViewById(R.id.add_subkey_expiry_date_picker); + mAlgorithmSpinner = (Spinner) view.findViewById(R.id.add_subkey_algorithm); + mKeySizeSpinner = (Spinner) view.findViewById(R.id.add_subkey_size); + mCustomKeyTextView = (TextView) view.findViewById(R.id.add_subkey_custom_key_size_label); + mCustomKeyEditText = (EditText) view.findViewById(R.id.add_subkey_custom_key_size_input); + mCustomKeyInfoTextView = (TextView) view.findViewById(R.id.add_subkey_custom_key_size_info); + mFlagCertify = (CheckBox) view.findViewById(R.id.add_subkey_flag_certify); + mFlagSign = (CheckBox) view.findViewById(R.id.add_subkey_flag_sign); + mFlagEncrypt = (CheckBox) view.findViewById(R.id.add_subkey_flag_encrypt); + mFlagAuthenticate = (CheckBox) view.findViewById(R.id.add_subkey_flag_authenticate); + + mNoExpiryCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + mExpiryDatePicker.setVisibility(View.GONE); + } else { + mExpiryDatePicker.setVisibility(View.VISIBLE); + } + } + }); + ArrayList choices = new ArrayList(); choices.add(new Choice(Constants.choice.algorithm.dsa, getResources().getString( R.string.dsa))); @@ -97,10 +129,8 @@ public class AddSubkeyDialogFragment extends DialogFragment { choices.add(new Choice(Constants.choice.algorithm.elgamal, getResources().getString( R.string.elgamal))); } - choices.add(new Choice(Constants.choice.algorithm.rsa, getResources().getString( R.string.rsa))); - ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, choices); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -113,7 +143,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { } } - mKeySizeSpinner = (Spinner) view.findViewById(R.id.create_key_size); + // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change ArrayAdapter keySizeAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); @@ -121,9 +151,6 @@ public class AddSubkeyDialogFragment extends DialogFragment { mKeySizeSpinner.setAdapter(keySizeAdapter); mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length - mCustomKeyTextView = (TextView) view.findViewById(R.id.custom_key_size_label); - mCustomKeyEditText = (EditText) view.findViewById(R.id.custom_key_size_input); - mCustomKeyInfoTextView = (TextView) view.findViewById(R.id.custom_key_size_info); dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -148,7 +175,8 @@ public class AddSubkeyDialogFragment extends DialogFragment { public void onClick(DialogInterface di, int id) { di.dismiss(); } - }); + } + ); final AlertDialog alertDialog = dialog.show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index 8482c0b37..303ab4363 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -92,10 +92,10 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { alert.setTitle(R.string.expiry_date_dialog_title); LayoutInflater inflater = activity.getLayoutInflater(); - View view = inflater.inflate(R.layout.expiry_dialog, null); + View view = inflater.inflate(R.layout.edit_subkey_expiry_dialog, null); alert.setView(view); - mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); + mDatePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { // will crash with IllegalArgumentException if we set a min date diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java index 8a31b7f64..70a3b8fd0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java @@ -29,8 +29,6 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; -import java.util.Arrays; - public class EditUserIdDialogFragment extends DialogFragment { private static final String ARG_MESSENGER = "messenger"; -- cgit v1.2.3 From 39380a361718201fdefa86628fb0deb8771deaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 18:42:55 +0200 Subject: More work on add subkey dialog design --- .../keychain/ui/dialog/AddSubkeyDialogFragment.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index c085adf40..34bb3486a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -37,6 +37,7 @@ import android.widget.CompoundButton; import android.widget.DatePicker; import android.widget.EditText; import android.widget.Spinner; +import android.widget.TableRow; import android.widget.TextView; import org.spongycastle.bcpg.sig.KeyFlags; @@ -59,6 +60,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { private OnAlgorithmSelectedListener mAlgorithmSelectedListener; private CheckBox mNoExpiryCheckBox; + private TableRow mExpiryRow; private DatePicker mExpiryDatePicker; private Spinner mAlgorithmSpinner; private Spinner mKeySizeSpinner; @@ -97,9 +99,10 @@ public class AddSubkeyDialogFragment extends DialogFragment { View view = mInflater.inflate(R.layout.add_subkey_dialog, null); dialog.setView(view); - dialog.setTitle(R.string.title_create_key); + dialog.setTitle(R.string.title_add_subkey); mNoExpiryCheckBox = (CheckBox) view.findViewById(R.id.add_subkey_no_expiry); + mExpiryRow = (TableRow) view.findViewById(R.id.add_subkey_expiry_row); mExpiryDatePicker = (DatePicker) view.findViewById(R.id.add_subkey_expiry_date_picker); mAlgorithmSpinner = (Spinner) view.findViewById(R.id.add_subkey_algorithm); mKeySizeSpinner = (Spinner) view.findViewById(R.id.add_subkey_size); @@ -115,9 +118,9 @@ public class AddSubkeyDialogFragment extends DialogFragment { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { - mExpiryDatePicker.setVisibility(View.GONE); + mExpiryRow.setVisibility(View.GONE); } else { - mExpiryDatePicker.setVisibility(View.VISIBLE); + mExpiryRow.setVisibility(View.VISIBLE); } } }); -- cgit v1.2.3 From f8a222983efe5741a0d79147c6724a49ad7e5b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 20:52:29 +0200 Subject: Use PublicKeyAlgorithmTags instead of homebrew choices constants, fix expiry selection for adding new subkeys --- .../org/sufficientlysecure/keychain/Constants.java | 7 --- .../keychain/pgp/PgpKeyHelper.java | 22 ++++---- .../keychain/pgp/PgpKeyOperation.java | 9 ++-- .../keychain/ui/CreateKeyFinalFragment.java | 8 +-- .../keychain/ui/EditKeyFragment.java | 9 ++-- .../keychain/ui/adapter/SubkeysAdapter.java | 13 +++-- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 36 +++++-------- .../ui/dialog/AddSubkeyDialogFragment.java | 61 +++++++++++++++++----- .../ui/dialog/EditSubkeyExpiryDialogFragment.java | 13 +++-- 9 files changed, 101 insertions(+), 77 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 6423697cf..df39efeb0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -92,13 +92,6 @@ public final class Constants { } public static final class choice { - public static final class algorithm { - // TODO: legacy reasons :/ better: PublicKeyAlgorithmTags - public static final int dsa = 0x21070001; - public static final int elgamal = 0x21070002; - public static final int rsa = 0x21070003; - } - public static final class compression { // TODO: legacy reasons :/ better: CompressionAlgorithmTags.UNCOMPRESSED public static final int none = 0x21070001; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index 7e18aa906..0c640538f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -24,7 +24,7 @@ import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; -import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -37,9 +37,6 @@ import java.util.Locale; public class PgpKeyHelper { - /** - * TODO: Only used in HkpKeyServer. Get rid of this one! - */ public static String getAlgorithmInfo(int algorithm) { return getAlgorithmInfo(null, algorithm, 0); } @@ -55,25 +52,25 @@ public class PgpKeyHelper { String algorithmStr; switch (algorithm) { - case PGPPublicKey.RSA_ENCRYPT: - case PGPPublicKey.RSA_GENERAL: - case PGPPublicKey.RSA_SIGN: { + case PublicKeyAlgorithmTags.RSA_ENCRYPT: + case PublicKeyAlgorithmTags.RSA_GENERAL: + case PublicKeyAlgorithmTags.RSA_SIGN: { algorithmStr = "RSA"; break; } - case PGPPublicKey.DSA: { + case PublicKeyAlgorithmTags.DSA: { algorithmStr = "DSA"; break; } - case PGPPublicKey.ELGAMAL_ENCRYPT: - case PGPPublicKey.ELGAMAL_GENERAL: { + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: + case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: { algorithmStr = "ElGamal"; break; } - case PGPPublicKey.ECDSA: - case PGPPublicKey.ECDH: { + case PublicKeyAlgorithmTags.ECDSA: + case PublicKeyAlgorithmTags.ECDH: { algorithmStr = "ECC"; break; } @@ -82,7 +79,6 @@ public class PgpKeyHelper { if (context != null) { algorithmStr = context.getResources().getString(R.string.unknown_algorithm); } else { - // TODO algorithmStr = "unknown"; } break; 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 3f058d888..6cd020684 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; +import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; @@ -138,7 +139,7 @@ public class PgpKeyOperation { KeyPairGenerator keyGen; switch (algorithmChoice) { - case Constants.choice.algorithm.dsa: { + case PublicKeyAlgorithmTags.DSA: { progress(R.string.progress_generating_dsa, 30); keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); keyGen.initialize(keySize, new SecureRandom()); @@ -146,7 +147,7 @@ public class PgpKeyOperation { break; } - case Constants.choice.algorithm.elgamal: { + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: { progress(R.string.progress_generating_elgamal, 30); keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME); BigInteger p = Primes.getBestPrime(keySize); @@ -159,7 +160,7 @@ public class PgpKeyOperation { break; } - case Constants.choice.algorithm.rsa: { + case PublicKeyAlgorithmTags.RSA_GENERAL: { progress(R.string.progress_generating_rsa, 30); keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); keyGen.initialize(keySize, new SecureRandom()); @@ -217,7 +218,7 @@ public class PgpKeyOperation { return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - if (add.mAlgorithm == Constants.choice.algorithm.elgamal) { + if (add.mAlgorithm == PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT) { log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_MASTER_ELGAMAL, indent); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } 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 abbc3f199..de9c7f77d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -31,7 +31,9 @@ import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; +import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; +import org.spongycastle.openpgp.PGPPublicKey; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; @@ -169,9 +171,9 @@ public class CreateKeyFinalFragment extends Fragment { Bundle data = new Bundle(); SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.CERTIFY_OTHER, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.CERTIFY_OTHER, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.SIGN_DATA, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); String userId = KeyRing.createUserId(mName, mEmail, null); parcel.mAddUserIds.add(userId); parcel.mChangePrimaryUserId = userId; 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 7697f736c..1a37567eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -397,15 +397,16 @@ public class EditKeyFragment extends LoaderFragment implements private void editSubkeyExpiry(final int position) { final long keyId = mSubkeysAdapter.getKeyId(position); - final long creationDate = mSubkeysAdapter.getCreationDate(position); - final long expiryDate = mSubkeysAdapter.getExpiryDate(position); + final Long creationDate = mSubkeysAdapter.getCreationDate(position); + final Long expiryDate = mSubkeysAdapter.getExpiryDate(position); Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: - long expiry = message.getData().getLong(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); + Long expiry = (Long) message.getData(). + getSerializable(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); Log.d(Constants.TAG, "new expiry: " + expiry); mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry; break; @@ -464,7 +465,7 @@ public class EditKeyFragment extends LoaderFragment implements new AddSubkeyDialogFragment.OnAlgorithmSelectedListener() { @Override public void onAlgorithmSelected(SaveKeyringParcel.SubkeyAdd newSubkey) { - mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); + mSubkeysAddedAdapter.add(newSubkey); } } ); 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 dd972866c..e845c7e42 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 @@ -95,9 +95,13 @@ public class SubkeysAdapter extends CursorAdapter { return mCursor.getLong(INDEX_CREATION); } - public long getExpiryDate(int position) { + public Long getExpiryDate(int position) { mCursor.moveToPosition(position); - return mCursor.getLong(INDEX_EXPIRY); + if (mCursor.isNull(INDEX_EXPIRY)) { + return null; + } else { + return mCursor.getLong(INDEX_EXPIRY); + } } @Override @@ -178,8 +182,9 @@ public class SubkeysAdapter extends CursorAdapter { SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); if (subkeyChange != null) { - // 0 is "no expiry" - if (subkeyChange.mExpiry != null && subkeyChange.mExpiry != 0) { + if (subkeyChange.mExpiry == null) { + expiryDate = null; + } else { expiryDate = new Date(subkeyChange.mExpiry * 1000); } } 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 1ec9add68..b3f87a4c4 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 @@ -102,35 +102,27 @@ public class SubkeysAddedAdapter extends ArrayAdapter= android.os.Build.VERSION_CODES.HONEYCOMB) { + mExpiryDatePicker.setMinDate(new Date().getTime() + DateUtils.DAY_IN_MILLIS); + } + ArrayList choices = new ArrayList(); - choices.add(new Choice(Constants.choice.algorithm.dsa, getResources().getString( + choices.add(new Choice(PublicKeyAlgorithmTags.DSA, getResources().getString( R.string.dsa))); if (!willBeMasterKey) { - choices.add(new Choice(Constants.choice.algorithm.elgamal, getResources().getString( + choices.add(new Choice(PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, getResources().getString( R.string.elgamal))); } - choices.add(new Choice(Constants.choice.algorithm.rsa, getResources().getString( + choices.add(new Choice(PublicKeyAlgorithmTags.RSA_GENERAL, getResources().getString( R.string.rsa))); ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, choices); @@ -140,13 +150,12 @@ public class AddSubkeyDialogFragment extends DialogFragment { mAlgorithmSpinner.setAdapter(adapter); // make RSA the default for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Constants.choice.algorithm.rsa) { + if (choices.get(i).getId() == PublicKeyAlgorithmTags.RSA_GENERAL) { mAlgorithmSpinner.setSelection(i); break; } } - // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change ArrayAdapter keySizeAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); @@ -161,11 +170,37 @@ public class AddSubkeyDialogFragment extends DialogFragment { di.dismiss(); Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); + + int flags = 0; + if (mFlagCertify.isChecked()) { + flags += KeyFlags.CERTIFY_OTHER; + } + if (mFlagSign.isChecked()) { + flags += KeyFlags.SIGN_DATA; + } + if (mFlagEncrypt.isChecked()) { + flags += KeyFlags.ENCRYPT_COMMS + KeyFlags.ENCRYPT_STORAGE; + } + if (mFlagAuthenticate.isChecked()) { + flags += KeyFlags.AUTHENTICATION; + } + + Long expiry; + if (mNoExpiryCheckBox.isChecked()) { + expiry = null; + } else { + Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + //noinspection ResourceType + selectedCal.set(mExpiryDatePicker.getYear(), + mExpiryDatePicker.getMonth(), mExpiryDatePicker.getDayOfMonth()); + expiry = selectedCal.getTime().getTime() / 1000; + } + SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd( newKeyAlgorithmChoice.getId(), newKeySize, - KeyFlags.SIGN_DATA, //TODO - null + flags, + expiry ); mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey); } @@ -261,12 +296,12 @@ public class AddSubkeyDialogFragment extends DialogFragment { final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; int properKeyLength = -1; switch (algorithmId) { - case Constants.choice.algorithm.rsa: + case PublicKeyAlgorithmTags.RSA_GENERAL: if (currentKeyLength > 1024 && currentKeyLength <= 8192) { properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); } break; - case Constants.choice.algorithm.elgamal: + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; for (int i = 0; i < elGamalSupportedLengths.length; i++) { elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); @@ -281,7 +316,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { } properKeyLength = elGamalSupportedLengths[minimalIndex]; break; - case Constants.choice.algorithm.dsa: + case PublicKeyAlgorithmTags.DSA: if (currentKeyLength >= 512 && currentKeyLength <= 1024) { properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); } @@ -320,15 +355,15 @@ public class AddSubkeyDialogFragment extends DialogFragment { final Object selectedItem = mKeySizeSpinner.getSelectedItem(); keySizeAdapter.clear(); switch (algorithmId) { - case Constants.choice.algorithm.rsa: + case PublicKeyAlgorithmTags.RSA_GENERAL: replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); break; - case Constants.choice.algorithm.elgamal: + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length break; - case Constants.choice.algorithm.dsa: + case PublicKeyAlgorithmTags.DSA: replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index 303ab4363..aa63f9944 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -56,12 +56,12 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { * Creates new instance of this dialog fragment */ public static EditSubkeyExpiryDialogFragment newInstance(Messenger messenger, - long creationDate, long expiryDate) { + Long creationDate, Long expiryDate) { EditSubkeyExpiryDialogFragment frag = new EditSubkeyExpiryDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); - args.putLong(ARG_CREATION_DATE, creationDate); - args.putLong(ARG_EXPIRY_DATE, expiryDate); + args.putSerializable(ARG_CREATION_DATE, creationDate); + args.putSerializable(ARG_EXPIRY_DATE, expiryDate); frag.setArguments(args); @@ -124,12 +124,12 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { - (mExpiryCal.getTimeInMillis() / 86400000); if (numDays > 0) { Bundle data = new Bundle(); - data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); } } else { Bundle data = new Bundle(); - data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); } } @@ -140,9 +140,8 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public void onClick(DialogInterface dialog, int id) { dismiss(); - // "no expiry" corresponds to a 0 Bundle data = new Bundle(); - data.putLong(MESSAGE_DATA_EXPIRY_DATE, 0); + data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null); sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); } }); -- cgit v1.2.3 From 1455af2eed0f5efa2bc3b3317334796516670970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 22:35:37 +0200 Subject: Edit key: key flags --- .../keychain/pgp/PgpKeyOperation.java | 2 +- .../keychain/ui/EditKeyFragment.java | 1 - .../keychain/ui/adapter/SubkeysAdapter.java | 1 + .../keychain/ui/adapter/SubkeysAddedAdapter.java | 31 +++++++++++++++------- .../ui/dialog/AddSubkeyDialogFragment.java | 8 +++--- 5 files changed, 27 insertions(+), 16 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 6cd020684..bb692555e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -769,7 +769,7 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); // If this key can sign, we need a primary key binding signature - if ((flags & KeyFlags.SIGN_DATA) != 0) { + if ((flags & KeyFlags.SIGN_DATA) > 0) { // cross-certify signing keys PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); subHashedPacketsGen.setSignatureCreationTime(false, todayDate); 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 1a37567eb..82206655f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -407,7 +407,6 @@ public class EditKeyFragment extends LoaderFragment implements case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: Long expiry = (Long) message.getData(). getSerializable(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); - Log.d(Constants.TAG, "new expiry: " + expiry); mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry; break; } 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 e845c7e42..d457e75bd 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 @@ -162,6 +162,7 @@ public class SubkeysAdapter extends CursorAdapter { vCertifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE); vEncryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE); vSignIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE); + // TODO: missing icon for authenticate boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; 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 b3f87a4c4..be2e17c63 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 @@ -28,6 +28,7 @@ import android.widget.ImageButton; import android.widget.ImageView; 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.service.SaveKeyringParcel; @@ -56,7 +57,6 @@ public class SubkeysAddedAdapter extends ArrayAdapter 0) { + holder.vCertifyIcon.setVisibility(View.VISIBLE); + } else { + holder.vCertifyIcon.setVisibility(View.GONE); + } + if ((flags & KeyFlags.SIGN_DATA) > 0) { + holder.vSignIcon.setVisibility(View.VISIBLE); + } else { + holder.vSignIcon.setVisibility(View.GONE); + } + if (((flags & KeyFlags.ENCRYPT_COMMS) > 0) + || ((flags & KeyFlags.ENCRYPT_STORAGE) > 0)) { + holder.vEncryptIcon.setVisibility(View.VISIBLE); + } else { + holder.vEncryptIcon.setVisibility(View.GONE); + } + // TODO: missing icon for authenticate return convertView; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index 53428f526..27c797a7d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -173,16 +173,16 @@ public class AddSubkeyDialogFragment extends DialogFragment { int flags = 0; if (mFlagCertify.isChecked()) { - flags += KeyFlags.CERTIFY_OTHER; + flags |= KeyFlags.CERTIFY_OTHER; } if (mFlagSign.isChecked()) { - flags += KeyFlags.SIGN_DATA; + flags |= KeyFlags.SIGN_DATA; } if (mFlagEncrypt.isChecked()) { - flags += KeyFlags.ENCRYPT_COMMS + KeyFlags.ENCRYPT_STORAGE; + flags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE; } if (mFlagAuthenticate.isChecked()) { - flags += KeyFlags.AUTHENTICATION; + flags |= KeyFlags.AUTHENTICATION; } Long expiry; -- cgit v1.2.3 From 6354b2dcf9d73f4931dcbc8c5ab3e89693b65ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 22:38:36 +0200 Subject: Increase maximum custom RSA size --- .../sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index 27c797a7d..9841deeab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -297,7 +297,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { int properKeyLength = -1; switch (algorithmId) { case PublicKeyAlgorithmTags.RSA_GENERAL: - if (currentKeyLength > 1024 && currentKeyLength <= 8192) { + if (currentKeyLength > 1024 && currentKeyLength <= 16384) { properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); } break; -- cgit v1.2.3 From f4802157dd1137e765acb9b538d26828b6fce3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 22:46:00 +0200 Subject: Optimize imports --- .../java/org/sufficientlysecure/keychain/Constants.java | 1 - .../sufficientlysecure/keychain/KeychainApplication.java | 1 - .../sufficientlysecure/keychain/helper/ContactHelper.java | 13 +++++++++++-- .../sufficientlysecure/keychain/helper/EmailKeyHelper.java | 1 + .../sufficientlysecure/keychain/helper/ExportHelper.java | 1 - .../org/sufficientlysecure/keychain/helper/FileHelper.java | 7 +++++-- .../org/sufficientlysecure/keychain/helper/TlsHelper.java | 12 ++++++++---- .../sufficientlysecure/keychain/keyimport/HkpKeyserver.java | 10 +++++----- .../keychain/pgp/CanonicalizedSecretKeyRing.java | 1 - .../sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 4 +--- .../keychain/provider/ProviderHelper.java | 10 +++++----- .../keychain/provider/TemporaryStorageProvider.java | 1 + .../keychain/remote/ui/AccountSettingsFragment.java | 2 +- .../keychain/service/ContactSyncAdapterService.java | 8 +++++++- .../keychain/service/DummyAccountService.java | 1 + .../keychain/service/KeychainIntentService.java | 5 +---- .../keychain/service/PassphraseCacheService.java | 3 +-- .../keychain/service/SaveKeyringParcel.java | 3 --- .../keychain/ui/CreateKeyFinalFragment.java | 2 -- .../org/sufficientlysecure/keychain/ui/DecryptActivity.java | 1 + .../sufficientlysecure/keychain/ui/DecryptFileFragment.java | 4 +--- .../org/sufficientlysecure/keychain/ui/DecryptFragment.java | 2 +- .../org/sufficientlysecure/keychain/ui/DrawerActivity.java | 2 +- .../org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 3 +-- .../sufficientlysecure/keychain/ui/EncryptFileFragment.java | 1 + .../keychain/ui/EncryptMessageFragment.java | 1 + .../sufficientlysecure/keychain/ui/ImportKeysActivity.java | 2 +- .../org/sufficientlysecure/keychain/ui/KeyListFragment.java | 2 +- .../sufficientlysecure/keychain/ui/LogDisplayFragment.java | 2 -- .../sufficientlysecure/keychain/ui/ViewCertActivity.java | 2 +- .../org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 3 +-- .../keychain/ui/ViewKeyShareFragment.java | 1 - .../keychain/ui/adapter/ImportKeysListLoader.java | 1 - .../keychain/ui/adapter/PagerTabStripAdapter.java | 5 ----- .../keychain/ui/dialog/AddSubkeyDialogFragment.java | 2 -- .../keychain/ui/dialog/AddUserIdDialogFragment.java | 1 - .../keychain/ui/dialog/DeleteFileDialogFragment.java | 3 +-- .../keychain/ui/dialog/FileDialogFragment.java | 1 + .../keychain/ui/dialog/SetPassphraseDialogFragment.java | 1 - .../keychain/ui/widget/EncryptKeyCompletionView.java | 2 ++ .../keychain/ui/widget/FoldableLinearLayout.java | 2 +- 41 files changed, 64 insertions(+), 66 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index df39efeb0..d19233b3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -17,7 +17,6 @@ package org.sufficientlysecure.keychain; -import android.os.Build; import android.os.Environment; import org.spongycastle.bcpg.CompressionAlgorithmTags; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 181470757..95f9425ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -32,7 +32,6 @@ import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; -import java.security.Provider; import java.security.Security; public class KeychainApplication extends Application { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 1d8661bfe..8697e49f7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -19,7 +19,10 @@ package org.sufficientlysecure.keychain.helper; import android.accounts.Account; import android.accounts.AccountManager; -import android.content.*; +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; @@ -36,7 +39,13 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; import java.io.InputStream; -import java.util.*; +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 { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java index 7cd4f6710..d8efdc480 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/EmailKeyHelper.java @@ -21,6 +21,7 @@ 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; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java index ae9438148..bcd57b290 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java @@ -35,7 +35,6 @@ 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.ui.dialog.FileDialogFragment; import org.sufficientlysecure.keychain.util.Log; import java.io.File; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index 1b36ba3fc..b640ecb03 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -26,14 +26,17 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Point; import android.net.Uri; -import android.os.*; +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.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java index 4b09af04d..8bbe73676 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/TlsHelper.java @@ -18,12 +18,10 @@ package org.sufficientlysecure.keychain.helper; import android.content.res.AssetManager; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.Log; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -34,10 +32,16 @@ import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; -import java.security.cert.*; +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 { 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 eb741fc45..f617be62a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -18,11 +18,6 @@ package org.sufficientlysecure.keychain.keyimport; -import de.measite.minidns.Client; -import de.measite.minidns.Question; -import de.measite.minidns.Record; -import de.measite.minidns.record.SRV; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.helper.TlsHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; @@ -45,6 +40,11 @@ import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.measite.minidns.Client; +import de.measite.minidns.Question; +import de.measite.minidns.Record; +import de.measite.minidns.record.SRV; + public class HkpKeyserver extends Keyserver { private static class HttpError extends Exception { private static final long serialVersionUID = 1718783705229428893L; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java index 812bf2fed..80889f70d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java @@ -23,7 +23,6 @@ import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; 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 af82495aa..18ddaa0ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -33,9 +33,9 @@ import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; +import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -44,11 +44,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.TreeSet; 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 e79771ed6..6111a4ef4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -28,17 +28,14 @@ import android.os.RemoteException; import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.NullProgressable; -import org.sufficientlysecure.keychain.pgp.Progressable; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; -import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; -import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; -import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.pgp.WrappedSignature; @@ -51,6 +48,9 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; +import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; +import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; +import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java index b8934b6c1..87c0cc0a6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -27,6 +27,7 @@ import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.provider.OpenableColumns; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.DatabaseUtil; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index 2ba792f9a..8468f5eca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -26,9 +26,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; -import android.widget.Button; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; 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 6c4d59a77..43ed2dad0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -23,7 +23,13 @@ import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; import android.content.Intent; import android.content.SyncResult; -import android.os.*; +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 org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.KeychainApplication; import org.sufficientlysecure.keychain.helper.ContactHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/DummyAccountService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/DummyAccountService.java index 008502ce7..41ff6d02b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/DummyAccountService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/DummyAccountService.java @@ -29,6 +29,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.widget.Toast; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; 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 19f7bc9bb..30108d52d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -24,7 +24,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.Message; import android.os.Messenger; -import android.os.Parcel; import android.os.RemoteException; import org.sufficientlysecure.keychain.Constants; @@ -32,7 +31,6 @@ 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.FileImportCache; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver; @@ -56,6 +54,7 @@ import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; +import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -63,11 +62,9 @@ import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; 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 7789ee064..e95e737d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -34,9 +34,8 @@ import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; - -import android.support.v4.util.LongSparseArray; import android.support.v4.app.NotificationCompat; +import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 442746feb..490a8e738 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -20,9 +20,6 @@ package org.sufficientlysecure.keychain.service; import android.os.Parcel; import android.os.Parcelable; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - import java.io.Serializable; import java.util.ArrayList; 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 de9c7f77d..773be816a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -33,8 +33,6 @@ import android.widget.TextView; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.openpgp.PGPPublicKey; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.pgp.KeyRing; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index e62591b1a..830b9a279 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -23,6 +23,7 @@ import android.net.Uri; import android.os.Bundle; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 51e90ea20..c33b1489a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -29,10 +29,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.ImageButton; - import android.widget.TextView; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; 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 16a7b911e..211a20ec8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -25,11 +25,11 @@ import android.os.Message; import android.support.v4.app.Fragment; import android.view.View; import android.view.View.OnClickListener; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; -import android.widget.Button; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.R; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java index 586442bb0..0e8d6f39d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java @@ -35,9 +35,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; -import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; 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 82206655f..5be196a45 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -37,7 +37,6 @@ import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast; -import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; @@ -59,8 +58,8 @@ import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index d412df0f4..8a9e17020 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -33,6 +33,7 @@ import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index e493ad066..6d753088b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -26,6 +26,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; + import org.sufficientlysecure.keychain.R; public class EncryptMessageFragment extends Fragment { 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 4a606a1b3..255290de3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -40,7 +40,6 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; @@ -49,6 +48,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; +import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; 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 28177c2ed..3c97b1128 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -47,10 +47,10 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; +import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; -import android.widget.Button; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 43de6774b..0e948bf7f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -41,9 +41,7 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogEntryPar import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.util.Log; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; public class LogDisplayFragment extends ListFragment implements OnTouchListener { 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 5201b5df8..341e11d1d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -34,8 +34,8 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; 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 e179115dc..28f7b8bf5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -42,7 +42,6 @@ import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -57,9 +56,9 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.OperationResultParcel; 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.ui.widget.SlidingTabLayout; import org.sufficientlysecure.keychain.util.Notify; import java.util.Date; 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 54ab76464..ae0bea5e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -49,7 +49,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 4971c535c..04947da93 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -33,7 +33,6 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; -import java.util.List; public class ImportKeysListLoader extends AsyncTaskLoader>> { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java index 3e3098b10..330254a8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java @@ -20,13 +20,8 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.app.FragmentTransaction; import android.support.v7.app.ActionBarActivity; -import android.view.ViewGroup; - -import org.sufficientlysecure.keychain.Constants; import java.util.ArrayList; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index 9841deeab..cb31978e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -43,8 +43,6 @@ import android.widget.TextView; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.openpgp.PGPPublicKey; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.util.Choice; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index 226bdf51e..4d6b13476 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -29,7 +29,6 @@ import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; import android.text.Editable; -import android.text.TextUtils; import android.text.TextWatcher; import android.util.Patterns; import android.view.KeyEvent; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index d408349d2..5f29f1d18 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -25,9 +25,8 @@ import android.os.Bundle; import android.provider.DocumentsContract; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; - import android.widget.Toast; -import org.sufficientlysecure.keychain.Constants; + import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java index 50f5ef7c0..18f134594 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java @@ -34,6 +34,7 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java index 1386ed098..5e2bec0e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java @@ -31,7 +31,6 @@ import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.view.WindowManager.LayoutParams; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.Button; 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 03b0d658f..7e762fe77 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 @@ -34,8 +34,10 @@ import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.TextView; + import com.tokenautocomplete.FilteredArrayAdapter; import com.tokenautocomplete.TokenCompleteTextView; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ContactHelper; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java index a29c17d37..31e01a7fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java @@ -24,9 +24,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.ImageButton; import org.sufficientlysecure.keychain.R; -- cgit v1.2.3 From e4974ac4097b7b92b51134942b01e9ab300222de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 23:50:59 +0200 Subject: Use CompressionAlgorithmTags instead of homebrew constants --- .../java/org/sufficientlysecure/keychain/Constants.java | 13 +------------ .../keychain/KeychainApplication.java | 2 +- .../sufficientlysecure/keychain/helper/Preferences.java | 13 ++++++++++--- .../sufficientlysecure/keychain/pgp/PgpSignEncrypt.java | 5 +++-- .../keychain/remote/AccountSettings.java | 3 ++- .../keychain/ui/PreferencesActivity.java | 17 +++++++++-------- .../keychain/util/AlgorithmNames.java | 9 +++++---- 7 files changed, 31 insertions(+), 31 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index d19233b3f..05676c5d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain; import android.os.Environment; -import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.sufficientlysecure.keychain.remote.ui.AppsListActivity; import org.sufficientlysecure.keychain.ui.DecryptActivity; @@ -50,7 +49,7 @@ public final class Constants { public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key"; - public static int TEMPFILE_TTL = 24*60*60*1000; // 1 day + public static int TEMPFILE_TTL = 24 * 60 * 60 * 1000; // 1 day public static final class Path { public static final File APP_DIR = new File(Environment.getExternalStorageDirectory(), "OpenKeychain"); @@ -90,16 +89,6 @@ public final class Constants { }; } - public static final class choice { - public static final class compression { - // TODO: legacy reasons :/ better: CompressionAlgorithmTags.UNCOMPRESSED - public static final int none = 0x21070001; - public static final int zlib = CompressionAlgorithmTags.ZLIB; - public static final int bzip2 = CompressionAlgorithmTags.BZIP2; - public static final int zip = CompressionAlgorithmTags.ZIP; - } - } - public static final class key { public static final int none = 0; public static final int symmetric = -1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 95f9425ed..9b9880533 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -84,7 +84,7 @@ public class KeychainApplication extends Application { setupAccountAsNeeded(this); // Update keyserver list as needed - Preferences.getPreferences(this).updateKeyServers(); + Preferences.getPreferences(this).updatePreferences(); TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index 5d765b663..00f6b6715 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.helper; import android.content.Context; import android.content.SharedPreferences; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; @@ -99,7 +100,7 @@ public class Preferences { public int getDefaultMessageCompression() { return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, - Constants.choice.compression.zlib); + CompressionAlgorithmTags.ZLIB); } public void setDefaultMessageCompression(int value) { @@ -110,7 +111,7 @@ public class Preferences { public int getDefaultFileCompression() { return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, - Constants.choice.compression.none); + CompressionAlgorithmTags.UNCOMPRESSED); } public void setDefaultFileCompression(int value) { @@ -180,7 +181,8 @@ public class Preferences { editor.commit(); } - public void updateKeyServers() { + public void updatePreferences() { + // migrate keyserver to hkps if (mSharedPreferences.getInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, 0) != Constants.Defaults.KEY_SERVERS_VERSION) { String[] servers = getKeyServers(); @@ -196,6 +198,11 @@ public class Preferences { .putInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, Constants.Defaults.KEY_SERVERS_VERSION) .commit(); } + + // migrate old uncompressed constant to new one + if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, 0) == 0x21070001) { + setDefaultFileCompression(CompressionAlgorithmTags.UNCOMPRESSED); + } } public void setConcealPgpApplication(boolean conceal) { 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 f0403e625..d8bf0d4d9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.BCPGOutputStream; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.openpgp.PGPCompressedDataGenerator; import org.spongycastle.openpgp.PGPEncryptedDataGenerator; import org.spongycastle.openpgp.PGPException; @@ -112,7 +113,7 @@ public class PgpSignEncrypt { // optional private Progressable mProgressable = null; private boolean mEnableAsciiArmorOutput = false; - private int mCompressionId = Constants.choice.compression.none; + private int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; private long[] mEncryptionMasterKeyIds = null; private String mSymmetricPassphrase = null; private int mSymmetricEncryptionAlgorithm = 0; @@ -242,7 +243,7 @@ public class PgpSignEncrypt { boolean enableSignature = mSignatureMasterKeyId != Constants.key.none; boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0) || mSymmetricPassphrase != null); - boolean enableCompression = (mCompressionId != Constants.choice.compression.none); + boolean enableCompression = (mCompressionId != CompressionAlgorithmTags.UNCOMPRESSED); Log.d(Constants.TAG, "enableSignature:" + enableSignature + "\nenableEncryption:" + enableEncryption diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java index a25ecded6..d6013b49d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/AccountSettings.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.remote; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; @@ -39,7 +40,7 @@ public class AccountSettings { // defaults: this.mEncryptionAlgorithm = PGPEncryptedData.AES_256; this.mHashAlgorithm = HashAlgorithmTags.SHA512; - this.mCompression = Constants.choice.compression.zlib; + this.mCompression = CompressionAlgorithmTags.ZLIB; } public String getAccountName() { 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 dcacdbc9d..e0261730d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java @@ -27,6 +27,7 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; @@ -88,10 +89,10 @@ public class PreferencesActivity extends PreferenceActivity { (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM)); int[] valueIds = new int[]{ - Constants.choice.compression.none, - Constants.choice.compression.zip, - Constants.choice.compression.zlib, - Constants.choice.compression.bzip2, + CompressionAlgorithmTags.UNCOMPRESSED, + CompressionAlgorithmTags.ZIP, + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2, }; String[] entries = new String[]{ getString(R.string.choice_none) + " (" + getString(R.string.compression_fast) + ")", @@ -232,10 +233,10 @@ public class PreferencesActivity extends PreferenceActivity { (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM)); int[] valueIds = new int[]{ - Constants.choice.compression.none, - Constants.choice.compression.zip, - Constants.choice.compression.zlib, - Constants.choice.compression.bzip2, + CompressionAlgorithmTags.UNCOMPRESSED, + CompressionAlgorithmTags.ZIP, + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2, }; String[] entries = new String[]{ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java index 2499f2571..9acc7a73b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.util; import android.annotation.SuppressLint; import android.app.Activity; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; @@ -57,13 +58,13 @@ public class AlgorithmNames { mHashNames.put(HashAlgorithmTags.SHA384, "SHA-384"); mHashNames.put(HashAlgorithmTags.SHA512, "SHA-512"); - mCompressionNames.put(Constants.choice.compression.none, mActivity.getString(R.string.choice_none) + mCompressionNames.put(CompressionAlgorithmTags.UNCOMPRESSED, mActivity.getString(R.string.choice_none) + " (" + mActivity.getString(R.string.compression_fast) + ")"); - mCompressionNames.put(Constants.choice.compression.zip, + mCompressionNames.put(CompressionAlgorithmTags.ZIP, "ZIP (" + mActivity.getString(R.string.compression_fast) + ")"); - mCompressionNames.put(Constants.choice.compression.zlib, + mCompressionNames.put(CompressionAlgorithmTags.ZLIB, "ZLIB (" + mActivity.getString(R.string.compression_fast) + ")"); - mCompressionNames.put(Constants.choice.compression.bzip2, + mCompressionNames.put(CompressionAlgorithmTags.BZIP2, "BZIP2 (" + mActivity.getString(R.string.compression_very_slow) + ")"); } -- cgit v1.2.3