|
| 1 | +// |
| 2 | +// Copyright 2024 Signal Messenger, LLC. |
| 3 | +// SPDX-License-Identifier: AGPL-3.0-only |
| 4 | +// |
| 5 | + |
| 6 | +package org.signal.libsignal.util |
| 7 | + |
| 8 | +import java.nio.charset.StandardCharsets |
| 9 | + |
| 10 | +// This whole helper can go away when we reach Android 26, which supports java.util.Base64. |
| 11 | +public class Base64 { |
| 12 | + public interface Impl { |
| 13 | + public fun decode(encoded: ByteArray): ByteArray |
| 14 | + public fun decodeUrl(encoded: ByteArray): ByteArray |
| 15 | + public fun encode(raw: ByteArray): String |
| 16 | + public fun encodeUrl(raw: ByteArray): String |
| 17 | + } |
| 18 | + |
| 19 | + companion object { |
| 20 | + @JvmStatic |
| 21 | + public fun decode(str: String): ByteArray = impl.decode(str.toByteArray(StandardCharsets.UTF_8)) |
| 22 | + |
| 23 | + @JvmStatic |
| 24 | + public fun decodeUrl(str: String): ByteArray = impl.decodeUrl(str.toByteArray(StandardCharsets.UTF_8)) |
| 25 | + |
| 26 | + @JvmStatic |
| 27 | + public fun encodeToString(input: ByteArray): String = impl.encode(input) |
| 28 | + |
| 29 | + @JvmStatic |
| 30 | + public fun encodeToStringUrl(input: ByteArray): String = impl.encodeUrl(input) |
| 31 | + |
| 32 | + val impl: Impl = run { |
| 33 | + // Prefer the Android class. If we preferred the JRE one, we'd only test the Android |
| 34 | + // codepath when testing on older emulators. |
| 35 | + try { |
| 36 | + try { |
| 37 | + var androidImpl = Class.forName("org.signal.libsignal.util.AndroidBase64") |
| 38 | + Impl::class.java.cast(androidImpl.getConstructor().newInstance()) |
| 39 | + } catch (notFoundException: ClassNotFoundException) { |
| 40 | + JavaBase64 |
| 41 | + } |
| 42 | + } catch (e: Exception) { |
| 43 | + throw AssertionError(e) |
| 44 | + } |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + private object JavaBase64 : Impl { |
| 49 | + public override fun decode(encoded: ByteArray): ByteArray = java.util.Base64.getDecoder().decode(encoded) |
| 50 | + |
| 51 | + public override fun decodeUrl(encoded: ByteArray): ByteArray = java.util.Base64.getUrlDecoder().decode(encoded) |
| 52 | + |
| 53 | + public override fun encode(raw: ByteArray): String = java.util.Base64.getEncoder().encodeToString(raw) |
| 54 | + |
| 55 | + public override fun encodeUrl( |
| 56 | + raw: ByteArray, |
| 57 | + ): String = java.util.Base64.getUrlEncoder().withoutPadding().encodeToString(raw) |
| 58 | + } |
| 59 | +} |
0 commit comments