mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-08 02:13:55 +01:00
feat(Instagram): Add Sanitize sharing links patch (#5986)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de> Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.extension.instagram.misc.privacy;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.privacy.LinkSanitizer;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class SanitizeSharingLinksPatch {
|
||||||
|
private static final LinkSanitizer sanitizer = new LinkSanitizer("igsh");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static String sanitizeSharingLink(String url) {
|
||||||
|
return sanitizer.sanitizeUrlString(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package app.revanced.extension.shared.patches;
|
package app.revanced.extension.shared.patches;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.privacy.LinkSanitizer;
|
||||||
import app.revanced.extension.shared.settings.BaseSettings;
|
import app.revanced.extension.shared.settings.BaseSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7,17 +8,18 @@ import app.revanced.extension.shared.settings.BaseSettings;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class SanitizeSharingLinksPatch {
|
public final class SanitizeSharingLinksPatch {
|
||||||
private static final String NEW_TRACKING_PARAMETER_REGEX = ".si=.+";
|
|
||||||
private static final String OLD_TRACKING_PARAMETER_REGEX = ".feature=.+";
|
private static final LinkSanitizer sanitizer = new LinkSanitizer(
|
||||||
|
"si",
|
||||||
|
"feature" // Old tracking parameter name, and may be obsolete.
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static String sanitize(String url) {
|
public static String sanitize(String url) {
|
||||||
if (BaseSettings.SANITIZE_SHARED_LINKS.get()) {
|
if (BaseSettings.SANITIZE_SHARED_LINKS.get()) {
|
||||||
url = url
|
url = sanitizer.sanitizeUrlString(url);
|
||||||
.replaceAll(NEW_TRACKING_PARAMETER_REGEX, "")
|
|
||||||
.replaceAll(OLD_TRACKING_PARAMETER_REGEX, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BaseSettings.REPLACE_MUSIC_LINKS_WITH_YOUTUBE.get()) {
|
if (BaseSettings.REPLACE_MUSIC_LINKS_WITH_YOUTUBE.get()) {
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package app.revanced.extension.shared.privacy;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips away specific parameters from URLs.
|
||||||
|
*/
|
||||||
|
public class LinkSanitizer {
|
||||||
|
|
||||||
|
private final Collection<String> parametersToRemove;
|
||||||
|
|
||||||
|
public LinkSanitizer(String ... parametersToRemove) {
|
||||||
|
final int parameterCount = parametersToRemove.length;
|
||||||
|
if (parameterCount == 0) {
|
||||||
|
throw new IllegalArgumentException("No parameters specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// List is faster if only checking a few parameters.
|
||||||
|
this.parametersToRemove = parameterCount > 4
|
||||||
|
? Set.of(parametersToRemove)
|
||||||
|
: List.of(parametersToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sanitizeUrlString(String url) {
|
||||||
|
try {
|
||||||
|
return sanitizeUri(Uri.parse(url)).toString();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "sanitizeUrlString failure: " + url, ex);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri sanitizeUri(Uri uri) {
|
||||||
|
try {
|
||||||
|
Uri.Builder builder = uri.buildUpon().clearQuery();
|
||||||
|
|
||||||
|
for (String paramName : uri.getQueryParameterNames()) {
|
||||||
|
if (!parametersToRemove.contains(paramName)) {
|
||||||
|
for (String value : uri.getQueryParameters(paramName)) {
|
||||||
|
builder.appendQueryParameter(paramName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri sanitizedUrl = builder.build();
|
||||||
|
Logger.printInfo(() -> "Sanitized url: " + uri + " to: " + sanitizedUrl);
|
||||||
|
|
||||||
|
return sanitizedUrl;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "sanitizeUri failure: " + uri, ex);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,11 @@
|
|||||||
package app.revanced.extension.spotify.misc.privacy;
|
package app.revanced.extension.spotify.misc.privacy;
|
||||||
|
|
||||||
import android.net.Uri;
|
import app.revanced.extension.shared.privacy.LinkSanitizer;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class SanitizeSharingLinksPatch {
|
public final class SanitizeSharingLinksPatch {
|
||||||
|
|
||||||
/**
|
private static final LinkSanitizer sanitizer = new LinkSanitizer(
|
||||||
* Parameters that are considered undesirable and should be stripped away.
|
|
||||||
*/
|
|
||||||
private static final List<String> SHARE_PARAMETERS_TO_REMOVE = List.of(
|
|
||||||
"si", // Share tracking parameter.
|
"si", // Share tracking parameter.
|
||||||
"utm_source" // Share source, such as "copy-link".
|
"utm_source" // Share source, such as "copy-link".
|
||||||
);
|
);
|
||||||
@@ -20,25 +13,7 @@ public final class SanitizeSharingLinksPatch {
|
|||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static String sanitizeUrl(String url) {
|
public static String sanitizeSharingLink(String url) {
|
||||||
try {
|
return sanitizer.sanitizeUrlString(url);
|
||||||
Uri uri = Uri.parse(url);
|
|
||||||
Uri.Builder builder = uri.buildUpon().clearQuery();
|
|
||||||
|
|
||||||
for (String paramName : uri.getQueryParameterNames()) {
|
|
||||||
if (!SHARE_PARAMETERS_TO_REMOVE.contains(paramName)) {
|
|
||||||
for (String value : uri.getQueryParameters(paramName)) {
|
|
||||||
builder.appendQueryParameter(paramName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String sanitizedUrl = builder.build().toString();
|
|
||||||
Logger.printInfo(() -> "Sanitized url " + url + " to " + sanitizedUrl);
|
|
||||||
return sanitizedUrl;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "sanitizeUrl failure with " + url, ex);
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,6 +288,10 @@ public final class app/revanced/patches/instagram/misc/links/OpenLinksExternally
|
|||||||
public static final fun getOpenLinksExternallyPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getOpenLinksExternallyPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/instagram/misc/privacy/SanitizeSharingLinksPatchKt {
|
||||||
|
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
||||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package app.revanced.patches.instagram.misc.privacy
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
internal val permalinkResponseJsonParserFingerprint = fingerprint {
|
||||||
|
strings("permalink", "PermalinkResponse")
|
||||||
|
custom { method, _ -> method.name == "parseFromJson" }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val storyUrlResponseJsonParserFingerprint = fingerprint {
|
||||||
|
strings("story_item_to_share_url", "StoryItemUrlResponse")
|
||||||
|
custom { method, _ -> method.name == "parseFromJson" }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val profileUrlResponseJsonParserFingerprint = fingerprint {
|
||||||
|
strings("profile_to_share_url", "ProfileUrlResponse")
|
||||||
|
custom { method, _ -> method.name == "parseFromJson" }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val liveUrlResponseJsonParserFingerprint = fingerprint {
|
||||||
|
strings("live_to_share_url", "LiveItemLinkUrlResponse")
|
||||||
|
custom { method, _ -> method.name == "parseFromJson" }
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package app.revanced.patches.instagram.misc.privacy
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
|
||||||
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
|
"Lapp/revanced/extension/instagram/misc/privacy/SanitizeSharingLinksPatch;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val sanitizeSharingLinksPatch = bytecodePatch(
|
||||||
|
name = "Sanitize sharing links",
|
||||||
|
description = "Removes the tracking query parameters from shared links.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
dependsOn(sharedExtensionPatch)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
arrayOf(
|
||||||
|
permalinkResponseJsonParserFingerprint,
|
||||||
|
storyUrlResponseJsonParserFingerprint,
|
||||||
|
profileUrlResponseJsonParserFingerprint,
|
||||||
|
liveUrlResponseJsonParserFingerprint
|
||||||
|
).forEach { fingerprint ->
|
||||||
|
fingerprint.method.apply {
|
||||||
|
val putSharingUrlIndex = indexOfFirstInstructionOrThrow(
|
||||||
|
fingerprint.stringMatches!!.first().index,
|
||||||
|
Opcode.IPUT_OBJECT
|
||||||
|
)
|
||||||
|
|
||||||
|
val sharingUrlRegister = getInstruction<TwoRegisterInstruction>(putSharingUrlIndex).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
putSharingUrlIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { v$sharingUrlRegister }, $EXTENSION_CLASS_DESCRIPTOR->sanitizeSharingLink(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v$sharingUrlRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import app.revanced.patcher.patch.bytecodePatch
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val sanitizeUrlQueryPatch = bytecodePatch(
|
val sanitizeUrlQueryPatch = bytecodePatch(
|
||||||
name = "Sanitize sharing links",
|
name = "Sanitize sharing links",
|
||||||
description = "Removes (tracking) query parameters from the URLs when sharing links.",
|
description = "Removes the tracking query parameters from shared links.",
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.reddit.frontpage")
|
compatibleWith("com.reddit.frontpage")
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val sanitizeSharingLinksPatch = bytecodePatch(
|
val sanitizeSharingLinksPatch = bytecodePatch(
|
||||||
name = "Sanitize sharing links",
|
name = "Sanitize sharing links",
|
||||||
description = "Removes the tracking query parameters from links before they are shared.",
|
description = "Removes the tracking query parameters from shared links.",
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.spotify.music")
|
compatibleWith("com.spotify.music")
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ val sanitizeSharingLinksPatch = bytecodePatch(
|
|||||||
|
|
||||||
execute {
|
execute {
|
||||||
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" +
|
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||||
"sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;"
|
"sanitizeSharingLink(Ljava/lang/String;)Ljava/lang/String;"
|
||||||
|
|
||||||
val copyFingerprint = if (shareCopyUrlFingerprint.originalMethodOrNull != null) {
|
val copyFingerprint = if (shareCopyUrlFingerprint.originalMethodOrNull != null) {
|
||||||
shareCopyUrlFingerprint
|
shareCopyUrlFingerprint
|
||||||
|
|||||||
Reference in New Issue
Block a user