diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt new file mode 100644 index 000000000..f0cffbea7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/AbstractChangeOAuthClientIdPatch.kt @@ -0,0 +1,57 @@ +package app.revanced.patches.reddit.customclients + +import android.os.Environment +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.patch.* +import app.revanced.patches.reddit.customclients.boostforreddit.api.patch.ChangeOAuthClientIdPatch +import app.revanced.patches.reddit.customclients.syncforreddit.api.patch.ChangeOAuthClientIdPatch.Companion.clientId +import java.io.File + +abstract class AbstractChangeOAuthClientIdPatch( + private val redirectUri: String, + private val fingerprint: MethodFingerprint, +) : BytecodePatch(listOf(fingerprint)) { + override fun execute(context: BytecodeContext): PatchResult { + if (ChangeOAuthClientIdPatch.clientId == null) { + // Test if on Android + try { + Class.forName("android.os.Environment") + } catch (e: ClassNotFoundException) { + return PatchResultError("No client ID provided") + } + + File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also { + if (it.exists()) return@also + + val error = """ + In order to use this patch, you need to provide a client ID. + You can do this by creating a file at ${it.absolutePath} with the client ID as its content. + Alternatively, you can provide the client ID using patch options. + + You can get your client ID from https://www.reddit.com/prefs/apps. + The application type has to be "installed app" and the redirect URI has to be set to "$redirectUri" + """.trimIndent() + + return PatchResultError(error) + }.let { clientId = it.readText().trim() } + } + + return fingerprint.patch(context) + } + + abstract fun MethodFingerprint.patch(context: BytecodeContext): PatchResult + + companion object Options { + open class ChangeOAuthClientIdOptionsContainer : OptionsContainer() { + var clientId by option( + PatchOption.StringOption( + "client-id", + null, + "OAuth client ID", + "The Reddit OAuth client ID." + ) + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt new file mode 100644 index 000000000..c8ffa4bae --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/GetClientIdFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint + +object GetClientIdFingerprint : MethodFingerprint( + customFingerprint = custom@{ methodDef, classDef -> + if (!classDef.type.endsWith("Credentials;")) return@custom false + + methodDef.name == "getClientId" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt new file mode 100644 index 000000000..c3b7c966f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/patch/ChangeOAuthClientIdPatch.kt @@ -0,0 +1,36 @@ +package app.revanced.patches.reddit.customclients.boostforreddit.api.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.* +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch +import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint + +@Patch +@Name("change-oauth-client-id") +@Description("Changes the OAuth client ID in Boost for Reddit.") +@Compatibility([Package("com.rubenmayayo.reddit")]) +@Version("0.0.1") +class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch( + "http://rubenmayayo.com", + GetClientIdFingerprint +) { + override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult { + result?.mutableMethod?.addInstructions( + 0, + """ + const-string v0, "$clientId" + return-object v0 + """ + ) ?: return toErrorResult() + + return PatchResultSuccess() + } + + companion object : Options.ChangeOAuthClientIdOptionsContainer() +} diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt similarity index 79% rename from src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt index ff01b38cf..40c98bc2b 100644 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.syncforreddit.ads.fingerprints +package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt similarity index 79% rename from src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt index 2b15bf39f..e743602f2 100644 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/patch/DisableAdsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.syncforreddit.ads.patch +package app.revanced.patches.reddit.customclients.syncforreddit.ads.patch import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.* @@ -9,8 +9,8 @@ import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint -import app.revanced.patches.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch +import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint +import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch @Patch @Name("disable-ads") diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt similarity index 69% rename from src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt index 8eceddfbf..0e517e1d3 100644 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetAuthorizationStringFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.syncforreddit.api.fingerprints +package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt similarity index 65% rename from src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt index a07208726..0d4fee94b 100644 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/fingerprints/GetBearerTokenFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.syncforreddit.api.fingerprints +package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt new file mode 100644 index 000000000..c8e3bd409 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt @@ -0,0 +1,68 @@ +package app.revanced.patches.reddit.customclients.syncforreddit.api.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.* +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch +import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint +import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.ReferenceInstruction +import org.jf.dexlib2.iface.reference.StringReference +import java.util.* + + +@Patch +@Name("change-oauth-client-id") +@Description("Changes the OAuth client ID.") +@Compatibility([Package("com.laurencedawson.reddit_sync"), Package("com.laurencedawson.reddit_sync.pro")]) +@Version("0.0.1") +class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch( + "http://redditsync/auth", + GetAuthorizationStringFingerprint, +) { + override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult { + result?.also { result -> + GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply { + val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8)) + addInstructions( + 0, + """ + const-string v0, "Basic $auth" + return-object v0 + """ + ) + } ?: return GetBearerTokenFingerprint.toErrorResult() + }?.let { + val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index + + it.mutableMethod.apply { + val authorizationStringInstruction = getInstruction(occurrenceIndex) + val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA + val reference = authorizationStringInstruction.reference as StringReference + + val newAuthorizationUrl = reference.string.replace( + "client_id=.*?&".toRegex(), + "client_id=${clientId!!}&" + ) + + replaceInstruction( + occurrenceIndex, + "const-string v$targetRegister, \"$newAuthorizationUrl\"" + ) + } + } ?: return toErrorResult() + + return PatchResultSuccess() + } + + companion object : Options.ChangeOAuthClientIdOptionsContainer() +} diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt similarity index 100% rename from src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt similarity index 92% rename from src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt index feb02a06c..b0e63f681 100644 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.syncforreddit.detection.piracy.patch +package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt deleted file mode 100644 index 2e81de61b..000000000 --- a/src/main/kotlin/app/revanced/patches/syncforreddit/api/patch/ChangeOAuthClientIdPatch.kt +++ /dev/null @@ -1,101 +0,0 @@ -package app.revanced.patches.syncforreddit.api.patch - -import android.os.Environment -import app.revanced.patcher.annotation.* -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint -import app.revanced.patches.syncforreddit.api.fingerprints.GetBearerTokenFingerprint -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.StringReference -import java.io.File -import java.util.* - -@Patch -@Name("change-oauth-client-id") -@Description("Changes the OAuth client ID.") -@Compatibility( - [ - Package("com.laurencedawson.reddit_sync"), - Package("com.laurencedawson.reddit_sync.pro") - ] -) -@Version("0.0.1") -class ChangeOAuthClientIdPatch : BytecodePatch( - listOf(GetAuthorizationStringFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - if (clientId == null) { - // Test if on Android - try { - Class.forName("android.os.Environment") - } catch (e: ClassNotFoundException) { - return PatchResultError("No client ID provided") - } - - File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also { - if (it.exists()) return@also - - val error = """ - In order to use this patch, you need to provide a client ID. - You can do this by creating a file at ${it.absolutePath} with the client ID as its content. - Alternatively, you can provide the client ID using patch options. - - You can get your client ID from https://www.reddit.com/prefs/apps. - The application type has to be "installed app" and the redirect URI has to be set to "http://redditsync/auth" - """.trimIndent() - - return PatchResultError(error) - }.let { clientId = it.readText().trim() } - } - - GetAuthorizationStringFingerprint.result?.also { result -> - GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply { - val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8)) - addInstructions( - 0, - """ - const-string v0, "Basic $auth" - return-object v0 - """ - ) - } ?: return PatchResultError("Could not find required method to patch.") - }?.let { - val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index - - it.mutableMethod.apply { - val authorizationStringInstruction = getInstruction(occurrenceIndex) - val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA - val reference = authorizationStringInstruction.reference as StringReference - - val newAuthorizationUrl = reference.string.replace( - "client_id=.*?&".toRegex(), - "client_id=${clientId!!}&" - ) - - replaceInstruction( - occurrenceIndex, - "const-string v$targetRegister, \"$newAuthorizationUrl\"" - ) - } - } ?: return PatchResultError("Could not find required method to patch.") - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - var clientId by option( - PatchOption.StringOption( - "client-id", - null, - "OAuth client ID", - "The client ID to use for OAuth." - ) - ) - } -}