/*
* 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.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.io.UnsupportedEncodingException;
public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext";
public static final String ARG_SHOW_MENU = "show_menu";
// view
private TextView mText;
// model
private String mCiphertext;
private boolean mShowMenuOptions;
public static DecryptTextFragment newInstance(String ciphertext) {
DecryptTextFragment frag = new DecryptTextFragment();
Bundle args = new Bundle();
args.putString(ARG_CIPHERTEXT, ciphertext);
frag.setArguments(args);
return frag;
}
/**
* Inflate the layout for this fragment
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false);
mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext);
return view;
}
/**
* Create Intent Chooser but exclude decrypt activites
*/
private Intent sendWithChooserExcludingDecrypt(String text) {
Intent prototype = createSendIntent(text);
String title = getString(R.string.title_share_message);
// we don't want to decrypt the decrypted, no inception ;)
String[] blacklist = new String[]{
Constants.PACKAGE_NAME + ".ui.DecryptTextActivity",
"org.thialfihar.android.apg.ui.DecryptActivity"
};
return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
}
private Intent createSendIntent(String text) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
return sendIntent;
}
private void copyToClipboard(String text) {
ClipboardReflection.copyToClipboard(getActivity(), text);
Notify.create(getActivity(), R.string.text_copied_to_clipboard, Notify.Style.OK).show();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState;
mCiphertext = args.getString(ARG_CIPHERTEXT);
mShowMenuOptions = args.getBoolean(ARG_SHOW_MENU, false);
if (savedInstanceState == null) {
cryptoOperation();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(ARG_CIPHERTEXT, mCiphertext);
outState.putBoolean(ARG_SHOW_MENU, mShowMenuOptions);
// no need to save the decrypted text, it's in the textview
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (mShowMenuOptions) {
inflater.inflate(R.menu.decrypt_menu, menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.decrypt_share: {
startActivity(sendWithChooserExcludingDecrypt(mText.getText().toString()));
break;
}
case R.id.decrypt_copy: {
copyToClipboard(mText.getText().toString());
break;
}
default: {
return super.onOptionsItemSelected(item);
}
}
return true;
}
@Override
protected PgpDecryptVerifyInputParcel createOperationInput() {
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCiphertext.getBytes());
input.setAllowSymmetricDecryption(true);
return input;
}
@Override
protected void onVerifyLoaded(boolean hideErrorOverlay) {
mShowMenuOptions = hideErrorOverlay;
getActivity().supportInvalidateOptionsMenu();
}
@Override
protected void onCryptoOperationSuccess(DecryptVerifyResult result) {
byte[] decryptedMessage = result.getOutputBytes();
String displayMessage;
if (result.getCharset() != null) {
try {
displayMessage = new String(decryptedMessage, result.getCharset());
} catch (UnsupportedEncodingException e) {
// if we can't decode properly, just fall back to utf-8
displayMessage = new String(decryptedMessage);
}
} else {
displayMessage = new String(decryptedMessage);
}
mText.setText(displayMessage);
// display signature result in activity
loadVerifyResult(result);
}
}