From 771eb3000cdd07d0c7faebf0f7b85d2bf1a5e996 Mon Sep 17 00:00:00 2001 From: GeopJr Date: Sun, 18 Jun 2023 14:41:52 +0300 Subject: [PATCH] feat: remove tracking ids from links (#305) * feat: remove tracking ids from links Co-authored-by: Chris Talbot * fix: handle fragment * fix: only check key * chore: remove dup rules * feat: use Uri * fix(fallback): do not handle url if incomplete * chore(fallback): search_terms => query_params * fix(fallback): & => = it's supposed to ignore it if there's no values * chore: add warning --------- Co-authored-by: Chris Talbot --- data/dev.geopjr.Tuba.gschema.xml | 3 + data/ui/dialogs/preferences.ui | 12 ++++ src/Dialogs/Preferences.vala | 2 + src/Services/Settings.vala | 2 + src/Utils/Host.vala | 2 + src/Utils/Tracking.vala | 114 +++++++++++++++++++++++++++++++ src/Utils/meson.build | 1 + 7 files changed, 136 insertions(+) create mode 100644 src/Utils/Tracking.vala diff --git a/data/dev.geopjr.Tuba.gschema.xml b/data/dev.geopjr.Tuba.gschema.xml index e0d6d0a88..88b49f13d 100644 --- a/data/dev.geopjr.Tuba.gschema.xml +++ b/data/dev.geopjr.Tuba.gschema.xml @@ -48,6 +48,9 @@ false + + true + -1 diff --git a/data/ui/dialogs/preferences.ui b/data/ui/dialogs/preferences.ui index 215b6d095..334fdec30 100644 --- a/data/ui/dialogs/preferences.ui +++ b/data/ui/dialogs/preferences.ui @@ -111,6 +111,18 @@ + + + Strip tracking parameters from links + strip_tracking + It can lead to broken links + + + center + + + + diff --git a/src/Dialogs/Preferences.vala b/src/Dialogs/Preferences.vala index bf7fcde76..625ace645 100644 --- a/src/Dialogs/Preferences.vala +++ b/src/Dialogs/Preferences.vala @@ -15,6 +15,7 @@ public class Tuba.Dialogs.Preferences : Adw.PreferencesWindow { [GtkChild] unowned Switch hide_preview_cards; [GtkChild] unowned Switch larger_font_size; [GtkChild] unowned Switch larger_line_height; + [GtkChild] unowned Switch strip_tracking; private bool lang_changed { get; set; default=false; } @@ -59,6 +60,7 @@ public class Tuba.Dialogs.Preferences : Adw.PreferencesWindow { settings.bind ("hide-preview-cards", hide_preview_cards, "active", SettingsBindFlags.DEFAULT); settings.bind ("larger-font-size", larger_font_size, "active", SettingsBindFlags.DEFAULT); settings.bind ("larger-line-height", larger_line_height, "active", SettingsBindFlags.DEFAULT); + settings.bind ("strip-tracking", strip_tracking, "active", SettingsBindFlags.DEFAULT); post_visibility_combo_row.notify["selected-item"].connect(on_post_visibility_changed); diff --git a/src/Services/Settings.vala b/src/Services/Settings.vala index d608134af..8dfe518ac 100644 --- a/src/Services/Settings.vala +++ b/src/Services/Settings.vala @@ -16,6 +16,7 @@ public class Tuba.Settings : GLib.Settings { public bool larger_font_size { get; set; } public bool larger_line_height { get; set; } public bool aggressive_resolving { get; set; } + public bool strip_tracking { get; set; } public Settings () { Object (schema_id: Build.DOMAIN); @@ -32,6 +33,7 @@ public class Tuba.Settings : GLib.Settings { init ("larger-font-size"); init ("larger-line-height"); init ("aggressive-resolving"); + init ("strip-tracking"); } void init (string key) { diff --git a/src/Utils/Host.vala b/src/Utils/Host.vala index b48339450..deacf6328 100644 --- a/src/Utils/Host.vala +++ b/src/Utils/Host.vala @@ -9,6 +9,8 @@ public class Tuba.Host { if (!(":" in uri)) uri = "file://" + _uri; + if (settings.strip_tracking) + uri = Tracking.strip_utm (uri); message (@"Opening URI: $uri"); try { var success = AppInfo.launch_default_for_uri (uri, null); diff --git a/src/Utils/Tracking.vala b/src/Utils/Tracking.vala new file mode 100644 index 000000000..9c6a54a74 --- /dev/null +++ b/src/Utils/Tracking.vala @@ -0,0 +1,114 @@ +// Ported from Chatty +// https://source.puri.sm/Librem5/chatty/-/merge_requests/1229 + +public class Tuba.Tracking { + /* https://github.com/brave/brave-core/blob/5fcad3e35bac6fea795941fd8189a59d79d488bc/browser/net/brave_site_hacks_network_delegate_helper.cc#L29-L67 */ + public const string[] tracking_ids = { + // Strip any utm_ based ones + "utm_", + // https://github.com/brave/brave-browser/issues/4239 + "fbclid", "gclid", "msclkid", "mc_eid", + // https://github.com/brave/brave-browser/issues/9879 + "dclid", + // https://github.com/brave/brave-browser/issues/13644 + "oly_anon_id", "oly_enc_id", + // https://github.com/brave/brave-browser/issues/11579 + "_openstat", + // https://github.com/brave/brave-browser/issues/11817 + "vero_conv", "vero_id", + // https://github.com/brave/brave-browser/issues/13647 + "wickedid", + // https://github.com/brave/brave-browser/issues/11578 + "yclid", + // https://github.com/brave/brave-browser/issues/8975 + "__s", + // https://github.com/brave/brave-browser/issues/17451 + "rb_clickid", + // https://github.com/brave/brave-browser/issues/17452 + "s_cid", + // https://github.com/brave/brave-browser/issues/17507 + "ml_subscriber", "ml_subscriber_hash", + // https://github.com/brave/brave-browser/issues/18020 + "twclid", + // https://github.com/brave/brave-browser/issues/18758 + "gbraid", "wbraid", + // https://github.com/brave/brave-browser/issues/9019 + "_hsenc", "__hssc", "__hstc", "__hsfp", "hsCtaTracking", + // https://github.com/brave/brave-browser/issues/22082 + "oft_id", "oft_k", "oft_lk", "oft_d", "oft_c", "oft_ck", "oft_ids", "oft_sk", + // https://github.com/brave/brave-browser/issues/11580 + "igshid", + }; + + public static string strip_utm (string url) { + if (!("?" in url)) return url; + + try { + var uri = Uri.parse (url, UriFlags.NONE); + return strip_utm_from_uri (uri).to_string (); + } catch (GLib.UriError e) { + warning (e.message); + return strip_utm_fallback (url); + } + } + + public static Uri strip_utm_from_uri (Uri uri) throws UriError { + var uri_params = Uri.parse_params (uri.get_query ()); + string[] res_params = {}; + + uri_params.foreach_remove ((key, val) => { + var not_tracking_id = true; + foreach (var id in tracking_ids) { + if (id in key.down ()) { + not_tracking_id = false; + break; + } + } + + if (not_tracking_id) res_params += @"$key=$val"; + + return !not_tracking_id; + }); + + string? res_query = res_params.length > 0 ? string.joinv("&", res_params) : null; + return Uri.build ( + uri.get_flags (), + uri.get_scheme(), + uri.get_userinfo (), + uri.get_host (), + uri.get_port (), + uri.get_path (), + res_query, + uri.get_fragment () + ); + } + + public static string strip_utm_fallback (string url) { + var split_url = url.split_set ("?", 2); + if (split_url[1].index_of_char ('=') == -1) return url; + + var query_params = split_url[1].split_set ("&"); + var str = @"$(split_url[0])?"; + + var fragment_offset = split_url[1].last_index_of_char ('#'); + var fragment = fragment_offset > -1 ? split_url[1].substring(fragment_offset) : ""; + + foreach (var param in query_params) { + var not_tracking_id = true; + + foreach (var id in tracking_ids) { + var index_of_eq = param.index_of_char ('='); + if (index_of_eq > -1 && id in param.slice (0, index_of_eq).down ()) { + not_tracking_id = false; + break; + } + } + + if (not_tracking_id) { + str += @"$(param)&"; + } + } + + return @"$(str.slice(0, -1))$fragment"; + } +} diff --git a/src/Utils/meson.build b/src/Utils/meson.build index 240751856..186b6cd90 100644 --- a/src/Utils/meson.build +++ b/src/Utils/meson.build @@ -3,4 +3,5 @@ sources += files( 'Host.vala', 'Html.vala', 'Locale.vala', + 'Tracking.vala', )