
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 995 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash |
||||
|
||||
APP_DIR=../k9mail/src/main |
||||
MDPI_DIR=$APP_DIR/res/drawable-mdpi |
||||
HDPI_DIR=$APP_DIR/res/drawable-hdpi |
||||
XDPI_DIR=$APP_DIR/res/drawable-xhdpi |
||||
XXDPI_DIR=$APP_DIR/res/drawable-xxhdpi |
||||
XXXDPI_DIR=$APP_DIR/res/drawable-xxxhdpi |
||||
SRC_DIR=./drawables-pgp/ |
||||
|
||||
|
||||
for NAME in "status_lock_closed" "status_lock_error" "status_lock_open" "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout" |
||||
do |
||||
echo $NAME |
||||
inkscape -w 24 -h 24 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" |
||||
inkscape -w 32 -h 32 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" |
||||
inkscape -w 48 -h 48 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" |
||||
inkscape -w 64 -h 64 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" |
||||
done |
@ -0,0 +1,423 @@
@@ -0,0 +1,423 @@
|
||||
|
||||
package com.fsck.k9.ui.messageview; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.InputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
import java.nio.charset.Charset; |
||||
|
||||
import android.app.Activity; |
||||
import android.app.Fragment; |
||||
import android.app.PendingIntent; |
||||
import android.content.Context; |
||||
import android.content.Intent; |
||||
import android.content.IntentSender.SendIntentException; |
||||
import android.util.AttributeSet; |
||||
import android.util.Log; |
||||
import android.view.View; |
||||
import android.widget.Button; |
||||
import android.widget.ImageView; |
||||
import android.widget.LinearLayout; |
||||
import android.widget.ProgressBar; |
||||
import android.widget.RelativeLayout; |
||||
import android.widget.TextView; |
||||
import android.widget.Toast; |
||||
|
||||
import com.fsck.k9.Account; |
||||
import com.fsck.k9.Identity; |
||||
import com.fsck.k9.K9; |
||||
import com.fsck.k9.R; |
||||
import com.fsck.k9.crypto.CryptoHelper; |
||||
import com.fsck.k9.crypto.OpenPgpApiHelper; |
||||
import com.fsck.k9.helper.IdentityHelper; |
||||
import com.fsck.k9.mail.Message; |
||||
import com.fsck.k9.mail.MessagingException; |
||||
import com.fsck.k9.mail.Part; |
||||
|
||||
import com.fsck.k9.mail.internet.MessageExtractor; |
||||
import com.fsck.k9.mail.internet.MimeUtility; |
||||
import org.openintents.openpgp.OpenPgpError; |
||||
import org.openintents.openpgp.OpenPgpSignatureResult; |
||||
import org.openintents.openpgp.util.OpenPgpApi; |
||||
import org.openintents.openpgp.util.OpenPgpServiceConnection; |
||||
|
||||
public class MessageOpenPgpViewOld extends LinearLayout { |
||||
|
||||
private Context mContext; |
||||
private MessageViewFragment mFragment; |
||||
private RelativeLayout mSignatureLayout = null; |
||||
private ImageView mSignatureStatusImage = null; |
||||
private TextView mSignatureUserId = null; |
||||
private TextView mText = null; |
||||
private ProgressBar mProgress; |
||||
private Button mGetKeyButton; |
||||
|
||||
private OpenPgpServiceConnection mOpenPgpServiceConnection; |
||||
private OpenPgpApi mOpenPgpApi; |
||||
|
||||
private String mOpenPgpProvider; |
||||
private Message mMessage; |
||||
|
||||
private PendingIntent mMissingKeyPI; |
||||
|
||||
private static final int REQUEST_CODE_DECRYPT_VERIFY = 12; |
||||
|
||||
String mData; |
||||
Account mAccount; |
||||
|
||||
public MessageOpenPgpViewOld(Context context, AttributeSet attrs) { |
||||
super(context, attrs); |
||||
mContext = context; |
||||
} |
||||
|
||||
public void setupChildViews() { |
||||
mSignatureLayout = (RelativeLayout) findViewById(R.id.openpgp_signature_layout); |
||||
mSignatureStatusImage = (ImageView) findViewById(R.id.openpgp_signature_status); |
||||
mSignatureUserId = (TextView) findViewById(R.id.openpgp_user_id); |
||||
mText = (TextView) findViewById(R.id.openpgp_text); |
||||
mProgress = (ProgressBar) findViewById(R.id.openpgp_progress); |
||||
mGetKeyButton = (Button) findViewById(R.id.openpgp_get_key); |
||||
|
||||
mGetKeyButton.setOnClickListener(new OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
getMissingKey(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void setFragment(Fragment fragment) { |
||||
mFragment = (MessageViewFragment) fragment; |
||||
} |
||||
|
||||
/** |
||||
* Fill the decrypt layout with signature data, if known, make controls |
||||
* visible, if they should be visible. |
||||
*/ |
||||
public void updateLayout(Account account, String decryptedData, |
||||
final OpenPgpSignatureResult signatureResult, |
||||
final Message message) { |
||||
|
||||
// set class variables
|
||||
mAccount = account; |
||||
mOpenPgpProvider = mAccount.getOpenPgpProvider(); |
||||
mMessage = message; |
||||
|
||||
// only use this view if a OpenPGP Provider is set
|
||||
if (mOpenPgpProvider == null) { |
||||
return; |
||||
} |
||||
|
||||
Activity activity = mFragment.getActivity(); |
||||
if (activity == null) { |
||||
return; |
||||
} |
||||
// bind to service
|
||||
mOpenPgpServiceConnection = new OpenPgpServiceConnection(activity, |
||||
mOpenPgpProvider); |
||||
mOpenPgpServiceConnection.bindToService(); |
||||
|
||||
if ((message == null) && (decryptedData == null)) { |
||||
this.setVisibility(View.GONE); |
||||
|
||||
// don't process further
|
||||
return; |
||||
} |
||||
if (decryptedData != null && signatureResult == null) { |
||||
// encrypted-only
|
||||
|
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_blue)); |
||||
mText.setText(R.string.openpgp_successful_decryption); |
||||
|
||||
// don't process further
|
||||
return; |
||||
} else if (decryptedData != null && signatureResult != null) { |
||||
// signed-only and signed-and-encrypted
|
||||
|
||||
switch (signatureResult.getStatus()) { |
||||
case OpenPgpSignatureResult.SIGNATURE_ERROR: |
||||
// TODO: signature error but decryption works?
|
||||
mText.setText(R.string.openpgp_signature_invalid); |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_red)); |
||||
|
||||
mGetKeyButton.setVisibility(View.GONE); |
||||
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); |
||||
mSignatureLayout.setVisibility(View.GONE); |
||||
break; |
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: |
||||
if (signatureResult.isSignatureOnly()) { |
||||
mText.setText(R.string.openpgp_signature_valid_certified); |
||||
} |
||||
else { |
||||
mText.setText(R.string.openpgp_successful_decryption_valid_signature_certified); |
||||
} |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_green)); |
||||
|
||||
mGetKeyButton.setVisibility(View.GONE); |
||||
mSignatureUserId.setText(signatureResult.getUserId()); |
||||
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); |
||||
mSignatureLayout.setVisibility(View.VISIBLE); |
||||
|
||||
break; |
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: |
||||
if (signatureResult.isSignatureOnly()) { |
||||
mText.setText(R.string.openpgp_signature_unknown_text); |
||||
} |
||||
else { |
||||
mText.setText(R.string.openpgp_successful_decryption_unknown_signature); |
||||
} |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_orange)); |
||||
|
||||
mGetKeyButton.setVisibility(View.VISIBLE); |
||||
mSignatureUserId.setText(R.string.openpgp_signature_unknown); |
||||
mSignatureStatusImage.setImageResource(R.drawable.overlay_error); |
||||
mSignatureLayout.setVisibility(View.VISIBLE); |
||||
|
||||
break; |
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: |
||||
if (signatureResult.isSignatureOnly()) { |
||||
mText.setText(R.string.openpgp_signature_valid_uncertified); |
||||
} |
||||
else { |
||||
mText.setText(R.string.openpgp_successful_decryption_valid_signature_uncertified); |
||||
} |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_orange)); |
||||
|
||||
mGetKeyButton.setVisibility(View.GONE); |
||||
mSignatureUserId.setText(signatureResult.getUserId()); |
||||
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); |
||||
mSignatureLayout.setVisibility(View.VISIBLE); |
||||
|
||||
break; |
||||
|
||||
default: |
||||
break; |
||||
} |
||||
|
||||
// don't process further
|
||||
return; |
||||
} |
||||
|
||||
// Start new decryption/verification
|
||||
CryptoHelper helper = new CryptoHelper(); |
||||
if (helper.isEncrypted(message) || helper.isSigned(message)) { |
||||
// start automatic decrypt
|
||||
decryptAndVerify(message); |
||||
} else { |
||||
try { |
||||
// check for PGP/MIME encryption
|
||||
Part pgp = MimeUtility.findFirstPartByMimeType(message, "application/pgp-encrypted"); |
||||
if (pgp != null) { |
||||
Toast.makeText(mContext, R.string.pgp_mime_unsupported, Toast.LENGTH_LONG) |
||||
.show(); |
||||
} |
||||
} catch (MessagingException e) { |
||||
// nothing to do...
|
||||
} |
||||
} |
||||
} |
||||
|
||||
private void decryptAndVerify(final Message message) { |
||||
this.setVisibility(View.VISIBLE); |
||||
mProgress.setVisibility(View.VISIBLE); |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_orange)); |
||||
mText.setText(R.string.openpgp_decrypting_verifying); |
||||
|
||||
// waiting in a new thread
|
||||
Runnable r = new Runnable() { |
||||
|
||||
@Override |
||||
public void run() { |
||||
try { |
||||
// get data String
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain"); |
||||
if (part == null) { |
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html"); |
||||
} |
||||
if (part != null) { |
||||
mData = MessageExtractor.getTextFromPart(part); |
||||
} |
||||
|
||||
// wait for service to be bound
|
||||
while (!mOpenPgpServiceConnection.isBound()) { |
||||
try { |
||||
Thread.sleep(100); |
||||
} catch (InterruptedException e) { |
||||
} |
||||
} |
||||
|
||||
mOpenPgpApi = new OpenPgpApi(getContext(), |
||||
mOpenPgpServiceConnection.getService()); |
||||
|
||||
decryptVerify(new Intent()); |
||||
|
||||
} catch (MessagingException me) { |
||||
Log.e(K9.LOG_TAG, "Unable to decrypt email.", me); |
||||
} |
||||
|
||||
} |
||||
}; |
||||
|
||||
new Thread(r).start(); |
||||
} |
||||
|
||||
private void decryptVerify(Intent intent) { |
||||
intent.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); |
||||
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); |
||||
|
||||
Identity identity = IdentityHelper.getRecipientIdentityFromMessage(mAccount, mMessage); |
||||
String accName = OpenPgpApiHelper.buildAccountName(identity); |
||||
intent.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, accName); |
||||
|
||||
InputStream is = new ByteArrayInputStream(mData.getBytes(Charset.forName("UTF-8"))); |
||||
final ByteArrayOutputStream os = new ByteArrayOutputStream(); |
||||
|
||||
DecryptVerifyCallback callback = new DecryptVerifyCallback(os, REQUEST_CODE_DECRYPT_VERIFY); |
||||
|
||||
mOpenPgpApi.executeApiAsync(intent, is, os, callback); |
||||
} |
||||
|
||||
private void getMissingKey() { |
||||
try { |
||||
mFragment.getActivity().startIntentSenderForResult( |
||||
mMissingKeyPI.getIntentSender(), |
||||
REQUEST_CODE_DECRYPT_VERIFY, null, 0, 0, 0); |
||||
} catch (SendIntentException e) { |
||||
Log.e(K9.LOG_TAG, "SendIntentException", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Called on successful decrypt/verification |
||||
*/ |
||||
private class DecryptVerifyCallback implements OpenPgpApi.IOpenPgpCallback { |
||||
ByteArrayOutputStream os; |
||||
int requestCode; |
||||
|
||||
private DecryptVerifyCallback(ByteArrayOutputStream os, int requestCode) { |
||||
this.os = os; |
||||
this.requestCode = requestCode; |
||||
} |
||||
|
||||
@Override |
||||
public void onReturn(Intent result) { |
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { |
||||
case OpenPgpApi.RESULT_CODE_SUCCESS: { |
||||
try { |
||||
final String output = os.toString("UTF-8"); |
||||
|
||||
OpenPgpSignatureResult sigResult = null; |
||||
if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) { |
||||
sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); |
||||
} |
||||
|
||||
if (K9.DEBUG) |
||||
Log.d(K9.LOG_TAG, "result: " + os.toByteArray().length |
||||
+ " str=" + output); |
||||
|
||||
// missing key -> PendingIntent to get keys
|
||||
mMissingKeyPI = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); |
||||
|
||||
mProgress.setVisibility(View.GONE); |
||||
mFragment.setMessageWithOpenPgp(output, sigResult); |
||||
} catch (UnsupportedEncodingException e) { |
||||
Log.e(K9.LOG_TAG, "UnsupportedEncodingException", e); |
||||
} |
||||
break; |
||||
} |
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { |
||||
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); |
||||
try { |
||||
mFragment.getActivity().startIntentSenderForResult( |
||||
pi.getIntentSender(), |
||||
requestCode, null, 0, 0, 0); |
||||
} catch (SendIntentException e) { |
||||
Log.e(K9.LOG_TAG, "SendIntentException", e); |
||||
} |
||||
break; |
||||
} |
||||
case OpenPgpApi.RESULT_CODE_ERROR: { |
||||
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); |
||||
handleError(error); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) { |
||||
if (K9.DEBUG) |
||||
Log.d(K9.LOG_TAG, "onActivityResult resultCode: " + resultCode); |
||||
|
||||
// try again after user interaction
|
||||
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_DECRYPT_VERIFY) { |
||||
/* |
||||
* The data originally given to the decryptVerify() method, is again |
||||
* returned here to be used when calling decryptVerify() after user |
||||
* interaction. The Intent now also contains results from the user |
||||
* interaction, for example selected key ids. |
||||
*/ |
||||
decryptVerify(data); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private void handleError(final OpenPgpError error) { |
||||
Activity activity = mFragment.getActivity(); |
||||
if (activity == null) { |
||||
return; |
||||
} |
||||
activity.runOnUiThread(new Runnable() { |
||||
|
||||
@Override |
||||
public void run() { |
||||
mProgress.setVisibility(View.GONE); |
||||
|
||||
if (K9.DEBUG) { |
||||
Log.d(K9.LOG_TAG, "OpenPGP Error ID:" + error.getErrorId()); |
||||
Log.d(K9.LOG_TAG, "OpenPGP Error Message:" + error.getMessage()); |
||||
} |
||||
|
||||
mText.setText(mFragment.getString(R.string.openpgp_error) + " " |
||||
+ error.getMessage()); |
||||
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor( |
||||
R.color.openpgp_red)); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
protected void onAttachedToWindow() { |
||||
super.onAttachedToWindow(); |
||||
|
||||
// bind to service if a OpenPGP Provider is available
|
||||
if (mOpenPgpProvider != null) { |
||||
mOpenPgpServiceConnection = new OpenPgpServiceConnection(mFragment.getActivity(), |
||||
mOpenPgpProvider); |
||||
mOpenPgpServiceConnection.bindToService(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void onDetachedFromWindow() { |
||||
super.onDetachedFromWindow(); |
||||
|
||||
if (mOpenPgpServiceConnection != null) { |
||||
mOpenPgpServiceConnection.unbindFromService(); |
||||
} |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 675 B |
After Width: | Height: | Size: 748 B |
After Width: | Height: | Size: 675 B |
After Width: | Height: | Size: 789 B |
After Width: | Height: | Size: 444 B |
After Width: | Height: | Size: 861 B |
After Width: | Height: | Size: 740 B |