aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java488
1 files changed, 186 insertions, 302 deletions
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 345e38a0e..8a9e17020 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
@@ -17,66 +17,50 @@
package org.sufficientlysecure.keychain.ui;
+import android.annotation.TargetApi;
import android.app.Activity;
-import android.app.ProgressDialog;
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.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.ImageButton;
-import android.widget.Spinner;
+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.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.FileDialogFragment;
-import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
-import org.sufficientlysecure.keychain.util.Choice;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Notify;
+import org.sufficientlysecure.keychain.helper.OtherHelper;
+import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
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 {
- public static final String ARG_FILENAME = "filename";
- public static final String ARG_ASCII_ARMOR = "ascii_armor";
+public class EncryptFileFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
+ public static final String ARG_URIS = "uris";
- private static final int REQUEST_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 CheckBox mDeleteAfter = null;
- private CheckBox mShareAfter = null;
- private ImageButton mBrowse = null;
+ private View mAddView;
+ private View mShareFile;
private View mEncryptFile;
-
- private FileDialogFragment mFileDialog;
-
- // model
- private String mInputFilename = null;
- private Uri mInputUri = null;
- private String mOutputFilename = null;
- private Uri mOutputUri = null;
+ private ListView mSelectedFiles;
+ private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter();
+ private final Map<Uri, Bitmap> thumbnailCache = new HashMap<Uri, Bitmap>();
@Override
public void onAttach(Activity activity) {
@@ -99,52 +83,27 @@ public class EncryptFileFragment extends Fragment {
mEncryptFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- encryptClicked();
+ encryptClicked(false);
}
});
-
- mFilename = (EditText) view.findViewById(R.id.filename);
- mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
- mBrowse.setOnClickListener(new View.OnClickListener() {
+ mShareFile = view.findViewById(R.id.action_encrypt_share);
+ mShareFile.setOnClickListener(new View.OnClickListener() {
+ @Override
public void onClick(View v) {
- if (Constants.KITKAT) {
- FileHelper.openDocument(EncryptFileFragment.this, mInputUri, "*/*", REQUEST_CODE_FILE);
- } else {
- FileHelper.openFile(EncryptFileFragment.this, mFilename.getText().toString(), "*/*",
- REQUEST_CODE_FILE);
- }
+ encryptClicked(true);
}
});
- 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<Choice> adapter = new ArrayAdapter<Choice>(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;
+ mAddView = inflater.inflate(R.layout.file_list_entry_add, null);
+ mAddView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ addInputUri();
}
- }
-
- 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());
+ });
+ mSelectedFiles = (ListView) view.findViewById(R.id.selected_files_list);
+ mSelectedFiles.addFooterView(mAddView);
+ mSelectedFiles.setAdapter(mAdapter);
return view;
}
@@ -153,267 +112,128 @@ 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);
- }
- boolean asciiArmor = getArguments().getBoolean(ARG_ASCII_ARMOR);
- if (asciiArmor) {
- mAsciiArmor.setChecked(asciiArmor);
- }
+ addInputUris(getArguments().<Uri>getParcelableArrayList(ARG_URIS));
}
- /**
- * 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;
-
- return outputFilename;
+ private void addInputUri() {
+ 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() ?
+ null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1),
+ "*/*", REQUEST_CODE_INPUT);
+ }
}
- 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();
- }
+ private void addInputUris(List<Uri> uris) {
+ if (uris != null) {
+ for (Uri uri : uris) {
+ addInputUri(uri);
}
- };
-
- // 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");
- }
-
- 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("")) {
- Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR);
+ private void addInputUri(Uri inputUri) {
+ if (inputUri == null) {
return;
}
- if (mInputUri == null && !mInputFilename.startsWith("content")) {
- File file = new File(mInputFilename);
- if (!file.exists() || !file.isFile()) {
- Notify.showNotify(
- getActivity(),
- getString(R.string.error_message,
- getString(R.string.error_file_not_found)), Notify.Style.ERROR
- );
- return;
- }
- }
+ mEncryptInterface.getInputUris().add(inputUri);
+ mEncryptInterface.notifyUpdate();
+ mSelectedFiles.requestFocus();
- if (mEncryptInterface.isModeSymmetric()) {
- // symmetric encryption
+ /**
+ * 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
+ */
- boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null
- && mEncryptInterface.getPassphrase().length() != 0);
- if (!gotPassphrase) {
- Notify.showNotify(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
- ;
- return;
- }
-
- if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) {
- Notify.showNotify(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR);
- return;
- }
+ if (mEncryptInterface.getInputUris().size() > 1) {
+ mEncryptFile.setVisibility(View.GONE);
} else {
- // asymmetric encryption
-
- boolean gotEncryptionKeys = (mEncryptInterface.getEncryptionKeys() != null
- && mEncryptInterface.getEncryptionKeys().length > 0);
-
- if (!gotEncryptionKeys) {
- Notify.showNotify(getActivity(), R.string.select_encryption_key, Notify.Style.ERROR);
- return;
- }
-
- if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) {
- Notify.showNotify(getActivity(), R.string.select_encryption_or_signature_key,
- Notify.Style.ERROR);
- 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;
- }
+ mEncryptFile.setVisibility(View.VISIBLE);
}
-
- showOutputFileDialog();
}
- private void encryptStart() {
- // 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);
+ private void delInputUri(int position) {
+ mEncryptInterface.getInputUris().remove(position);
+ mEncryptInterface.notifyUpdate();
+ mSelectedFiles.requestFocus();
- // fill values for this action
- Bundle data = new Bundle();
-
- Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename="
- + mOutputFilename + ",mInputUri=" + mInputUri + ", mOutputUri="
- + mOutputUri);
-
- if (mInputUri != null) {
- data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI);
- data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri);
+ if (mEncryptInterface.getInputUris().size() > 1) {
+ mEncryptFile.setVisibility(View.GONE);
} else {
- data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_FILE);
- data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename);
+ mEncryptFile.setVisibility(View.VISIBLE);
}
+ }
- if (mOutputUri != null) {
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI);
- data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri);
+ private void showOutputFileDialog() {
+ if (mEncryptInterface.getInputUris().size() > 1 || mEncryptInterface.getInputUris().isEmpty()) {
+ throw new IllegalStateException();
+ }
+ Uri inputUri = mEncryptInterface.getInputUris().get(0);
+ 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) +
+ (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 {
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_FILE);
- data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename);
+ FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), inputUri) +
+ (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT);
}
+ }
- if (mEncryptInterface.isModeSymmetric()) {
- Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mEncryptInterface.getPassphrase();
- if (passphrase.length() == 0) {
- passphrase = null;
+ private void encryptClicked(boolean share) {
+ if (share) {
+ mEncryptInterface.getOutputUris().clear();
+ for (Uri uri : mEncryptInterface.getInputUris()) {
+ String targetName = FileHelper.getFilename(getActivity(), uri) +
+ (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg");
+ mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName));
}
- 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());
+ mEncryptInterface.startEncrypt(true);
+ } else if (mEncryptInterface.getInputUris().size() == 1) {
+ showOutputFileDialog();
}
+ }
- boolean useAsciiArmor = mAsciiArmor.isChecked();
- data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, useAsciiArmor);
-
- 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) {
- Notify.showNotify(getActivity(), R.string.encrypt_sign_successful,
- Notify.Style.INFO);
-
- 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);
- }
- deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
- }
-
- 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));
- }
- startActivity(Intent.createChooser(sendFileIntent,
- getString(R.string.title_share_file)));
- }
- }
+ @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);
}
- };
-
- // 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);
+ return true;
+ }
+ return false;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
- case REQUEST_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!");
- }
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.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;
+ }
default: {
super.onActivityResult(requestCode, resultCode, data);
@@ -422,4 +242,68 @@ public class EncryptFileFragment extends Fragment {
}
}
}
+
+ @Override
+ public void onNotifyUpdate() {
+ // Clear cache if needed
+ for (Uri uri : new HashSet<Uri>(thumbnailCache.keySet())) {
+ if (!mEncryptInterface.getInputUris().contains(uri)) {
+ thumbnailCache.remove(uri);
+ }
+ }
+
+ mAdapter.notifyDataSetChanged();
+ }
+
+ private class SelectedFilesAdapter extends BaseAdapter {
+ @Override
+ public int getCount() {
+ return mEncryptInterface.getInputUris().size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mEncryptInterface.getInputUris().get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return getItem(position).hashCode();
+ }
+
+ @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(), inputUri));
+ long size = FileHelper.getFileSize(getActivity(), inputUri);
+ 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);
+ 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 {
+ ((ImageView) view.findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_doc_generic_am);
+ }
+ return view;
+ }
+ }
}