aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java13
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java26
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java6
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java11
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java969
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java14
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java283
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java415
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java289
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java96
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml3
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/encrypt_asymmetric_fragment.xml4
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/encrypt_content.xml339
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/encrypt_file_fragment.xml8
-rw-r--r--OpenPGP-Keychain/src/main/res/values/strings.xml2
15 files changed, 1302 insertions, 1176 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index d6dad424e..046d80b72 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -22,23 +22,13 @@ import android.net.Uri;
import android.os.Bundle;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
import android.widget.Toast;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-import com.devspark.appmsg.AppMsg;
-
-import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
import org.sufficientlysecure.keychain.util.Log;
@@ -47,7 +37,6 @@ import java.util.regex.Matcher;
public class DecryptActivity extends DrawerActivity {
/* Intents */
- // without permission
public static final String ACTION_DECRYPT = Constants.INTENT_PREFIX + "DECRYPT";
/* EXTRA keys for input */
@@ -64,9 +53,7 @@ public class DecryptActivity extends DrawerActivity {
private static final int PAGER_TAB_MESSAGE = 0;
private static final int PAGER_TAB_FILE = 1;
-
private void initView() {
- // Pager
mViewPager = (ViewPager) findViewById(R.id.decrypt_pager);
mPagerTabStrip = (PagerTabStrip) findViewById(R.id.decrypt_pager_tab_strip);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java
index 069a5a584..a929047b8 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -49,20 +49,19 @@ import java.io.File;
public class DecryptFileFragment extends DecryptFragment {
public static final String ARG_FILENAME = "filename";
+ private static final int RESULT_CODE_FILE = 0x00007003;
+
+ // view
private EditText mFilename;
private CheckBox mDeleteAfter;
private BootstrapButton mBrowse;
private BootstrapButton mDecryptButton;
-
private String mInputFilename = null;
private String mOutputFilename = null;
private FileDialogFragment mFileDialog;
- private static final int RESULT_CODE_FILE = 0x00007003;
-
-
/**
* Inflate the layout for this fragment
*/
@@ -72,14 +71,14 @@ public class DecryptFileFragment extends DecryptFragment {
mFilename = (EditText) 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 = (BootstrapButton) view.findViewById(R.id.decrypt_file_action_decrypt);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FileHelper.openFile(DecryptFileFragment.this, mFilename.getText().toString(), "*/*",
RESULT_CODE_FILE);
}
});
- mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption);
- mDecryptButton = (BootstrapButton) view.findViewById(R.id.decrypt_file_action_decrypt);
mDecryptButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -87,12 +86,17 @@ public class DecryptFileFragment extends DecryptFragment {
}
});
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
String filename = getArguments().getString(ARG_FILENAME);
if (filename != null) {
mFilename.setText(filename);
}
-
- return view;
}
private void guessOutputFilename() {
@@ -193,14 +197,12 @@ public class DecryptFileFragment extends DecryptFragment {
// get returned data bundle
Bundle returnData = message.getData();
-
PgpDecryptVerifyResult decryptVerifyResult =
returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT);
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded());
} else {
-
if (mDeleteAfter.isChecked()) {
// Create and show dialog to delete original file
DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
@@ -208,13 +210,11 @@ public class DecryptFileFragment extends DecryptFragment {
deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
}
-
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
// display signature result in activity
onSignatureResult(signatureResult);
}
-
}
}
};
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 4c0c80742..fd7aef353 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -187,6 +187,10 @@ public class DecryptFragment extends Fragment {
}
}
+ /**
+ * Should be overridden by MessageFragment and FileFragment to start actual decryption
+ * @param passphrase
+ */
protected void decryptStart(String passphrase) {
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java
index 3a8aaec42..94034b356 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -50,7 +50,6 @@ public class DecryptMessageFragment extends DecryptFragment {
private BootstrapButton mDecryptButton;
private BootstrapButton mDecryptFromCLipboardButton;
-
/**
* Inflate the layout for this fragment
*/
@@ -61,14 +60,12 @@ public class DecryptMessageFragment extends DecryptFragment {
mMessage = (EditText) view.findViewById(R.id.message);
mDecryptButton = (BootstrapButton) view.findViewById(R.id.action_decrypt);
mDecryptFromCLipboardButton = (BootstrapButton) view.findViewById(R.id.action_decrypt_from_clipboard);
-
mDecryptButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
decryptStart(null);
}
});
-
mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -93,6 +90,7 @@ public class DecryptMessageFragment extends DecryptFragment {
private void decryptFromClipboard() {
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
+ // only decrypt if clipboard content is available and a pgp message or cleartext signature
if (clipboardText != null) {
Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText);
if (!matcher.matches()) {
@@ -146,14 +144,12 @@ public class DecryptMessageFragment extends DecryptFragment {
// get returned data bundle
Bundle returnData = message.getData();
-
PgpDecryptVerifyResult decryptVerifyResult =
returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT);
if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {
showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded());
} else {
-
AppMsg.makeText(getActivity(), R.string.decryption_successful,
AppMsg.STYLE_INFO).show();
@@ -162,13 +158,11 @@ public class DecryptMessageFragment extends DecryptFragment {
mMessage.setText(new String(decryptedMessage));
mMessage.setHorizontallyScrolling(false);
-
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
// display signature result in activity
onSignatureResult(signatureResult);
}
-
}
}
};
@@ -184,5 +178,4 @@ public class DecryptMessageFragment extends DecryptFragment {
getActivity().startService(intent);
}
-
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index cc8224f06..47c4347f6 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -17,49 +17,25 @@
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.view.View;
-import android.view.View.OnClickListener;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.*;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-import com.beardedhen.androidbootstrap.FontAwesomeText;
-import com.devspark.appmsg.AppMsg;
-import org.spongycastle.openpgp.PGPPublicKey;
-import org.spongycastle.openpgp.PGPPublicKeyRing;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
+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.Id;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
-import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.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.ui.adapter.PagerTabStripAdapter;
import org.sufficientlysecure.keychain.util.Log;
-import java.io.File;
-import java.util.Vector;
-
-public class EncryptActivity extends DrawerActivity {
+public class EncryptActivity extends DrawerActivity implements
+ EncryptSymmetricFragment.OnSymmetricKeySelection,
+ EncryptAsymmetricFragment.OnAsymmetricKeySelection,
+ EncryptActivityInterface {
/* Intents */
public static final String ACTION_ENCRYPT = Constants.INTENT_PREFIX + "ENCRYPT";
@@ -74,52 +50,100 @@ public class EncryptActivity extends DrawerActivity {
public static final String EXTRA_SIGNATURE_KEY_ID = "signature_key_id";
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryption_key_ids";
+ // view
+ ViewPager mViewPagerMode;
+ PagerTabStrip mPagerTabStripMode;
+ PagerTabStripAdapter mTabsAdapterMode;
+ ViewPager mViewPagerContent;
+ PagerTabStrip mPagerTabStripContent;
+ PagerTabStripAdapter mTabsAdapterContent;
+
+ // tabs
+ Bundle mAsymmetricFragmentBundle = new Bundle();
+ Bundle mSymmetricFragmentBundle = new Bundle();
+ Bundle mMessageFragmentBundle = new Bundle();
+ Bundle mFileFragmentBundle = new Bundle();
+ int mSwitchToMode = PAGER_MODE_ASYMMETRIC;
+ int mSwitchToContent = PAGER_CONTENT_MESSAGE;
+
+ private static final int PAGER_MODE_ASYMMETRIC = 0;
+ private static final int PAGER_MODE_SYMMETRIC = 1;
+ private static final int PAGER_CONTENT_MESSAGE = 0;
+ private static final int PAGER_CONTENT_FILE = 1;
+
+ // model
private long mEncryptionKeyIds[] = null;
+ private long mSigningKeyId = Id.key.none;
+ private String mPassphrase;
+ private String mPassphraseAgain;
- private EditText mMessage = null;
- private BootstrapButton mSelectKeysButton = null;
+ private boolean mAsciiArmorDemand = false;
+ private boolean mOverrideAsciiArmor = false;
- private CheckBox mSign = null;
- private TextView mMainUserId = null;
- private TextView mMainUserIdRest = null;
+ private boolean mGenerateSignature = false;
- private ViewFlipper mSource = null;
- private TextView mSourceLabel = null;
- private ImageView mSourcePrevious = null;
- private ImageView mSourceNext = null;
- private ViewFlipper mMode = null;
- private TextView mModeLabel = null;
- private ImageView mModePrevious = null;
- private ImageView mModeNext = null;
+ @Override
+ public void onSigningKeySelected(long signingKeyId) {
+ mSigningKeyId = signingKeyId;
+ }
- private int mEncryptTarget;
+ @Override
+ public void onEncryptionKeysSelected(long[] encryptionKeyIds) {
+ mEncryptionKeyIds = encryptionKeyIds;
+ }
- private EditText mPassphrase = null;
- private EditText mPassphraseAgain = null;
- private CheckBox mAsciiArmor = null;
- private Spinner mFileCompression = null;
+ @Override
+ public void onPassphraseUpdate(String passphrase) {
+ mPassphrase = passphrase;
+ }
- private EditText mFilename = null;
- private CheckBox mDeleteAfter = null;
- private CheckBox mShareAfter = null;
- private BootstrapButton mBrowse = null;
+ @Override
+ public void onPassphraseAgainUpdate(String passphrase) {
+ mPassphraseAgain = passphrase;
+ }
- private String mInputFilename = null;
- private String mOutputFilename = null;
+ @Override
+ public boolean isModeSymmetric() {
+ if (PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
- private boolean mAsciiArmorDemand = false;
- private boolean mOverrideAsciiArmor = false;
+ @Override
+ public long getSignatureKey() {
+ return mSigningKeyId;
+ }
- private boolean mGenerateSignature = false;
+ @Override
+ public long[] getEncryptionKeys() {
+ return mEncryptionKeyIds;
+ }
- private long mSecretKeyId = Id.key.none;
+ @Override
+ public String getPassphrase() {
+ return mPassphrase;
+ }
- private FileDialogFragment mFileDialog;
+ @Override
+ public String getPassphraseAgain() {
+ return mPassphraseAgain;
+ }
- private BootstrapButton mEncryptShare;
- private BootstrapButton mEncryptClipboard;
- private BootstrapButton mEncryptFile;
+
+ private void initView() {
+ mViewPagerMode = (ViewPager) findViewById(R.id.encrypt_pager_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);
+
+ mTabsAdapterMode = new PagerTabStripAdapter(this);
+ mViewPagerMode.setAdapter(mTabsAdapterMode);
+ mTabsAdapterContent = new PagerTabStripAdapter(this);
+ mViewPagerContent.setAdapter(mTabsAdapterContent);
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -137,11 +161,13 @@ public class EncryptActivity extends DrawerActivity {
// Handle intent actions
handleActions(getIntent());
- updateView();
- updateSource();
- updateMode();
+ mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class, mAsymmetricFragmentBundle, getString(R.string.label_asymmetric));
+ mTabsAdapterMode.addTab(EncryptSymmetricFragment.class, mSymmetricFragmentBundle, getString(R.string.label_symmetric));
+ mViewPagerMode.setCurrentItem(mSwitchToMode);
- updateActionBarButtons();
+ mTabsAdapterContent.addTab(EncryptMessageFragment.class, mMessageFragmentBundle, getString(R.string.label_message));
+ mTabsAdapterContent.addTab(EncryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file));
+ mViewPagerContent.setCurrentItem(mSwitchToContent);
}
/**
@@ -183,8 +209,7 @@ public class EncryptActivity extends DrawerActivity {
if (extras.containsKey(EXTRA_ASCII_ARMOR)) {
mAsciiArmorDemand = extras.getBoolean(EXTRA_ASCII_ARMOR, true);
- mOverrideAsciiArmor = true;
- mAsciiArmor.setChecked(mAsciiArmorDemand);
+ mFileFragmentBundle.putBoolean(EncryptFileFragment.ARG_ASCII_ARMOR, mAsciiArmorDemand);
}
String textData = extras.getString(EXTRA_TEXT);
@@ -193,20 +218,17 @@ public class EncryptActivity extends DrawerActivity {
long[] encryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
// preselect keys given by intent
- preselectKeys(signatureKeyId, encryptionKeyIds);
+ mAsymmetricFragmentBundle.putLongArray(EncryptAsymmetricFragment.ARG_ENCRYPTION_KEY_IDS, encryptionKeyIds);
+ mAsymmetricFragmentBundle.putLong(EncryptAsymmetricFragment.ARG_SIGNATURE_KEY_ID, signatureKeyId);
+ mSwitchToMode = PAGER_MODE_ASYMMETRIC;
/**
* Main Actions
*/
if (ACTION_ENCRYPT.equals(action) && textData != null) {
// encrypt text based on given extra
-
- mMessage.setText(textData);
- mSource.setInAnimation(null);
- mSource.setOutAnimation(null);
- while (mSource.getCurrentView().getId() != R.id.sourceMessage) {
- mSource.showNext();
- }
+ mMessageFragmentBundle.putString(EncryptMessageFragment.ARG_TEXT, textData);
+ mSwitchToContent = PAGER_CONTENT_MESSAGE;
} else if (ACTION_ENCRYPT.equals(action) && uri != null) {
// encrypt file based on Uri
@@ -214,14 +236,8 @@ public class EncryptActivity extends DrawerActivity {
String path = FileHelper.getPath(this, uri);
if (path != null) {
- mInputFilename = path;
- mFilename.setText(mInputFilename);
-
- mSource.setInAnimation(null);
- mSource.setOutAnimation(null);
- while (mSource.getCurrentView().getId() != R.id.sourceFile) {
- mSource.showNext();
- }
+ 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!");
@@ -236,740 +252,51 @@ public class EncryptActivity extends DrawerActivity {
}
}
- /**
- * If an Intent gives a signatureKeyId and/or encryptionKeyIds, preselect those!
- *
- * @param preselectedSignatureKeyId
- * @param preselectedEncryptionKeyIds
- */
- private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds) {
- if (preselectedSignatureKeyId != 0) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this,
- preselectedSignatureKeyId);
- PGPSecretKey masterKey = null;
- if (keyRing != null) {
- masterKey = PgpKeyHelper.getMasterKey(keyRing);
- if (masterKey != null) {
- Vector<PGPSecretKey> signKeys = PgpKeyHelper.getUsableSigningKeys(keyRing);
- if (signKeys.size() > 0) {
- mSecretKeyId = masterKey.getKeyID();
- }
- }
- }
- }
-
- if (preselectedEncryptionKeyIds != null) {
- Vector<Long> goodIds = new Vector<Long>();
- for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
- PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this,
- preselectedEncryptionKeyIds[i]);
- PGPPublicKey masterKey = null;
- if (keyRing == null) {
- continue;
- }
- masterKey = PgpKeyHelper.getMasterKey(keyRing);
- if (masterKey == null) {
- continue;
- }
- Vector<PGPPublicKey> encryptKeys = PgpKeyHelper.getUsableEncryptKeys(keyRing);
- if (encryptKeys.size() == 0) {
- continue;
- }
- goodIds.add(masterKey.getKeyID());
- }
- if (goodIds.size() > 0) {
- mEncryptionKeyIds = new long[goodIds.size()];
- for (int i = 0; i < goodIds.size(); ++i) {
- mEncryptionKeyIds[i] = goodIds.get(i);
- }
- }
- }
- }
-
- /**
- * 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 updateSource() {
- switch (mSource.getCurrentView().getId()) {
- case R.id.sourceFile: {
- mSourceLabel.setText(R.string.label_file);
- break;
- }
-
- case R.id.sourceMessage: {
- mSourceLabel.setText(R.string.label_message);
- break;
- }
-
- default: {
- break;
- }
- }
- updateActionBarButtons();
- }
-
- /**
- * Update ActionBar buttons based on current selection in view
- */
- private void updateActionBarButtons() {
- switch (mSource.getCurrentView().getId()) {
- case R.id.sourceFile: {
- mEncryptShare.setVisibility(View.GONE);
- mEncryptClipboard.setVisibility(View.GONE);
- mEncryptFile.setVisibility(View.VISIBLE);
- break;
- }
-
- case R.id.sourceMessage: {
- mSourceLabel.setText(R.string.label_message);
-
- mEncryptShare.setVisibility(View.VISIBLE);
- mEncryptClipboard.setVisibility(View.VISIBLE);
- mEncryptFile.setVisibility(View.GONE);
-
- if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
- mEncryptShare.setEnabled(true);
- mEncryptClipboard.setEnabled(true);
- } else {
- if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
- if (mSecretKeyId == 0) {
- mEncryptShare.setEnabled(false);
- mEncryptClipboard.setEnabled(false);
- } else {
- mEncryptShare.setEnabled(true);
- mEncryptClipboard.setEnabled(true);
- }
- } else {
- mEncryptShare.setEnabled(true);
- mEncryptClipboard.setEnabled(true);
- }
- }
- break;
- }
-
- default: {
- break;
- }
- }
-
- }
-
- private void updateMode() {
- switch (mMode.getCurrentView().getId()) {
- case R.id.modeAsymmetric: {
- mModeLabel.setText(R.string.label_asymmetric);
- break;
- }
-
- case R.id.modeSymmetric: {
- mModeLabel.setText(R.string.label_symmetric);
- break;
- }
-
- default: {
- break;
- }
- }
- updateActionBarButtons();
- }
-
- private void encryptToClipboardClicked() {
- mEncryptTarget = Id.target.clipboard;
- initiateEncryption();
- }
-
- private void encryptClicked() {
- Log.d(Constants.TAG, "encryptClicked invoked!");
-
- if (mSource.getCurrentView().getId() == R.id.sourceFile) {
- mEncryptTarget = Id.target.file;
- } else {
- mEncryptTarget = Id.target.email;
- }
- initiateEncryption();
- }
-
- private void initiateEncryption() {
- if (mEncryptTarget == Id.target.file) {
- String currentFilename = mFilename.getText().toString();
- if (mInputFilename == null || !mInputFilename.equals(currentFilename)) {
- mInputFilename = mFilename.getText().toString();
- }
-
- mOutputFilename = guessOutputFilename(mInputFilename);
-
- if (mInputFilename.equals("")) {
- AppMsg.makeText(this, R.string.no_file_selected, AppMsg.STYLE_ALERT).show();
- return;
- }
-
- if (!mInputFilename.startsWith("content")) {
- File file = new File(mInputFilename);
- if (!file.exists() || !file.isFile()) {
- AppMsg.makeText(
- this,
- getString(R.string.error_message,
- getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT)
- .show();
- return;
- }
- }
- }
-
- // symmetric encryption
- if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
- boolean gotPassPhrase = false;
- String passphrase = mPassphrase.getText().toString();
- String passphraseAgain = mPassphraseAgain.getText().toString();
- if (!passphrase.equals(passphraseAgain)) {
- AppMsg.makeText(this, R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show();
- return;
- }
-
- gotPassPhrase = (passphrase.length() != 0);
- if (!gotPassPhrase) {
- AppMsg.makeText(this, R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT)
- .show();
- return;
- }
- } else {
- boolean encryptIt = (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0);
- // for now require at least one form of encryption for files
- if (!encryptIt && mEncryptTarget == Id.target.file) {
- AppMsg.makeText(this, R.string.select_encryption_key, AppMsg.STYLE_ALERT).show();
- return;
- }
-
- if (!encryptIt && mSecretKeyId == 0) {
- AppMsg.makeText(this, R.string.select_encryption_or_signature_key,
- AppMsg.STYLE_ALERT).show();
- return;
- }
-
- if (mSecretKeyId != 0
- && PassphraseCacheService.getCachedPassphrase(this, mSecretKeyId) == null) {
- showPassphraseDialog();
-
- return;
- }
- }
-
- if (mEncryptTarget == Id.target.file) {
- showOutputFileDialog();
- } else {
- encryptStart();
- }
- }
-
- /**
- * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
- * encryption
- */
- private void showPassphraseDialog() {
- // Message is received after passphrase is cached
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- if (mEncryptTarget == Id.target.file) {
- showOutputFileDialog();
- } else {
- encryptStart();
- }
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(returnHandler);
-
- try {
- PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
- EncryptActivity.this, messenger, mSecretKeyId);
-
- passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpGeneralException e) {
- Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
- // send message to handler to start encryption directly
- returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
- }
- }
-
- 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();
- 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(getSupportFragmentManager(), "fileDialog");
- }
-
- private void encryptStart() {
- // Send all information needed to service to edit key in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
-
- // fill values for this action
- Bundle data = new Bundle();
-
- boolean useAsciiArmor = true;
- long encryptionKeyIds[] = null;
- int compressionId = 0;
- boolean signOnly = false;
- long mSecretKeyIdToPass = 0;
-
- if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
- Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mPassphrase.getText().toString();
- if (passphrase.length() == 0) {
- passphrase = null;
- }
- data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passphrase);
- } else {
- mSecretKeyIdToPass = mSecretKeyId;
- encryptionKeyIds = mEncryptionKeyIds;
- signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
- }
-
- intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN);
- // choose default settings, target and data bundle by target
- if (mEncryptTarget == Id.target.file) {
- useAsciiArmor = mAsciiArmor.isChecked();
- compressionId = ((Choice) mFileCompression.getSelectedItem()).getId();
-
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI);
-
- Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename="
- + mOutputFilename);
-
- data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename);
- data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename);
-
- } else {
- useAsciiArmor = true;
- compressionId = Preferences.getPreferences(this).getDefaultMessageCompression();
-
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
-
- String message = mMessage.getText().toString();
- if (signOnly) {
- message = fixBadCharactersForGmail(message);
- }
- data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, message.getBytes());
- }
-
- if (mOverrideAsciiArmor) {
- useAsciiArmor = mAsciiArmorDemand;
- }
-
- data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyIdToPass);
- data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, useAsciiArmor);
- data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
- data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
- data.putBoolean(KeychainIntentService.ENCRYPT_GENERATE_SIGNATURE, mGenerateSignature);
- data.putBoolean(KeychainIntentService.ENCRYPT_SIGN_ONLY, signOnly);
-
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after encrypting is done in KeychainIntentService
- KeychainIntentServiceHandler saveHandler = 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) {
- // get returned data bundle
- Bundle data = message.getData();
-
- String output;
- switch (mEncryptTarget) {
- case Id.target.clipboard:
- output = data.getString(KeychainIntentService.RESULT_ENCRYPTED_STRING);
- Log.d(Constants.TAG, "output: " + output);
- ClipboardReflection.copyToClipboard(EncryptActivity.this, output);
- AppMsg.makeText(EncryptActivity.this,
- R.string.encryption_to_clipboard_successful, AppMsg.STYLE_INFO)
- .show();
- break;
-
- case Id.target.email:
-
- output = data.getString(KeychainIntentService.RESULT_ENCRYPTED_STRING);
- Log.d(Constants.TAG, "output: " + output);
-
- 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");
-
- sendIntent.putExtra(Intent.EXTRA_TEXT, output);
- startActivity(Intent.createChooser(sendIntent,
- getString(R.string.title_send_email)));
- break;
-
- case Id.target.file:
- AppMsg.makeText(EncryptActivity.this, R.string.encryption_successful,
- AppMsg.STYLE_INFO).show();
-
- if (mDeleteAfter.isChecked()) {
- // Create and show dialog to delete original file
- DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
- .newInstance(mInputFilename);
- deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
- }
-
- if (mShareAfter.isChecked()) {
- // Share encrypted file
- Intent sendFileIntent = new Intent(Intent.ACTION_SEND);
- sendFileIntent.setType("*/*");
- sendFileIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(mOutputFilename));
- startActivity(Intent.createChooser(sendFileIntent,
- getString(R.string.title_send_file)));
- }
- break;
-
- default:
- // shouldn't happen
- break;
-
- }
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- // show progress dialog
- saveHandler.showProgressDialog(this);
-
- // start service with intent
- startService(intent);
- }
-
- /**
- * Fixes bad message characters for gmail
- *
- * @param message
- * @return
- */
- private String fixBadCharactersForGmail(String message) {
- // fix the message a bit, trailing spaces and newlines break stuff,
- // because GMail sends as HTML and such things fuck up the
- // signature,
- // TODO: things like "<" and ">" also fuck up the signature
- message = message.replaceAll(" +\n", "\n");
- message = message.replaceAll("\n\n+", "\n\n");
- message = message.replaceFirst("^\n+", "");
- // make sure there'll be exactly one newline at the end
- message = message.replaceFirst("\n*$", "\n");
-
- return message;
- }
-
- private void initView() {
- mSource = (ViewFlipper) findViewById(R.id.source);
- mSourceLabel = (TextView) findViewById(R.id.sourceLabel);
- mSourcePrevious = (ImageView) findViewById(R.id.sourcePrevious);
- mSourceNext = (ImageView) findViewById(R.id.sourceNext);
-
- mSourcePrevious.setClickable(true);
- mSourcePrevious.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mSource.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_right_in));
- mSource.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_right_out));
- mSource.showPrevious();
- updateSource();
- }
- });
-
- mSourceNext.setClickable(true);
- OnClickListener nextSourceClickListener = new OnClickListener() {
- public void onClick(View v) {
- mSource.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_left_in));
- mSource.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_left_out));
- mSource.showNext();
- updateSource();
- }
- };
- mSourceNext.setOnClickListener(nextSourceClickListener);
-
- mSourceLabel.setClickable(true);
- mSourceLabel.setOnClickListener(nextSourceClickListener);
-
- mMode = (ViewFlipper) findViewById(R.id.mode);
- mModeLabel = (TextView) findViewById(R.id.modeLabel);
- mModePrevious = (ImageView) findViewById(R.id.modePrevious);
- mModeNext = (ImageView) findViewById(R.id.modeNext);
-
- mModePrevious.setClickable(true);
- mModePrevious.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mMode.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_right_in));
- mMode.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_right_out));
- mMode.showPrevious();
- updateMode();
- }
- });
-
- OnClickListener nextModeClickListener = new OnClickListener() {
- public void onClick(View v) {
- mMode.setInAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_left_in));
- mMode.setOutAnimation(AnimationUtils.loadAnimation(EncryptActivity.this,
- R.anim.push_left_out));
- mMode.showNext();
- updateMode();
- }
- };
- mModeNext.setOnClickListener(nextModeClickListener);
-
- mModeLabel.setClickable(true);
- mModeLabel.setOnClickListener(nextModeClickListener);
-
- mMessage = (EditText) findViewById(R.id.message);
- mSelectKeysButton = (BootstrapButton) findViewById(R.id.btn_selectEncryptKeys);
- mSign = (CheckBox) findViewById(R.id.sign);
- mMainUserId = (TextView) findViewById(R.id.mainUserId);
- mMainUserIdRest = (TextView) findViewById(R.id.mainUserIdRest);
-
- mPassphrase = (EditText) findViewById(R.id.passphrase);
- mPassphraseAgain = (EditText) findViewById(R.id.passphraseAgain);
-
- // measure the height of the source_file view and set the message view's min height to that,
- // so it fills mSource fully... bit of a hack.
- View tmp = findViewById(R.id.sourceFile);
- tmp.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- int height = tmp.getMeasuredHeight();
- mMessage.setMinimumHeight(height);
-
- mFilename = (EditText) findViewById(R.id.filename);
- mBrowse = (BootstrapButton) findViewById(R.id.btn_browse);
- mBrowse.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- FileHelper.openFile(EncryptActivity.this, mFilename.getText().toString(), "*/*",
- Id.request.filename);
- }
- });
-
-
-
-
-
-
- mFileCompression = (Spinner) findViewById(R.id.fileCompression);
- Choice[] choices = new Choice[]{
- new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
- + getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.zip, "ZIP ("
- + getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.zlib, "ZLIB ("
- + getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.bzip2, "BZIP2 ("
- + getString(R.string.compression_very_slow) + ")"), };
- ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
- android.R.layout.simple_spinner_item, choices);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mFileCompression.setAdapter(adapter);
-
- int defaultFileCompression = Preferences.getPreferences(this).getDefaultFileCompression();
- for (int i = 0; i < choices.length; ++i) {
- if (choices[i].getId() == defaultFileCompression) {
- mFileCompression.setSelection(i);
- break;
- }
- }
-
- mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterEncryption);
- mShareAfter = (CheckBox) findViewById(R.id.shareAfterEncryption);
-
- mAsciiArmor = (CheckBox) findViewById(R.id.asciiArmour);
- mAsciiArmor.setChecked(Preferences.getPreferences(this).getDefaultAsciiArmour());
-
- mSelectKeysButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- selectPublicKeys();
- }
- });
-
- mSign.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- CheckBox checkBox = (CheckBox) v;
- if (checkBox.isChecked()) {
- selectSecretKey();
- } else {
- mSecretKeyId = Id.key.none;
- updateView();
- }
- }
- });
-
- mEncryptClipboard = (BootstrapButton) findViewById(R.id.action_encrypt_clipboard);
- mEncryptClipboard.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- encryptToClipboardClicked();
- }
- });
- mEncryptShare = (BootstrapButton) findViewById(R.id.action_encrypt_share);
- mEncryptShare.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- encryptClicked();
- }
- });
- mEncryptFile = (BootstrapButton) findViewById(R.id.action_encrypt_file);
- mEncryptFile.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- encryptClicked();
- }
- });
- }
-
- 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 == Id.key.none) {
- mSign.setChecked(false);
- mMainUserId.setText("");
- mMainUserIdRest.setText("");
- } else {
- String uid = getResources().getString(R.string.user_id_no_name);
- String uidExtra = "";
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this,
- mSecretKeyId);
- if (keyRing != null) {
- PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
- if (key != null) {
- String userId = PgpKeyHelper.getMainUserIdSafe(this, key);
- String chunks[] = userId.split(" <", 2);
- uid = chunks[0];
- if (chunks.length > 1) {
- uidExtra = "<" + chunks[1];
- }
- }
- }
- mMainUserId.setText(uid);
- mMainUserIdRest.setText(uidExtra);
- mSign.setChecked(true);
- }
-
- updateActionBarButtons();
- }
-
- private void selectPublicKeys() {
- Intent intent = new Intent(this, SelectPublicKeyActivity.class);
- Vector<Long> keyIds = new Vector<Long>();
- if (mSecretKeyId != 0) {
- keyIds.add(mSecretKeyId);
- }
- if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) {
- for (int i = 0; i < mEncryptionKeyIds.length; ++i) {
- keyIds.add(mEncryptionKeyIds[i]);
- }
- }
- 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);
- }
- }
- intent.putExtra(SelectPublicKeyActivity.EXTRA_SELECTED_MASTER_KEY_IDS, initialKeyIds);
- startActivityForResult(intent, Id.request.public_keys);
- }
-
- private void selectSecretKey() {
- Intent intent = new Intent(this, SelectSecretKeyActivity.class);
- startActivityForResult(intent, Id.request.secret_keys);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case Id.request.filename: {
- if (resultCode == RESULT_OK && data != null) {
- try {
- String path = FileHelper.getPath(this, data.getData());
- Log.d(Constants.TAG, "path=" + path);
-
- mFilename.setText(path);
- } catch (NullPointerException e) {
- Log.e(Constants.TAG, "Nullpointer while retrieving path!");
- }
- }
- return;
- }
-
- case Id.request.public_keys: {
- if (resultCode == RESULT_OK) {
- Bundle bundle = data.getExtras();
- mEncryptionKeyIds = bundle
- .getLongArray(SelectPublicKeyActivity.RESULT_EXTRA_MASTER_KEY_IDS);
- }
- updateView();
- break;
- }
-
- case Id.request.secret_keys: {
- if (resultCode == RESULT_OK) {
- Uri uri_master_key = data.getData();
- mSecretKeyId = Long.valueOf(uri_master_key.getLastPathSegment());
- } else {
- mSecretKeyId = Id.key.none;
- }
- updateView();
- break;
- }
-
- default: {
- break;
- }
- }
-
- super.onActivityResult(requestCode, resultCode, data);
- }
+// /**
+// * Update ActionBar buttons based on current selection in view
+// */
+// private void updateActionBarButtons() {
+// switch (mSource.getCurrentView().getId()) {
+// case R.id.sourceFile: {
+// mEncryptShare.setVisibility(View.GONE);
+// mEncryptClipboard.setVisibility(View.GONE);
+// mEncryptFile.setVisibility(View.VISIBLE);
+// break;
+// }
+//
+// case R.id.sourceMessage: {
+// mSourceLabel.setText(R.string.label_message);
+//
+// mEncryptShare.setVisibility(View.VISIBLE);
+// mEncryptClipboard.setVisibility(View.VISIBLE);
+// mEncryptFile.setVisibility(View.GONE);
+//
+// if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
+// mEncryptShare.setEnabled(true);
+// mEncryptClipboard.setEnabled(true);
+// } else {
+// if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
+// if (mSecretKeyId == 0) {
+// mEncryptShare.setEnabled(false);
+// mEncryptClipboard.setEnabled(false);
+// } else {
+// mEncryptShare.setEnabled(true);
+// mEncryptClipboard.setEnabled(true);
+// }
+// } else {
+// mEncryptShare.setEnabled(true);
+// mEncryptClipboard.setEnabled(true);
+// }
+// }
+// break;
+// }
+//
+// default: {
+// break;
+// }
+// }
+//
+// }
}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
new file mode 100644
index 000000000..8fbabe9c0
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
@@ -0,0 +1,14 @@
+package org.sufficientlysecure.keychain.ui;
+
+
+public interface EncryptActivityInterface {
+
+ public boolean isModeSymmetric();
+
+ public long getSignatureKey();
+ public long[] getEncryptionKeys();
+
+ public String getPassphrase();
+ public String getPassphraseAgain();
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
new file mode 100644
index 000000000..b88dafd4a
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+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.CheckBox;
+import android.widget.TextView;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+
+import java.util.Vector;
+
+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";
+
+ public static final int RESULT_CODE_PUBLIC_KEYS = 0x00007001;
+ public static final int RESULT_CODE_SECRET_KEYS = 0x00007002;
+
+ OnAsymmetricKeySelection mKeySelectionListener;
+
+ // view
+ private BootstrapButton mSelectKeysButton;
+ private CheckBox mSign;
+ private TextView mMainUserId;
+ private TextView mMainUserIdRest;
+
+ // model
+ private long mSecretKeyId = Id.key.none;
+ private long mEncryptionKeyIds[] = null;
+
+ // Container Activity must implement this interface
+ public interface OnAsymmetricKeySelection {
+ public void onSigningKeySelected(long signingKeyId);
+
+ public void onEncryptionKeysSelected(long[] encryptionKeyIds);
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mKeySelectionListener = (OnAsymmetricKeySelection) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement OnAsymmetricKeySelection");
+ }
+ }
+
+ private void setSignatureKeyId(long signatureKeyId) {
+ mSecretKeyId = signatureKeyId;
+ mKeySelectionListener.onSigningKeySelected(signatureKeyId);
+ }
+
+ private void setEncryptionKeyIds(long[] encryptionKeyIds) {
+ mEncryptionKeyIds = encryptionKeyIds;
+ mKeySelectionListener.onEncryptionKeysSelected(encryptionKeyIds);
+ }
+
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false);
+
+ mSelectKeysButton = (BootstrapButton) 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;
+ if (checkBox.isChecked()) {
+ selectSecretKey();
+ } else {
+ setSignatureKeyId(Id.key.none);
+ updateView();
+ }
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ long signatureKeyId = getArguments().getLong(ARG_SIGNATURE_KEY_ID);
+ long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS);
+
+ // preselect keys given by arguments (given by Intent to EncryptActivity)
+ preselectKeys(signatureKeyId, encryptionKeyIds);
+ }
+
+ /**
+ * If an Intent gives a signatureKeyId and/or encryptionKeyIds, preselect those!
+ *
+ * @param preselectedSignatureKeyId
+ * @param preselectedEncryptionKeyIds
+ */
+ private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds) {
+ if (preselectedSignatureKeyId != 0) {
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(getActivity(),
+ preselectedSignatureKeyId);
+ PGPSecretKey masterKey;
+ if (keyRing != null) {
+ masterKey = PgpKeyHelper.getMasterKey(keyRing);
+ if (masterKey != null) {
+ Vector<PGPSecretKey> signKeys = PgpKeyHelper.getUsableSigningKeys(keyRing);
+ if (signKeys.size() > 0) {
+ setSignatureKeyId(masterKey.getKeyID());
+ }
+ }
+ }
+ }
+
+ if (preselectedEncryptionKeyIds != null) {
+ Vector<Long> goodIds = new Vector<Long>();
+ for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
+ PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(getActivity(),
+ preselectedEncryptionKeyIds[i]);
+ PGPPublicKey masterKey;
+ if (keyRing == null) {
+ continue;
+ }
+ masterKey = PgpKeyHelper.getMasterKey(keyRing);
+ if (masterKey == null) {
+ continue;
+ }
+ Vector<PGPPublicKey> encryptKeys = PgpKeyHelper.getUsableEncryptKeys(keyRing);
+ if (encryptKeys.size() == 0) {
+ continue;
+ }
+ goodIds.add(masterKey.getKeyID());
+ }
+ 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);
+ }
+ }
+ }
+
+ 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 == Id.key.none) {
+ mSign.setChecked(false);
+ mMainUserId.setText("");
+ mMainUserIdRest.setText("");
+ } else {
+ String uid = getResources().getString(R.string.user_id_no_name);
+ String uidExtra = "";
+ // TODO: make it nice and use helper!
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(getActivity(),
+ mSecretKeyId);
+ if (keyRing != null) {
+ PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
+ if (key != null) {
+ String userId = PgpKeyHelper.getMainUserIdSafe(getActivity(), key);
+ String chunks[] = userId.split(" <", 2);
+ uid = chunks[0];
+ if (chunks.length > 1) {
+ uidExtra = "<" + chunks[1];
+ }
+ }
+ }
+ mMainUserId.setText(uid);
+ mMainUserIdRest.setText(uidExtra);
+ mSign.setChecked(true);
+ }
+
+//TODO
+// updateActionBarButtons();
+ }
+
+ private void selectPublicKeys() {
+ Intent intent = new Intent(getActivity(), SelectPublicKeyActivity.class);
+ Vector<Long> keyIds = new Vector<Long>();
+ if (mSecretKeyId != 0) {
+ keyIds.add(mSecretKeyId);
+ }
+ if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) {
+ for (int i = 0; i < mEncryptionKeyIds.length; ++i) {
+ keyIds.add(mEncryptionKeyIds[i]);
+ }
+ }
+ 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);
+ }
+ }
+ intent.putExtra(SelectPublicKeyActivity.EXTRA_SELECTED_MASTER_KEY_IDS, initialKeyIds);
+ startActivityForResult(intent, Id.request.public_keys);
+ }
+
+ private void selectSecretKey() {
+ Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class);
+ startActivityForResult(intent, Id.request.secret_keys);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+
+ case RESULT_CODE_PUBLIC_KEYS: {
+ if (resultCode == Activity.RESULT_OK) {
+ Bundle bundle = data.getExtras();
+ setEncryptionKeyIds(bundle
+ .getLongArray(SelectPublicKeyActivity.RESULT_EXTRA_MASTER_KEY_IDS));
+ }
+ updateView();
+ break;
+ }
+
+ case RESULT_CODE_SECRET_KEYS: {
+ if (resultCode == Activity.RESULT_OK) {
+ Uri uri_master_key = data.getData();
+ setSignatureKeyId(Long.valueOf(uri_master_key.getLastPathSegment()));
+ } else {
+ setSignatureKeyId(Id.key.none);
+ }
+ updateView();
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
new file mode 100644
index 000000000..734941ca7
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+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.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 com.beardedhen.androidbootstrap.BootstrapButton;
+import com.devspark.appmsg.AppMsg;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.FileHelper;
+import org.sufficientlysecure.keychain.helper.Preferences;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+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 java.io.File;
+
+public class EncryptFileFragment extends Fragment {
+ public static final String ARG_FILENAME = "filename";
+ public static final String ARG_ASCII_ARMOR = "ascii_armor";
+
+ private static final int RESULT_CODE_FILE = 0x00007003;
+
+ 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 BootstrapButton mBrowse = null;
+ private BootstrapButton mEncryptFile;
+
+ private FileDialogFragment mFileDialog;
+
+ // model
+ private String mInputFilename = null;
+ private String mOutputFilename = null;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mEncryptInterface = (EncryptActivityInterface) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface");
+ }
+ }
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.encrypt_file_fragment, container, false);
+
+ mEncryptFile = (BootstrapButton) view.findViewById(R.id.action_encrypt_file);
+ mEncryptFile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ encryptClicked();
+ }
+ });
+
+ mFilename = (EditText) view.findViewById(R.id.filename);
+ mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse);
+ mBrowse.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ FileHelper.openFile(EncryptFileFragment.this, mFilename.getText().toString(), "*/*",
+ Id.request.filename);
+ }
+ });
+
+ mFileCompression = (Spinner) view.findViewById(R.id.fileCompression);
+ Choice[] choices = new Choice[]{
+ new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
+ + getString(R.string.compression_fast) + ")"),
+ new Choice(Id.choice.compression.zip, "ZIP ("
+ + getString(R.string.compression_fast) + ")"),
+ new Choice(Id.choice.compression.zlib, "ZLIB ("
+ + getString(R.string.compression_fast) + ")"),
+ new Choice(Id.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;
+ }
+ }
+
+ mDeleteAfter = (CheckBox) view.findViewById(R.id.deleteAfterEncryption);
+ mShareAfter = (CheckBox) view.findViewById(R.id.shareAfterEncryption);
+
+ mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmour);
+ mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmour());
+
+ return view;
+ }
+
+ @Override
+ 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);
+ }
+ }
+
+ /**
+ * 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 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();
+ 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");
+ }
+
+ private void encryptClicked() {
+ String currentFilename = mFilename.getText().toString();
+ if (mInputFilename == null || !mInputFilename.equals(currentFilename)) {
+ mInputFilename = mFilename.getText().toString();
+ }
+
+ mOutputFilename = guessOutputFilename(mInputFilename);
+
+ if (mInputFilename.equals("")) {
+ AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show();
+ return;
+ }
+
+ if (!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
+
+ if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) {
+ AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show();
+ return;
+ }
+
+ boolean gotPassPhrase = (mEncryptInterface.getPassphrase().length() != 0);
+ if (!gotPassPhrase) {
+ AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT)
+ .show();
+ return;
+ }
+ } else {
+ // asymmetric encryption
+
+ boolean encryptIt = (mEncryptInterface.getEncryptionKeys() != null
+ && mEncryptInterface.getEncryptionKeys().length > 0);
+ // for now require at least one form of encryption for files
+ if (!encryptIt) {
+ AppMsg.makeText(getActivity(), R.string.select_encryption_key, AppMsg.STYLE_ALERT).show();
+ return;
+ }
+
+ if (!encryptIt && 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) {
+ showPassphraseDialog();
+
+ return;
+ }
+ }
+
+ showOutputFileDialog();
+ }
+
+ private void encryptStart() {
+ // Send all information needed to service to edit key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ boolean useAsciiArmor = true;
+ long encryptionKeyIds[] = null;
+ int compressionId = 0;
+ boolean signOnly = false;
+ long mSecretKeyIdToPass = 0;
+
+ if (mEncryptInterface.isModeSymmetric()) {
+ Log.d(Constants.TAG, "Symmetric encryption enabled!");
+ String passphrase = mEncryptInterface.getPassphrase();
+ if (passphrase.length() == 0) {
+ passphrase = null;
+ }
+ data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passphrase);
+ } else {
+ mSecretKeyIdToPass = mEncryptInterface.getSignatureKey();
+ encryptionKeyIds = mEncryptInterface.getEncryptionKeys();
+ signOnly = (mEncryptInterface.getEncryptionKeys() == null
+ || mEncryptInterface.getEncryptionKeys().length == 0);
+ }
+
+ intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN);
+
+ // choose default settings, target and data bundle by target
+ useAsciiArmor = mAsciiArmor.isChecked();
+ compressionId = ((Choice) mFileCompression.getSelectedItem()).getId();
+
+ data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI);
+
+ Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename="
+ + mOutputFilename);
+
+ data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename);
+ data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename);
+
+
+ data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyIdToPass);
+ data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, useAsciiArmor);
+ data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
+ data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
+// data.putBoolean(KeychainIntentService.ENCRYPT_GENERATE_SIGNATURE, mGenerateSignature);
+ data.putBoolean(KeychainIntentService.ENCRYPT_SIGN_ONLY, signOnly);
+
+ 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;
+ AppMsg.makeText(getActivity(), R.string.encryption_successful,
+ AppMsg.STYLE_INFO).show();
+
+ if (mDeleteAfter.isChecked()) {
+ // Create and show dialog to delete original file
+ DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
+ .newInstance(mInputFilename);
+ deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
+ }
+
+ if (mShareAfter.isChecked()) {
+ // Share encrypted file
+ Intent sendFileIntent = new Intent(Intent.ACTION_SEND);
+ sendFileIntent.setType("*/*");
+ sendFileIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(mOutputFilename));
+ startActivity(Intent.createChooser(sendFileIntent,
+ getString(R.string.title_send_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) {
+ case RESULT_CODE_FILE: {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ 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!");
+ }
+ }
+ return;
+ }
+
+ default: {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
+ * encryption
+ */
+ private void showPassphraseDialog() {
+ // Message is received after passphrase is cached
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ showOutputFileDialog();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ try {
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ getActivity(), messenger, mEncryptInterface.getSignatureKey());
+
+ passphraseDialog.show(getActivity().getSupportFragmentManager(), "passphraseDialog");
+ } catch (PgpGeneralException e) {
+ Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
+ // send message to handler to start encryption directly
+ returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ }
+ }
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java
new file mode 100644
index 000000000..7f1d7311d
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+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.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
+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.exception.PgpGeneralException;
+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;
+
+public class EncryptMessageFragment extends Fragment {
+ public static final String ARG_TEXT = "text";
+
+ private EditText mMessage = null;
+ private BootstrapButton mEncryptShare;
+ private BootstrapButton mEncryptClipboard;
+
+ private EncryptActivityInterface mEncryptInterface;
+
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mEncryptInterface = (EncryptActivityInterface) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface");
+ }
+ }
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.encrypt_message_fragment, container, false);
+
+ mMessage = (EditText) view.findViewById(R.id.message);
+ mEncryptClipboard = (BootstrapButton) view.findViewById(R.id.action_encrypt_clipboard);
+ mEncryptShare = (BootstrapButton) view.findViewById(R.id.action_encrypt_share);
+ mEncryptClipboard.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ encryptClicked(true);
+ }
+ });
+ mEncryptShare.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ encryptClicked(false);
+ }
+ });
+
+ return view;
+ }
+
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ String text = getArguments().getString(ARG_TEXT);
+ if (text != null) {
+ mMessage.setText(text);
+ }
+ }
+
+ /**
+ * Fixes bad message characters for gmail
+ *
+ * @param message
+ * @return
+ */
+ private String fixBadCharactersForGmail(String message) {
+ // fix the message a bit, trailing spaces and newlines break stuff,
+ // because GMail sends as HTML and such things fuck up the
+ // signature,
+ // TODO: things like "<" and ">" also fuck up the signature
+ message = message.replaceAll(" +\n", "\n");
+ message = message.replaceAll("\n\n+", "\n\n");
+ message = message.replaceFirst("^\n+", "");
+ // make sure there'll be exactly one newline at the end
+ message = message.replaceFirst("\n*$", "\n");
+
+ return message;
+ }
+
+ private void encryptClicked(boolean toClipboard) {
+ if (mEncryptInterface.isModeSymmetric()) {
+ // symmetric encryption
+
+ boolean gotPassPhrase = false;
+ if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) {
+ AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show();
+ return;
+ }
+
+ gotPassPhrase = (mEncryptInterface.getPassphrase().length() != 0);
+ if (!gotPassPhrase) {
+ AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT)
+ .show();
+ return;
+ }
+ } else {
+ // asymmetric encryption
+
+ boolean encryptIt = (mEncryptInterface.getEncryptionKeys() != null
+ && mEncryptInterface.getEncryptionKeys().length > 0);
+
+ if (!encryptIt && 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) {
+ showPassphraseDialog(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);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ long encryptionKeyIds[] = null;
+ int compressionId = 0;
+ boolean signOnly = false;
+ long mSecretKeyIdToPass = 0;
+
+ if (mEncryptInterface.isModeSymmetric()) {
+ Log.d(Constants.TAG, "Symmetric encryption enabled!");
+ String passphrase = mEncryptInterface.getPassphrase();
+ if (passphrase.length() == 0) {
+ passphrase = null;
+ }
+ data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passphrase);
+ } else {
+ mSecretKeyIdToPass = mEncryptInterface.getSignatureKey();
+ encryptionKeyIds = mEncryptInterface.getEncryptionKeys();
+ signOnly = (mEncryptInterface.getEncryptionKeys() == null
+ || mEncryptInterface.getEncryptionKeys().length == 0);
+ }
+
+ intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN);
+
+ // choose default settings, target and data bundle by target
+ compressionId = Preferences.getPreferences(getActivity()).getDefaultMessageCompression();
+
+ data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
+
+ String message = mMessage.getText().toString();
+ if (signOnly) {
+ message = fixBadCharactersForGmail(message);
+ }
+ data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, message.getBytes());
+
+ data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyIdToPass);
+ data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, true);
+ data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
+ data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
+// data.putBoolean(KeychainIntentService.ENCRYPT_GENERATE_SIGNATURE, mGenerateSignature);
+ data.putBoolean(KeychainIntentService.ENCRYPT_SIGN_ONLY, signOnly);
+
+ 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;
+ if (toClipboard) {
+ output = data.getString(KeychainIntentService.RESULT_ENCRYPTED_STRING);
+ Log.d(Constants.TAG, "output: " + output);
+ ClipboardReflection.copyToClipboard(getActivity(), output);
+ AppMsg.makeText(getActivity(),
+ R.string.encryption_to_clipboard_successful, AppMsg.STYLE_INFO)
+ .show();
+ } else {
+ output = data.getString(KeychainIntentService.RESULT_ENCRYPTED_STRING);
+ Log.d(Constants.TAG, "output: " + output);
+
+ 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");
+
+ sendIntent.putExtra(Intent.EXTRA_TEXT, output);
+ startActivity(Intent.createChooser(sendIntent,
+ getString(R.string.title_send_email)));
+ }
+ }
+ }
+ };
+
+ // 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);
+ }
+
+ /**
+ * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
+ * encryption
+ */
+ private void showPassphraseDialog(final boolean toClipboard) {
+ // Message is received after passphrase is cached
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ encryptStart(toClipboard);
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ try {
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ getActivity(), messenger, mEncryptInterface.getSignatureKey());
+
+ passphraseDialog.show(getActivity().getSupportFragmentManager(), "passphraseDialog");
+ } catch (PgpGeneralException e) {
+ Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
+ // send message to handler to start encryption directly
+ returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ }
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
new file mode 100644
index 000000000..f23cc565a
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+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;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.R;
+
+public class EncryptSymmetricFragment extends Fragment {
+
+ OnSymmetricKeySelection mPassphraseUpdateListener;
+
+ 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;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement OnSymmetricKeySelection");
+ }
+ }
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.encrypt_symmetric_fragment, container, false);
+
+ mPassphrase = (EditText) view.findViewById(R.id.passphrase);
+ mPassphraseAgain = (EditText) view.findViewById(R.id.passphraseAgain);
+ mPassphrase.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) {
+ mPassphraseUpdateListener.onPassphraseUpdate(s.toString());
+ }
+ });
+ mPassphraseAgain.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) {
+ mPassphraseUpdateListener.onPassphraseAgainUpdate(s.toString());
+ }
+ });
+
+ return view;
+ }
+}
diff --git a/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml
index e7d08f0fa..4515c8092 100644
--- a/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml
@@ -13,8 +13,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:id="@+id/linearLayout">
+ android:orientation="horizontal">
<EditText
android:id="@+id/decrypt_file_filename"
diff --git a/OpenPGP-Keychain/src/main/res/layout/encrypt_asymmetric_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
index 24932508b..95ed5afa4 100644
--- a/OpenPGP-Keychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
@@ -34,7 +34,7 @@
android:layout_gravity="right"
android:ellipsize="end"
android:singleLine="true"
- android:text="@string/label_sign_user_id"
+ android:text="Alice"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
@@ -44,7 +44,7 @@
android:layout_gravity="right"
android:ellipsize="end"
android:singleLine="true"
- android:text="@string/label_sign_email"
+ android:text="alice@example.com"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
diff --git a/OpenPGP-Keychain/src/main/res/layout/encrypt_content.xml b/OpenPGP-Keychain/src/main/res/layout/encrypt_content.xml
index 1dba66cfa..e719d07e1 100644
--- a/OpenPGP-Keychain/src/main/res/layout/encrypt_content.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/encrypt_content.xml
@@ -1,318 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
- xmlns:custom="http://schemas.android.com/apk/res-auto"
- android:id="@+id/content_frame"
- android:layout_marginLeft="@dimen/drawer_content_padding"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content_frame"
+ android:layout_marginLeft="@dimen/drawer_content_padding"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/encrypt_pager_mode"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fillViewport="true">
+ android:layout_height="150dp">
- <LinearLayout
+ <android.support.v4.view.PagerTabStrip
+ android:id="@+id/encrypt_pager_tab_strip_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="10dp"
- android:paddingRight="10dp">
+ android:layout_gravity="top"
+ android:background="@color/emphasis"
+ android:textColor="#fff" />
+ </android.support.v4.view.ViewPager>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="4dp">
-
- <ImageView
- android:id="@+id/modePrevious"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous"/>
-
- <TextView
- android:id="@+id/modeLabel"
- style="@style/SectionHeader"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_horizontal|center_vertical"
- android:text="@string/label_asymmetric"/>
-
- <ImageView
- android:id="@+id/modeNext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next"/>
- </LinearLayout>
-
- <ViewFlipper
- android:id="@+id/mode"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:id="@+id/modeAsymmetric"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:padding="4dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <CheckBox
- android:id="@+id/sign"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/label_sign"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="16dp"
- android:paddingRight="4dip">
-
- <TextView
- android:id="@+id/mainUserId"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="@string/label_sign_user_id"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <TextView
- android:id="@+id/mainUserIdRest"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="@string/label_sign_email"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
- </LinearLayout>
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingBottom="3dip">
-
- <TextView
- android:id="@+id/label_selectPublicKeys"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:text="@string/label_select_public_keys"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/btn_selectEncryptKeys"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_margin="4dp"
- android:text="@string/btn_select_encrypt_keys"
- bootstrapbutton:bb_icon_left="fa-user"
- bootstrapbutton:bb_size="default"
- bootstrapbutton:bb_type="default"/>
- </LinearLayout>
- </LinearLayout>
-
- <TableLayout
- android:id="@+id/modeSymmetric"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="4dp"
- android:stretchColumns="1">
-
- <TableRow>
-
- <TextView
- android:id="@+id/label_passphrase"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="10dip"
- android:text="@string/label_passphrase"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <EditText
- android:id="@+id/passphrase"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textPassword"/>
- </TableRow>
-
- <TableRow>
-
- <TextView
- android:id="@+id/label_passphraseAgain"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="10dip"
- android:text="@string/label_passphrase_again"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <EditText
- android:id="@+id/passphraseAgain"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textPassword"/>
- </TableRow>
- </TableLayout>
- </ViewFlipper>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="4dp">
-
- <ImageView
- android:id="@+id/sourcePrevious"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous"/>
-
- <TextView
- android:id="@+id/sourceLabel"
- style="@style/SectionHeader"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_horizontal|center_vertical"
- android:text="@string/label_message"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <ImageView
- android:id="@+id/sourceNext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next"/>
- </LinearLayout>
-
- <ViewFlipper
- android:id="@+id/source"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
-
- <LinearLayout
- android:id="@+id/sourceMessage"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="4dp">
-
- <EditText
- android:id="@+id/message"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="top"
- android:inputType="text|textCapSentences|textMultiLine|textLongMessage"
- android:hint="@string/encrypt_content_edit_text_hint"/>
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/sourceFile"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="4dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <EditText
- android:id="@+id/filename"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="top|left"
- android:inputType="textMultiLine|textUri"
- android:lines="4"
- android:maxLines="10"
- android:minLines="2"
- android:scrollbars="vertical"/>
-
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/btn_browse"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="4dp"
- bootstrapbutton:bb_icon_left="fa-folder-open"
- bootstrapbutton:bb_roundedCorners="true"
- bootstrapbutton:bb_size="default"
- bootstrapbutton:bb_type="default"/>
- </LinearLayout>
-
- <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- custom:foldedLabel="@string/btn_encryption_advanced_settings_show"
- custom:unFoldedLabel="@string/btn_encryption_advanced_settings_hide"
- custom:foldedIcon="fa-chevron-right"
- custom:unFoldedIcon="fa-chevron-down">
-
- <include layout="@layout/encrypt_content_adv_settings"/>
-
- </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
-
- </LinearLayout>
- </ViewFlipper>
-
- <TextView
- style="@style/SectionHeader"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"
- android:text="@string/section_encrypt_and_or_sign"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="4dp">
-
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/action_encrypt_share"
- android:layout_width="match_parent"
- android:layout_height="60dp"
- android:padding="4dp"
- android:layout_weight="1"
- android:text="@string/btn_share"
- bootstrapbutton:bb_icon_left="fa-share-square"
- bootstrapbutton:bb_type="info"/>
+ <android.support.v4.view.ViewPager
+ android:id="@+id/encrypt_pager_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/action_encrypt_clipboard"
- android:layout_width="match_parent"
- android:layout_height="60dp"
- android:padding="4dp"
- android:layout_weight="1"
- android:text="@string/btn_clipboard"
- bootstrapbutton:bb_icon_left="fa-clipboard"
- bootstrapbutton:bb_type="info"/>
+ <android.support.v4.view.PagerTabStrip
+ android:id="@+id/encrypt_pager_tab_strip_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:background="@color/emphasis"
+ android:textColor="#fff" />
+ </android.support.v4.view.ViewPager>
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/action_encrypt_file"
- android:layout_width="match_parent"
- android:layout_height="60dp"
- android:padding="4dp"
- android:visibility="gone"
- android:text="@string/btn_encrypt_file"
- bootstrapbutton:bb_icon_left="fa-lock"
- bootstrapbutton:bb_type="info"/>
- </LinearLayout>
- </LinearLayout>
-</ScrollView>
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/layout/encrypt_file_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/encrypt_file_fragment.xml
index 24a67acb7..09df8ae28 100644
--- a/OpenPGP-Keychain/src/main/res/layout/encrypt_file_fragment.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/encrypt_file_fragment.xml
@@ -59,7 +59,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/section_encrypt_and_or_sign"
- android:layout_above="@+id/decrypt_file_action_decrypt"
+ android:layout_above="@+id/action_encrypt_file"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
@@ -68,10 +68,12 @@
android:layout_width="match_parent"
android:layout_height="60dp"
android:padding="4dp"
- android:visibility="gone"
android:text="@string/btn_encrypt_file"
bootstrapbutton:bb_icon_left="fa-lock"
- bootstrapbutton:bb_type="info" />
+ bootstrapbutton:bb_type="info"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
</RelativeLayout>
</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/res/values/strings.xml b/OpenPGP-Keychain/src/main/res/values/strings.xml
index 5d325d5ec..8ae43c8ea 100644
--- a/OpenPGP-Keychain/src/main/res/values/strings.xml
+++ b/OpenPGP-Keychain/src/main/res/values/strings.xml
@@ -135,8 +135,6 @@
<string name="label_name">Name</string>
<string name="label_comment">Comment</string>
<string name="label_email">Email</string>
- <string name="label_sign_user_id">Sign User Id</string>
- <string name="label_sign_email">Sign email</string>
<string name="label_send_key">Upload key to selected keyserver after certification</string>
<string name="label_fingerprint">Fingerprint</string>
<string name="select_keys_button_default">Select</string>