diff --git a/app/src/amazon/AndroidManifest.xml b/app/src/amazon/AndroidManifest.xml
index ed0c10c11b..bd58679360 100644
--- a/app/src/amazon/AndroidManifest.xml
+++ b/app/src/amazon/AndroidManifest.xml
@@ -474,6 +474,15 @@
+
+
+
+
+
+
+
+
+
+
.
+
+ Copyright 2018-2023 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.Group;
+import androidx.preference.PreferenceManager;
+
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.w3c.dom.css.CSSStyleSheet;
+
+import java.io.File;
+import java.util.List;
+
+public class ActivityHTML extends ActivityBase {
+ private TextView tvText;
+ private ContentLoadingProgressBar pbWait;
+ private Group grpReady;
+
+ private boolean sanitize = BuildConfig.DEBUG;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState != null)
+ sanitize = savedInstanceState.getBoolean("fair:sanitize");
+
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ View view = LayoutInflater.from(this).inflate(R.layout.activity_text, null);
+ setContentView(view);
+
+ tvText = findViewById(R.id.tvText);
+ pbWait = findViewById(R.id.pbWait);
+ grpReady = findViewById(R.id.grpReady);
+
+ // Initialize
+ grpReady.setVisibility(View.GONE);
+
+ load();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ load();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putBoolean("fair:sanitize", sanitize);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.menu_html, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean debug = prefs.getBoolean("debug", false);
+
+ menu.findItem(R.id.menu_sanitize)
+ .setVisible(BuildConfig.DEBUG || debug)
+ .setChecked(sanitize);
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int itemId = item.getItemId();
+ if (itemId == android.R.id.home) {
+ finish();
+ return true;
+ } else if (itemId == R.id.menu_sanitize) {
+ sanitize = !sanitize;
+ item.setChecked(sanitize);
+ load();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void load() {
+ Intent intent = getIntent();
+ long id = intent.getLongExtra("id", -1L);
+ Log.i("Text id=" + id + " sanitize=" + sanitize);
+
+ Bundle args = new Bundle();
+ args.putLong("id", id);
+ args.putBoolean("sanitize", sanitize);
+
+ new SimpleTask() {
+ @Override
+ protected void onPreExecute(Bundle args) {
+ pbWait.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected void onPostExecute(Bundle args) {
+ pbWait.setVisibility(View.GONE);
+ }
+
+ @Override
+ protected String onExecute(Context context, Bundle args) throws Throwable {
+ long id = args.getLong("id");
+ boolean sanitize = args.getBoolean("sanitize");
+
+ DB db = DB.getInstance(context);
+ EntityMessage message = db.message().getMessage(id);
+ if (message == null)
+ return null;
+
+ args.putString("subject", message.subject);
+
+ File file = message.getFile(context);
+ if (sanitize) {
+ Document d = JsoupEx.parse(file);
+
+ List sheets =
+ HtmlHelper.parseStyles(d.head().select("style"));
+ for (Element element : d.select("*")) {
+ String computed = HtmlHelper.processStyles(context,
+ element.tagName(),
+ element.className(),
+ element.attr("style"),
+ sheets);
+ if (!TextUtils.isEmpty(computed))
+ element.attr("x-computed", computed);
+ }
+
+ d = HtmlHelper.sanitizeView(context, d, false);
+ d.outputSettings().prettyPrint(true).outline(true).indentAmount(1);
+
+ return d.html();
+ } else
+ return Helper.readText(file);
+ }
+
+ @Override
+ protected void onExecuted(Bundle args, String text) {
+ getSupportActionBar().setSubtitle(args.getString("subject"));
+
+ tvText.setText(text);
+ grpReady.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected void onException(Bundle args, @NonNull Throwable ex) {
+ Log.unexpectedError(getSupportFragmentManager(), ex, false);
+ }
+ }.execute(this, args, "view:text");
+ }
+}
diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java
index e84fa8df79..14b6064883 100644
--- a/app/src/main/java/eu/faircode/email/AdapterMessage.java
+++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java
@@ -149,7 +149,6 @@ import com.google.android.material.snackbar.Snackbar;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
-import org.w3c.dom.css.CSSStyleSheet;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -6108,7 +6107,7 @@ public class AdapterMessage extends RecyclerView.Adapter() {
- @Override
- protected File onExecute(Context context, Bundle args) throws IOException {
- Long id = args.getLong("id");
-
- DB db = DB.getInstance(context);
- EntityMessage message = db.message().getMessage(id);
- if (message == null || !message.content)
- return null;
-
- File file = message.getFile(context);
- Document d = JsoupEx.parse(file);
-
- if (BuildConfig.DEBUG) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- boolean overview_mode = prefs.getBoolean("overview_mode", false);
- HtmlHelper.setViewport(d, overview_mode);
- }
-
- d.head().prependElement("meta").attr("charset", "utf-8");
-
- if (message.language != null)
- d.body().attr("lang", message.language);
-
- List sheets =
- HtmlHelper.parseStyles(d.head().select("style"));
- for (Element element : d.select("*")) {
- String computed = HtmlHelper.processStyles(context,
- element.tagName(),
- element.className(),
- element.attr("style"),
- sheets);
- if (!TextUtils.isEmpty(computed))
- element.attr("x-computed", computed);
- }
-
- if (BuildConfig.DEBUG) {
- d = HtmlHelper.sanitizeView(context, d, false);
- d.outputSettings().prettyPrint(true).outline(true).indentAmount(1);
- }
-
- File dir = Helper.ensureExists(new File(context.getFilesDir(), "shared"));
- File share = new File(dir, message.id + ".txt");
- Helper.writeText(share, d.html());
-
- return share;
- }
-
- @Override
- protected void onExecuted(Bundle args, File share) {
- Helper.share(context, share, "text/plain", share.getName());
- }
-
- @Override
- protected void onException(Bundle args, Throwable ex) {
- Log.unexpectedError(parentFragment.getParentFragmentManager(), ex);
- }
- }.execute(context, owner, args, "message:headers");
+ context.startActivity(new Intent(context, ActivityHTML.class)
+ .putExtra("id", message.id));
}
private void onMenuRawSave(TupleMessageEx message) {
diff --git a/app/src/main/res/layout/activity_text.xml b/app/src/main/res/layout/activity_text.xml
new file mode 100644
index 0000000000..1b59c5deca
--- /dev/null
+++ b/app/src/main/res/layout/activity_text.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu_html.xml b/app/src/main/res/menu/menu_html.xml
new file mode 100644
index 0000000000..04d5268559
--- /dev/null
+++ b/app/src/main/res/menu/menu_html.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/app/src/main/res/menu/popup_message_more.xml b/app/src/main/res/menu/popup_message_more.xml
index 0c83cc45ec..9976b0089e 100644
--- a/app/src/main/res/menu/popup_message_more.xml
+++ b/app/src/main/res/menu/popup_message_more.xml
@@ -138,9 +138,9 @@
android:title="@string/title_show_headers" />
+ android:title="@string/title_show_html" />
- Downloading images might take some time
Print block quotes lines
Show headers
- Share as HTML
+ Show HTML
Save raw message
Send as attachment
Message
@@ -2344,6 +2344,7 @@
Follow dark system theme
Google removed dark mode for Android versions before version 10
+ Sanitize
Important
diff --git a/app/src/play/AndroidManifest.xml b/app/src/play/AndroidManifest.xml
index 7da46ef521..c26a247b80 100644
--- a/app/src/play/AndroidManifest.xml
+++ b/app/src/play/AndroidManifest.xml
@@ -474,6 +474,15 @@
+
+