Made extra privacy features explicit

pull/157/head
M66B 6 years ago
parent bd7e879eff
commit 3a34a30cbc

@ -160,7 +160,7 @@ FairEmail follows all the best practices for an email client as decribed in [thi
* [(83) What does 'User is authenticated but not connected' mean?](#user-content-faq83) * [(83) What does 'User is authenticated but not connected' mean?](#user-content-faq83)
* [(84) What are local contacts for?](#user-content-faq84) * [(84) What are local contacts for?](#user-content-faq84)
* [(85) Why is an identity not available?](#user-content-faq85) * [(85) Why is an identity not available?](#user-content-faq85)
* [(86) What are 'extra privacy features'?](#user-content-faq86) * [~~(86) What are 'extra privacy features'?~~](#user-content-faq86)
* [(87) What does 'invalid credentials' mean?](#user-content-faq87) * [(87) What does 'invalid credentials' mean?](#user-content-faq87)
* [(88) How can I use a Yahoo! account?](#user-content-faq88) * [(88) How can I use a Yahoo! account?](#user-content-faq88)
* [(89) How can I send plain text only messages?](#user-content-faq89) * [(89) How can I send plain text only messages?](#user-content-faq89)
@ -1550,12 +1550,12 @@ FairEmail will try to select the best identity based on the *to* address of the
<br /> <br />
<a name="faq86"></a> <a name="faq86"></a>
**(86) What are 'extra privacy features'?** **~~(86) What are 'extra privacy features'?~~**
The advanced option *extra privacy features* enables: ~~The advanced option *extra privacy features* enables:~~
* Looking up the owner of the IP address of a link * ~~Looking up the owner of the IP address of a link~~
* Detection and removal of [tracking images](#user-content-faq82) * ~~Detection and removal of [tracking images](#user-content-faq82)~~
<br /> <br />

@ -117,7 +117,6 @@ import org.jsoup.nodes.Element;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -3371,9 +3370,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
boolean paranoid = prefs.getBoolean("paranoid", true);
final Uri uri = getArguments().getParcelable("uri"); final Uri uri = getArguments().getParcelable("uri");
String title = getArguments().getString("title"); String title = getArguments().getString("title");
@ -3401,6 +3397,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
final EditText etLink = view.findViewById(R.id.etLink); final EditText etLink = view.findViewById(R.id.etLink);
final CheckBox cbSecure = view.findViewById(R.id.cbSecure); final CheckBox cbSecure = view.findViewById(R.id.cbSecure);
CheckBox cbSanitize = view.findViewById(R.id.cbSanitize); CheckBox cbSanitize = view.findViewById(R.id.cbSanitize);
final Button btnOwner = view.findViewById(R.id.btnOwner);
final ContentLoadingProgressBar pbWait = view.findViewById(R.id.pbWait);
final TextView tvOwner = view.findViewById(R.id.tvOwner); final TextView tvOwner = view.findViewById(R.id.tvOwner);
final TextView tvHost = view.findViewById(R.id.tvHost); final TextView tvHost = view.findViewById(R.id.tvHost);
final Group grpOwner = view.findViewById(R.id.grpOwner); final Group grpOwner = view.findViewById(R.id.grpOwner);
@ -3472,43 +3470,50 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} }
}); });
pbWait.setVisibility(View.GONE);
grpOwner.setVisibility(View.GONE); grpOwner.setVisibility(View.GONE);
btnOwner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle args = new Bundle();
args.putParcelable("uri", uri);
if (paranoid) { new SimpleTask<String[]>() {
// TODO: spinner @Override
Bundle args = new Bundle(); protected void onPreExecute(Bundle args) {
args.putParcelable("uri", uri); btnOwner.setEnabled(false);
pbWait.setVisibility(View.VISIBLE);
grpOwner.setVisibility(View.GONE);
}
new SimpleTask<String[]>() { @Override
@Override protected void onPostExecute(Bundle args) {
protected void onPreExecute(Bundle args) { btnOwner.setEnabled(true);
tvOwner.setText("…"); pbWait.setVisibility(View.GONE);
grpOwner.setVisibility(View.VISIBLE); grpOwner.setVisibility(View.VISIBLE);
} }
@Override @Override
protected String[] onExecute(Context context, Bundle args) throws Throwable { protected String[] onExecute(Context context, Bundle args) throws Throwable {
Uri uri = args.getParcelable("uri"); Uri uri = args.getParcelable("uri");
return IPInfo.getOrganization(uri); return IPInfo.getOrganization(uri);
} }
@Override @Override
protected void onExecuted(Bundle args, String[] data) { protected void onExecuted(Bundle args, String[] data) {
String host = data[0]; String host = data[0];
String organization = data[1]; String organization = data[1];
tvHost.setText(host); tvHost.setText(host);
tvOwner.setText(organization == null ? "?" : organization); tvOwner.setText(organization == null ? "?" : organization);
} }
@Override @Override
protected void onException(Bundle args, Throwable ex) { protected void onException(Bundle args, Throwable ex) {
if (ex instanceof UnknownHostException)
grpOwner.setVisibility(View.GONE);
else
tvOwner.setText(ex.getMessage()); tvOwner.setText(ex.getMessage());
} }
}.execute(getContext(), getActivity(), args, "link:domain"); }.execute(getContext(), getActivity(), args, "link:owner");
} }
});
return new AlertDialog.Builder(getContext()) return new AlertDialog.Builder(getContext())
.setView(view) .setView(view)

@ -45,10 +45,11 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
private SwitchCompat swCollapse; private SwitchCompat swCollapse;
private SwitchCompat swAutoRead; private SwitchCompat swAutoRead;
private SwitchCompat swAutoMove; private SwitchCompat swAutoMove;
private SwitchCompat swDisableTracking;
private final static String[] RESET_OPTIONS = new String[]{ private final static String[] RESET_OPTIONS = new String[]{
"pull", "autoscroll", "swipenav", "doubletap", "autoexpand", "autoclose", "autonext", "pull", "autoscroll", "swipenav", "doubletap", "autoexpand", "autoclose", "autonext",
"collapse", "autoread", "automove" "collapse", "autoread", "automove", "disable_tracking"
}; };
@Override @Override
@ -71,6 +72,7 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
swCollapse = view.findViewById(R.id.swCollapse); swCollapse = view.findViewById(R.id.swCollapse);
swAutoRead = view.findViewById(R.id.swAutoRead); swAutoRead = view.findViewById(R.id.swAutoRead);
swAutoMove = view.findViewById(R.id.swAutoMove); swAutoMove = view.findViewById(R.id.swAutoMove);
swDisableTracking = view.findViewById(R.id.swDisableTracking);
setOptions(); setOptions();
@ -149,6 +151,13 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
} }
}); });
swDisableTracking.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("disable_tracking", checked).apply();
}
});
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this); PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
return view; return view;
@ -204,5 +213,6 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
swCollapse.setChecked(prefs.getBoolean("collapse", false)); swCollapse.setChecked(prefs.getBoolean("collapse", false));
swAutoRead.setChecked(prefs.getBoolean("autoread", false)); swAutoRead.setChecked(prefs.getBoolean("autoread", false));
swAutoMove.setChecked(!prefs.getBoolean("automove", false)); swAutoMove.setChecked(!prefs.getBoolean("automove", false));
swDisableTracking.setChecked(prefs.getBoolean("disable_tracking", true));
} }
} }

@ -24,7 +24,6 @@ import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -52,8 +51,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
private SwitchCompat swSubscribedOnly; private SwitchCompat swSubscribedOnly;
private SwitchCompat swEnglish; private SwitchCompat swEnglish;
private SwitchCompat swAuthentication; private SwitchCompat swAuthentication;
private SwitchCompat swParanoid;
private TextView tvParanoidHint;
private SwitchCompat swWatchdog; private SwitchCompat swWatchdog;
private SwitchCompat swUpdates; private SwitchCompat swUpdates;
private SwitchCompat swCrashReports; private SwitchCompat swCrashReports;
@ -67,7 +64,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
private Group grpDebug; private Group grpDebug;
private final static String[] RESET_OPTIONS = new String[]{ private final static String[] RESET_OPTIONS = new String[]{
"badge", "subscriptions", "subscribed_only", "english", "authentication", "paranoid", "watchdog", "updates", "crash_reports", "debug" "badge", "subscriptions", "subscribed_only", "english", "authentication", "watchdog", "updates", "crash_reports", "debug"
}; };
private final static String[] RESET_QUESTIONS = new String[]{ private final static String[] RESET_QUESTIONS = new String[]{
@ -90,8 +87,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
swSubscribedOnly = view.findViewById(R.id.swSubscribedOnly); swSubscribedOnly = view.findViewById(R.id.swSubscribedOnly);
swEnglish = view.findViewById(R.id.swEnglish); swEnglish = view.findViewById(R.id.swEnglish);
swAuthentication = view.findViewById(R.id.swAuthentication); swAuthentication = view.findViewById(R.id.swAuthentication);
swParanoid = view.findViewById(R.id.swParanoid);
tvParanoidHint = view.findViewById(R.id.tvParanoidHint);
swWatchdog = view.findViewById(R.id.swWatchdog); swWatchdog = view.findViewById(R.id.swWatchdog);
swUpdates = view.findViewById(R.id.swUpdates); swUpdates = view.findViewById(R.id.swUpdates);
swCrashReports = view.findViewById(R.id.swCrashReports); swCrashReports = view.findViewById(R.id.swCrashReports);
@ -150,26 +145,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
} }
}); });
swParanoid.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("paranoid", checked).apply();
}
});
final Intent faq = new Intent(Intent.ACTION_VIEW);
faq.setData(Uri.parse(Helper.FAQ_URI + "#user-content-faq86"));
faq.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (faq.resolveActivity(getContext().getPackageManager()) != null) {
tvParanoidHint.getPaint().setUnderlineText(true);
tvParanoidHint.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(faq);
}
});
}
swWatchdog.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { swWatchdog.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@ -269,7 +244,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
swEnglish.setChecked(prefs.getBoolean("english", false)); swEnglish.setChecked(prefs.getBoolean("english", false));
swAuthentication.setChecked(prefs.getBoolean("authentication", false)); swAuthentication.setChecked(prefs.getBoolean("authentication", false));
swParanoid.setChecked(prefs.getBoolean("paranoid", true));
swWatchdog.setChecked(prefs.getBoolean("watchdog", true)); swWatchdog.setChecked(prefs.getBoolean("watchdog", true));
swUpdates.setChecked(prefs.getBoolean("updates", true)); swUpdates.setChecked(prefs.getBoolean("updates", true));
swUpdates.setVisibility(Helper.isPlayStoreInstall(getContext()) ? View.GONE : View.VISIBLE); swUpdates.setVisibility(Helper.isPlayStoreInstall(getContext()) ? View.GONE : View.VISIBLE);

@ -85,9 +85,6 @@ public class HtmlHelper {
private static final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory); private static final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
static String sanitize(Context context, String html, boolean show_images) { static String sanitize(Context context, String html, boolean show_images) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean paranoid = prefs.getBoolean("paranoid", true);
Document parsed = Jsoup.parse(html); Document parsed = Jsoup.parse(html);
// <html xmlns:v="urn:schemas-microsoft-com:vml" // <html xmlns:v="urn:schemas-microsoft-com:vml"
@ -225,9 +222,11 @@ public class HtmlHelper {
table.tagName("div"); table.tagName("div");
// Images // Images
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean disable_tracking = prefs.getBoolean("disable_tracking", true);
for (Element img : document.select("img")) { for (Element img : document.select("img")) {
// Remove link tracking pixels // Remove link tracking pixels
if (paranoid && isTrackingPixel(img)) { if (disable_tracking && isTrackingPixel(img)) {
String src = img.attr("src"); String src = img.attr("src");
img.removeAttr("src"); img.removeAttr("src");
img.tagName("a"); img.tagName("a");

@ -62,6 +62,29 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbSecure" /> app:layout_constraintTop_toBottomOf="@id/cbSecure" />
<Button
android:id="@+id/btnOwner"
style="@style/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:minWidth="0dp"
android:minHeight="0dp"
android:text="@string/title_check_owner"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbSanitize" />
<eu.faircode.email.ContentLoadingProgressBar
android:id="@+id/pbWait"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="@id/btnOwner"
app:layout_constraintStart_toEndOf="@id/btnOwner"
app:layout_constraintTop_toTopOf="@id/btnOwner" />
<TextView <TextView
android:id="@+id/tvOwnerTitle" android:id="@+id/tvOwnerTitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -71,7 +94,7 @@
android:text="@string/title_ip_owner" android:text="@string/title_ip_owner"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbSanitize" /> app:layout_constraintTop_toBottomOf="@id/btnOwner" />
<TextView <TextView
android:id="@+id/tvHost" android:id="@+id/tvHost"

@ -157,6 +157,17 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swAutoRead" app:layout_constraintTop_toBottomOf="@id/swAutoRead"
app:switchPadding="12dp" /> app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swDisableTracking"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_tracking"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swAutoMove"
app:switchPadding="12dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -22,6 +22,7 @@
android:id="@+id/swBadge" android:id="@+id/swBadge"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="true"
android:text="@string/title_advanced_badge" android:text="@string/title_advanced_badge"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -116,37 +117,15 @@
app:layout_constraintTop_toBottomOf="@id/tvEnglishHint" app:layout_constraintTop_toBottomOf="@id/tvEnglishHint"
app:switchPadding="12dp" /> app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swParanoid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_paranoid"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swAuthentication"
app:switchPadding="12dp" />
<TextView
android:id="@+id/tvParanoidHint"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginEnd="48dp"
android:text="@string/title_advanced_paranoid_hint"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swParanoid" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat
android:id="@+id/swWatchdog" android:id="@+id/swWatchdog"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_watchdog" android:text="@string/title_advanced_watchdog"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvParanoidHint" app:layout_constraintTop_toBottomOf="@id/swAuthentication"
app:switchPadding="12dp" /> app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat
@ -154,6 +133,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_updates" android:text="@string/title_advanced_updates"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swWatchdog" app:layout_constraintTop_toBottomOf="@id/swWatchdog"

@ -221,6 +221,7 @@
<string name="title_advanced_autonext">Automatically go to next conversation on close conversation</string> <string name="title_advanced_autonext">Automatically go to next conversation on close conversation</string>
<string name="title_advanced_autoread">Automatically mark messages read on moving messages</string> <string name="title_advanced_autoread">Automatically mark messages read on moving messages</string>
<string name="title_advanced_automove">Confirm moving messages</string> <string name="title_advanced_automove">Confirm moving messages</string>
<string name="title_advanced_tracking">Automatically recognize and disable tracking images</string>
<string name="title_advanced_notify_preview">Show message preview in notifications</string> <string name="title_advanced_notify_preview">Show message preview in notifications</string>
<string name="title_advanced_notify_actions">Notification actions</string> <string name="title_advanced_notify_actions">Notification actions</string>
@ -239,7 +240,6 @@
<string name="title_advanced_sync_subscribed">Synchronize subscribed folders only</string> <string name="title_advanced_sync_subscribed">Synchronize subscribed folders only</string>
<string name="title_advanced_english">Force English language</string> <string name="title_advanced_english">Force English language</string>
<string name="title_advanced_authentication">Show a warning when the receiving server could not authenticate the message</string> <string name="title_advanced_authentication">Show a warning when the receiving server could not authenticate the message</string>
<string name="title_advanced_paranoid">Extra privacy features</string>
<string name="title_advanced_watchdog">Periodically check if FairEmail is still active</string> <string name="title_advanced_watchdog">Periodically check if FairEmail is still active</string>
<string name="title_advanced_updates">Check for updates</string> <string name="title_advanced_updates">Check for updates</string>
<string name="title_advanced_crash_reports">Send error reports</string> <string name="title_advanced_crash_reports">Send error reports</string>
@ -274,7 +274,6 @@
<string name="title_advanced_badge_hint">Only available on supported launchers</string> <string name="title_advanced_badge_hint">Only available on supported launchers</string>
<string name="title_advanced_subscribed_only_hint">Enabling this will delete all local folders without subscription</string> <string name="title_advanced_subscribed_only_hint">Enabling this will delete all local folders without subscription</string>
<string name="title_advanced_english_hint">This will restart the app</string> <string name="title_advanced_english_hint">This will restart the app</string>
<string name="title_advanced_paranoid_hint">See the FAQ for details</string>
<string name="title_advanced_debug_hint">Enable extra logging and show debug information at various places</string> <string name="title_advanced_debug_hint">Enable extra logging and show debug information at various places</string>
<string name="title_select">Select &#8230;</string> <string name="title_select">Select &#8230;</string>
@ -704,6 +703,7 @@
<string name="title_link_secured">Link is secure</string> <string name="title_link_secured">Link is secure</string>
<string name="title_sanitize_link">Remove tracking parameters</string> <string name="title_sanitize_link">Remove tracking parameters</string>
<string name="title_insecure_link">This link is insecure</string> <string name="title_insecure_link">This link is insecure</string>
<string name="title_check_owner">Check owner</string>
<string name="title_ip_owner">Owner IP address</string> <string name="title_ip_owner">Owner IP address</string>
<string name="title_select_app">Select app</string> <string name="title_select_app">Select app</string>
<string name="title_updated">There is an update to version %1$s available</string> <string name="title_updated">There is an update to version %1$s available</string>

Loading…
Cancel
Save