diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 4bba02a5..e07e2e7a 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1062,10 +1062,6 @@ public final class app/revanced/patches/tumblr/fixes/FixOldVersionsPatch : app/r public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { - public static final field INSTANCE Lapp/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint; -} - public final class app/revanced/patches/tumblr/live/DisableTumblrLivePatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/tumblr/live/DisableTumblrLivePatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt index 9fe883d9..4a337785 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt @@ -5,34 +5,63 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.tumblr.fixes.fingerprints.AddQueryParamFingerprint import app.revanced.patches.tumblr.fixes.fingerprints.HttpPathParserFingerprint import app.revanced.util.exception @Patch( name = "Fix old versions", description = "Fixes old versions of the app (v33.2 and earlier) breaking due to Tumblr removing remnants of Tumblr" + - " Live from the API, which causes many requests to fail. This patch has no effect on newer versions of the app.", + " Live from the API, which causes many requests to fail. This patch has no effect on newer versions of the app.", compatiblePackages = [CompatiblePackage("com.tumblr")], use = false, ) @Suppress("unused") object FixOldVersionsPatch : BytecodePatch( - setOf(HttpPathParserFingerprint), + setOf(HttpPathParserFingerprint, AddQueryParamFingerprint), ) { - override fun execute(context: BytecodeContext) = + override fun execute(context: BytecodeContext) { + val liveQueryParameters = listOf( + ",?live_now", + ",?live_streaming_user_id", + ) + HttpPathParserFingerprint.result?.let { val endIndex = it.scanResult.patternScanResult!!.endIndex - - it.mutableMethod.addInstructions( - endIndex + 1, - """ - # Remove "?live_now" from the request path p2. - # p2 = p2.replace(p1, p3) - const-string p1, ",?live_now" - const-string p3, "" - invoke-virtual {p2, p1, p3}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; - move-result-object p2 - """, - ) + // Remove the live query parameters from the path when it's specified via a @METHOD annotation. + for (liveQueryParameter in liveQueryParameters) { + it.mutableMethod.addInstructions( + endIndex + 1, + """ + # urlPath = urlPath.replace(liveQueryParameter, "") + const-string p1, "$liveQueryParameter" + const-string p3, "" + invoke-virtual {p2, p1, p3}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; + move-result-object p2 + """, + ) + } } ?: throw HttpPathParserFingerprint.exception + + AddQueryParamFingerprint.result?.let { + // Remove the live query parameters when passed via a parameter which has the @Query annotation. + // e.g. an API call could be defined like this: + // @GET("api/me/info") + // ApiResponse getCurrentUserInfo(@Query("fields[blog]") String value) + // which would result in the path "api/me/inf0?fields[blog]=${value}" + // Here we make sure that this value doesn't contain the broken query parameters. + for (liveQueryParameter in liveQueryParameters) { + it.mutableMethod.addInstructions( + 0, + """ + # queryParameterValue = queryParameterValue.replace(liveQueryParameter, "") + const-string v0, "$liveQueryParameter" + const-string v1, "" + invoke-virtual {p2, v0, v1}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; + move-result-object p2 + """, + ) + } + } ?: throw AddQueryParamFingerprint.exception + } } diff --git a/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/AddQueryParamFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/AddQueryParamFingerprint.kt new file mode 100644 index 00000000..a908d7e6 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/AddQueryParamFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.tumblr.fixes.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +// Fingerprint for the addQueryParam method from retrofit2 +// https://github.com/square/retrofit/blob/trunk/retrofit/src/main/java/retrofit2/RequestBuilder.java#L186 +// Injecting here allows modifying dynamically set query parameters +internal object AddQueryParamFingerprint : MethodFingerprint( + strings = listOf("Malformed URL. Base: ", ", Relative: "), + parameters = listOf("Ljava/lang/String;", "Ljava/lang/String;", "Z"), +) diff --git a/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt index 0ef376ed..e807ef22 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.tumblr.fixes.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode -// Fingerprint for the parseHttpMethodAndPath from retrofit2 +// Fingerprint for the parseHttpMethodAndPath method from retrofit2 // https://github.com/square/retrofit/blob/ebf87b10997e2136af4d335276fa950221852c64/retrofit/src/main/java/retrofit2/RequestFactory.java#L270-L302 // Injecting here allows modifying the path/query params of API endpoints defined via annotations -object HttpPathParserFingerprint : MethodFingerprint( +internal object HttpPathParserFingerprint : MethodFingerprint( strings = listOf("Only one HTTP method is allowed. Found: %s and %s."), opcodes = listOf( Opcode.IPUT_OBJECT, - Opcode.IPUT_BOOLEAN - ) -) \ No newline at end of file + Opcode.IPUT_BOOLEAN, + ), +)