|
|
@ -71,6 +71,7 @@ import android.view.ViewGroup;
|
|
|
|
import android.view.inputmethod.InputMethodManager;
|
|
|
|
import android.view.inputmethod.InputMethodManager;
|
|
|
|
import android.widget.AdapterView;
|
|
|
|
import android.widget.AdapterView;
|
|
|
|
import android.widget.ArrayAdapter;
|
|
|
|
import android.widget.ArrayAdapter;
|
|
|
|
|
|
|
|
import android.widget.Button;
|
|
|
|
import android.widget.CheckBox;
|
|
|
|
import android.widget.CheckBox;
|
|
|
|
import android.widget.CompoundButton;
|
|
|
|
import android.widget.CompoundButton;
|
|
|
|
import android.widget.EditText;
|
|
|
|
import android.widget.EditText;
|
|
|
@ -119,6 +120,8 @@ import org.bouncycastle.operator.OutputEncryptor;
|
|
|
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
|
|
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
|
|
|
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
|
|
|
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
|
|
|
import org.bouncycastle.util.Store;
|
|
|
|
import org.bouncycastle.util.Store;
|
|
|
|
|
|
|
|
import org.bouncycastle.util.io.pem.PemObject;
|
|
|
|
|
|
|
|
import org.bouncycastle.util.io.pem.PemReader;
|
|
|
|
import org.jsoup.nodes.Document;
|
|
|
|
import org.jsoup.nodes.Document;
|
|
|
|
import org.jsoup.nodes.Element;
|
|
|
|
import org.jsoup.nodes.Element;
|
|
|
|
import org.jsoup.nodes.TextNode;
|
|
|
|
import org.jsoup.nodes.TextNode;
|
|
|
@ -135,6 +138,7 @@ import java.io.FileInputStream;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.net.UnknownHostException;
|
|
|
|
import java.net.UnknownHostException;
|
|
|
|
import java.security.PrivateKey;
|
|
|
|
import java.security.PrivateKey;
|
|
|
@ -169,6 +173,7 @@ import javax.mail.internet.MimeMessage;
|
|
|
|
import javax.mail.internet.MimeMultipart;
|
|
|
|
import javax.mail.internet.MimeMultipart;
|
|
|
|
import javax.mail.internet.ParseException;
|
|
|
|
import javax.mail.internet.ParseException;
|
|
|
|
import javax.mail.util.ByteArrayDataSource;
|
|
|
|
import javax.mail.util.ByteArrayDataSource;
|
|
|
|
|
|
|
|
import javax.security.auth.x500.X500Principal;
|
|
|
|
|
|
|
|
|
|
|
|
import static android.app.Activity.RESULT_CANCELED;
|
|
|
|
import static android.app.Activity.RESULT_CANCELED;
|
|
|
|
import static android.app.Activity.RESULT_OK;
|
|
|
|
import static android.app.Activity.RESULT_OK;
|
|
|
@ -255,7 +260,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
private static final int REQUEST_LINK = 12;
|
|
|
|
private static final int REQUEST_LINK = 12;
|
|
|
|
private static final int REQUEST_DISCARD = 13;
|
|
|
|
private static final int REQUEST_DISCARD = 13;
|
|
|
|
private static final int REQUEST_SEND = 14;
|
|
|
|
private static final int REQUEST_SEND = 14;
|
|
|
|
private static final int REQUEST_SELECT_CERTIFICATE = 15;
|
|
|
|
private static final int REQUEST_CERTIFICATE = 15;
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
@ -1248,15 +1253,20 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
|
|
|
|
String email = null;
|
|
|
|
|
|
|
|
if (draft.to != null && draft.to.length == 1)
|
|
|
|
|
|
|
|
email = ((InternetAddress) draft.to[0]).getAddress();
|
|
|
|
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
args.putLong("id", draft.id);
|
|
|
|
args.putLong("id", draft.id);
|
|
|
|
args.putInt("type", draft.encrypt);
|
|
|
|
args.putInt("type", draft.encrypt);
|
|
|
|
|
|
|
|
args.putString("email", email);
|
|
|
|
args.putString("alias", alias);
|
|
|
|
args.putString("alias", alias);
|
|
|
|
|
|
|
|
|
|
|
|
if (EntityMessage.SMIME_SIGNENCRYPT.equals(draft.encrypt)) {
|
|
|
|
if (EntityMessage.SMIME_SIGNENCRYPT.equals(draft.encrypt)) {
|
|
|
|
FragmentDialogCertificate fragment = new FragmentDialogCertificate();
|
|
|
|
FragmentDialogCertificate fragment = new FragmentDialogCertificate();
|
|
|
|
fragment.setArguments(args);
|
|
|
|
fragment.setArguments(args);
|
|
|
|
fragment.setTargetFragment(FragmentCompose.this, REQUEST_SELECT_CERTIFICATE);
|
|
|
|
fragment.setTargetFragment(FragmentCompose.this, REQUEST_CERTIFICATE);
|
|
|
|
fragment.show(getParentFragmentManager(), "compose:certificate");
|
|
|
|
fragment.show(getParentFragmentManager(), "compose:certificate");
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
onSmime(args);
|
|
|
|
onSmime(args);
|
|
|
@ -1379,7 +1389,7 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
if (resultCode == RESULT_OK)
|
|
|
|
if (resultCode == RESULT_OK)
|
|
|
|
onActionSend();
|
|
|
|
onActionSend();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case REQUEST_SELECT_CERTIFICATE:
|
|
|
|
case REQUEST_CERTIFICATE:
|
|
|
|
if (resultCode == RESULT_OK && data != null)
|
|
|
|
if (resultCode == RESULT_OK && data != null)
|
|
|
|
onSmime(data.getBundleExtra("args"));
|
|
|
|
onSmime(data.getBundleExtra("args"));
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -3938,11 +3948,16 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class FragmentDialogCertificate extends FragmentDialogBase {
|
|
|
|
public static class FragmentDialogCertificate extends FragmentDialogBase {
|
|
|
|
|
|
|
|
private String email;
|
|
|
|
|
|
|
|
|
|
|
|
@NonNull
|
|
|
|
@NonNull
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
|
|
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
|
|
|
|
|
|
|
email = getArguments().getString("email");
|
|
|
|
|
|
|
|
|
|
|
|
View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_certificate, null);
|
|
|
|
View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_certificate, null);
|
|
|
|
final RecyclerView rvCertificate = dview.findViewById(R.id.rvCertificate);
|
|
|
|
final RecyclerView rvCertificate = dview.findViewById(R.id.rvCertificate);
|
|
|
|
|
|
|
|
final Button btnImport = dview.findViewById(R.id.btnImport);
|
|
|
|
final ProgressBar pbWait = dview.findViewById(R.id.pbWait);
|
|
|
|
final ProgressBar pbWait = dview.findViewById(R.id.pbWait);
|
|
|
|
|
|
|
|
|
|
|
|
final Dialog dialog = new AlertDialog.Builder(getContext())
|
|
|
|
final Dialog dialog = new AlertDialog.Builder(getContext())
|
|
|
@ -3964,6 +3979,22 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
rvCertificate.setAdapter(adapter);
|
|
|
|
rvCertificate.setAdapter(adapter);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
btnImport.setOnClickListener(new View.OnClickListener() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
|
|
|
|
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
|
|
|
|
|
|
intent.setType("*/*");
|
|
|
|
|
|
|
|
Helper.openAdvanced(intent);
|
|
|
|
|
|
|
|
PackageManager pm = getContext().getPackageManager();
|
|
|
|
|
|
|
|
if (intent.resolveActivity(pm) == null)
|
|
|
|
|
|
|
|
ToastEx.makeText(getContext(), R.string.title_no_saf, Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
startActivityForResult(Helper.getChooser(getContext(), intent), 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
btnImport.setEnabled(email != null);
|
|
|
|
|
|
|
|
|
|
|
|
rvCertificate.setVisibility(View.GONE);
|
|
|
|
rvCertificate.setVisibility(View.GONE);
|
|
|
|
pbWait.setVisibility(View.VISIBLE);
|
|
|
|
pbWait.setVisibility(View.VISIBLE);
|
|
|
|
|
|
|
|
|
|
|
@ -3979,6 +4010,54 @@ public class FragmentCompose extends FragmentBase {
|
|
|
|
|
|
|
|
|
|
|
|
return dialog;
|
|
|
|
return dialog;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
|
|
|
|
|
|
|
if (resultCode == RESULT_OK && data != null) {
|
|
|
|
|
|
|
|
Uri uri = data.getData();
|
|
|
|
|
|
|
|
if (uri != null) {
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
|
|
|
|
args.putParcelable("uri", uri);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new SimpleTask<Void>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected Void onExecute(Context context, Bundle args) throws Throwable {
|
|
|
|
|
|
|
|
Uri uri = args.getParcelable("uri");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PemObject pem;
|
|
|
|
|
|
|
|
try (InputStream is = context.getContentResolver().openInputStream(uri)) {
|
|
|
|
|
|
|
|
pem = new PemReader(new InputStreamReader(is)).readPemObject();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ByteArrayInputStream bis = new ByteArrayInputStream(pem.getContent());
|
|
|
|
|
|
|
|
CertificateFactory fact = CertificateFactory.getInstance("X.509");
|
|
|
|
|
|
|
|
X509Certificate cert = (X509Certificate) fact.generateCertificate(bis);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String fingerprint = Helper.sha256(cert.getEncoded());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
|
|
|
EntityCertificate record = db.certificate().getCertificate(fingerprint, email);
|
|
|
|
|
|
|
|
if (record == null) {
|
|
|
|
|
|
|
|
record = new EntityCertificate();
|
|
|
|
|
|
|
|
record.fingerprint = Helper.sha256(cert.getEncoded());
|
|
|
|
|
|
|
|
record.email = email;
|
|
|
|
|
|
|
|
record.subject = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
|
|
|
|
|
|
|
|
record.setEncoded(cert.getEncoded());
|
|
|
|
|
|
|
|
record.id = db.certificate().insertCertificate(record);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: report exists
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onException(Bundle args, Throwable ex) {
|
|
|
|
|
|
|
|
Helper.unexpectedError(getParentFragmentManager(), ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}.execute(this, args, "compose:cert");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class FragmentDialogSend extends FragmentDialogBase {
|
|
|
|
public static class FragmentDialogSend extends FragmentDialogBase {
|
|
|
|