diff --git a/app/libs/common.jar b/app/libs/common.jar deleted file mode 100644 index 8e925135..00000000 Binary files a/app/libs/common.jar and /dev/null differ diff --git a/app/src/main/java/com/huanchengfly/tieba/post/App.kt b/app/src/main/java/com/huanchengfly/tieba/post/App.kt index 8edb58fb..201d99ef 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/App.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/App.kt @@ -40,10 +40,10 @@ import com.huanchengfly.tieba.post.utils.EmoticonManager import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil import com.huanchengfly.tieba.post.utils.ThemeUtil import com.huanchengfly.tieba.post.utils.TiebaUtil -import com.huanchengfly.tieba.post.utils.UIDUtil import com.huanchengfly.tieba.post.utils.Util import com.huanchengfly.tieba.post.utils.appPreferences import com.huanchengfly.tieba.post.utils.applicationMetaData +import com.huanchengfly.tieba.post.utils.helios.Base32 import com.huanchengfly.tieba.post.utils.launchUrl import com.microsoft.appcenter.AppCenter import com.microsoft.appcenter.analytics.Analytics @@ -65,9 +65,7 @@ class App : Application(), IApp, IGetter, SketchFactory { private val mActivityList: MutableList = mutableListOf() override fun onOAIDGetComplete(result: String) { - oaid = UIDUtil.Encoder( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=" - ).encode(result.encodeToByteArray()) + oaid = Base32.encode(result.encodeToByteArray()) } override fun onOAIDGetError(error: Exception) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt index fe2358c4..e8957bea 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt @@ -1,7 +1,6 @@ package com.huanchengfly.tieba.post.api.retrofit import android.os.Build -import android.webkit.WebView import com.huanchengfly.tieba.post.App import com.huanchengfly.tieba.post.api.Header import com.huanchengfly.tieba.post.api.Param @@ -47,7 +46,8 @@ object RetrofitTiebaApi { internal val randomClientId = "wappc_${initTime}_${(Math.random() * 1000).roundToInt()}" private val stParamInterceptor = StParamInterceptor() private val connectionPool = ConnectionPool(32, 5, TimeUnit.MINUTES) - private val defaultUserAgent = WebView(App.INSTANCE).settings.userAgentString + private val defaultUserAgent: String = + "Mozilla/5.0 (Linux; Android ${Build.VERSION.RELEASE}; ${Build.MODEL} Build/TKQ1.220829.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.86 Mobile Safari/537.36" private val defaultCommonParamInterceptor = CommonParamInterceptor( Param.BDUSS to { AccountUtil.getBduss() }, @@ -74,10 +74,10 @@ object RetrofitTiebaApi { defaultCommonHeaderInterceptor, CommonHeaderInterceptor( Header.USER_AGENT to { "bdtb for Android 8.2.2" }, - Header.CUID to { UIDUtil.getFinalCUID() } + Header.CUID to { UIDUtil.finalCUID } ), defaultCommonParamInterceptor + CommonParamInterceptor( - Param.CUID to { UIDUtil.getFinalCUID() }, + Param.CUID to { UIDUtil.finalCUID }, Param.FROM to { "baidu_appstore" }, Param.CLIENT_VERSION to { "8.2.2" } ), @@ -106,12 +106,12 @@ object RetrofitTiebaApi { defaultCommonHeaderInterceptor, CommonHeaderInterceptor( Header.USER_AGENT to { "bdtb for Android 7.2.0.0" }, - Header.CUID to { UIDUtil.getFinalCUID() }, - Header.CUID_GALAXY2 to { UIDUtil.getFinalCUID() } + Header.CUID to { UIDUtil.finalCUID }, + Header.CUID_GALAXY2 to { UIDUtil.finalCUID } ), defaultCommonParamInterceptor + CommonParamInterceptor( - Param.CUID to { UIDUtil.getFinalCUID() }, - Param.CUID_GALAXY2 to { UIDUtil.getFinalCUID() }, + Param.CUID to { UIDUtil.finalCUID }, + Param.CUID_GALAXY2 to { UIDUtil.finalCUID }, Param.FROM to { "1021636m" }, Param.CLIENT_VERSION to { "7.2.0.0" }, Param.SUBAPP_TYPE to { "mini" } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchPage.kt new file mode 100644 index 00000000..c14ebf0b --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchPage.kt @@ -0,0 +1,12 @@ +package com.huanchengfly.tieba.post.ui.page.search + +import androidx.compose.runtime.Composable +import com.ramcosta.composedestinations.annotation.Destination + +@Destination +@Composable +fun SearchPage( + searchWord: String? = null +) { + +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchViewModel.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchViewModel.kt new file mode 100644 index 00000000..de18eebd --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/search/SearchViewModel.kt @@ -0,0 +1,20 @@ +package com.huanchengfly.tieba.post.ui.page.search + +import com.huanchengfly.tieba.post.models.database.SearchHistory + +class SearchViewModel + +sealed interface SearchUiIntent { + data class Init(val keyword: String) : SearchUiIntent + + data class SubmitKeyword(val keyword: String) : SearchUiIntent +} + +sealed interface SearchPartialChange + +data class SearchUiState( + val keyword: String = "", + val searchHistories: List = emptyList() +) + +sealed interface SearchUiEvent \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/CuidUtils.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/CuidUtils.kt index 5b1edf79..208bf91e 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/CuidUtils.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/CuidUtils.kt @@ -1,12 +1,12 @@ package com.huanchengfly.tieba.post.utils +import com.huanchengfly.tieba.post.utils.helios.Base32 +import com.huanchengfly.tieba.post.utils.helios.Hasher + object CuidUtils { fun getNewCuid(): String { - val cuid = UIDUtil.getCUID() - val b = aid.common.cc.b().y(cuid.encodeToByteArray()) - val encode = UIDUtil.Encoder( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=" - ).encode(b) + val cuid = UIDUtil.cUID + val encode = Base32.encode(Hasher.hash(cuid.toByteArray())) return "$cuid|V$encode" } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.java deleted file mode 100644 index 376422f8..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.huanchengfly.tieba.post.utils; - -import android.annotation.SuppressLint; -import android.os.Build; -import android.provider.Settings; -import android.text.TextUtils; - -import com.huanchengfly.tieba.post.App; - -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.util.UUID; - -public class UIDUtil { - @SuppressLint("HardwareIds") - public static String getAndroidId() { - return getAndroidId(""); - } - - @SuppressLint("HardwareIds") - public static String getAndroidId(String defaultValue) { - String androidId = Settings.Secure.getString(App.getINSTANCE().getContentResolver(), Settings.Secure.ANDROID_ID); - return androidId == null ? defaultValue : androidId; - } - - public static String getAid() { - String raw = "com.helios" + getAndroidId("000000000") + getUUID(); - byte[] bytes = getSHA1(raw); - return aid.ids.a.ag("A00", new Encoder("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=").encode(bytes)); - } - - public static byte[] getSHA1(String str) { - byte[] sha1 = null; - try { - MessageDigest digest = MessageDigest.getInstance("SHA1"); - sha1 = digest.digest(str.getBytes(StandardCharsets.UTF_8)); - } catch (Exception e) { - e.printStackTrace(); - } - return sha1; - } - - public static String getNewCUID() { - return "baidutiebaapp" + getUUID(); - } - - public static String getCUID() { - String androidId = getAndroidId(); - String imei = MobileInfoUtil.getIMEI(App.getINSTANCE()); - if (TextUtils.isEmpty(imei)) { - imei = "0"; - } - return MD5Util.toMd5((Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? imei + androidId + getUUID() : "com.baidu" + androidId).getBytes()).toUpperCase(); - } - - public static String getFinalCUID() { - String imei = MobileInfoUtil.getIMEI(App.getINSTANCE()); - if (TextUtils.isEmpty(imei)) { - imei = "0"; - } - return getCUID() + "|" + new StringBuffer(imei).reverse(); - } - - @SuppressLint("ApplySharedPref") - public static String getUUID() { - String uuid = SharedPreferencesUtil.get(App.getINSTANCE(), SharedPreferencesUtil.SP_APP_DATA) - .getString("uuid", null); - if (uuid == null) { - uuid = UUID.randomUUID().toString(); - SharedPreferencesUtil.get(App.getINSTANCE(), SharedPreferencesUtil.SP_APP_DATA) - .edit() - .putString("uuid", uuid) - .apply(); - } - return uuid; - } - - - public static class Encoder { - private final String secret; - - public Encoder(String secret) { - this.secret = secret; - } - - private static int dt(int var0) { - byte var1; - switch (var0) { - case 1: - var1 = 6; - break; - case 2: - var1 = 4; - break; - case 3: - var1 = 3; - break; - case 4: - var1 = 1; - break; - case 5: - var1 = 0; - break; - default: - var1 = -1; - } - - return var1; - } - - public String encode(byte[] bytes) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - for (int i = 0; i < (bytes.length + 4) / 5; ++i) { - short[] shorts = new short[5]; - int[] ints = new int[8]; - int i1 = 0; - - int i2; - for (i2 = 5; i1 < 5; ++i1) { - if (i * 5 + i1 < bytes.length) { - shorts[i1] = (short) (bytes[i * 5 + i1] & 255); - } else { - shorts[i1] = 0; - --i2; - } - } - - int dt = dt(i2); - ints[0] = (byte) (shorts[0] >> 3 & 31); - ints[1] = (byte) ((shorts[0] & 7) << 2 | shorts[1] >> 6 & 3); - ints[2] = (byte) (shorts[1] >> 1 & 31); - ints[3] = (byte) ((shorts[1] & 1) << 4 | shorts[2] >> 4 & 15); - ints[4] = (byte) ((shorts[2] & 15) << 1 | shorts[3] >> 7 & 1); - ints[5] = (byte) (shorts[3] >> 2 & 31); - ints[6] = (byte) ((shorts[3] & 3) << 3 | shorts[4] >> 5 & 7); - ints[7] = (byte) (shorts[4] & 31); - - for (i1 = 0; i1 < ints.length - dt; ++i1) { - outputStream.write(this.secret.charAt(ints[i1])); - } - } - - return outputStream.toString(); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.kt new file mode 100644 index 00000000..7b47553a --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/UIDUtil.kt @@ -0,0 +1,86 @@ +package com.huanchengfly.tieba.post.utils + +import android.annotation.SuppressLint +import android.os.Build +import android.provider.Settings +import android.text.TextUtils +import com.huanchengfly.tieba.post.App.Companion.INSTANCE +import com.huanchengfly.tieba.post.utils.helios.Base32 +import com.huanchengfly.tieba.post.utils.helios.Hasher +import java.nio.charset.StandardCharsets +import java.security.MessageDigest +import java.util.Locale +import java.util.UUID + +object UIDUtil { + @get:SuppressLint("HardwareIds") + val androidId: String + get() = getAndroidId("") + + @SuppressLint("HardwareIds") + fun getAndroidId(defaultValue: String): String { + val androidId = + Settings.Secure.getString(INSTANCE.contentResolver, Settings.Secure.ANDROID_ID) + return androidId ?: defaultValue + } + + fun getAid(): String { + val raw = "com.helios" + getAndroidId("000000000") + uUID + val bytes = getSHA1(raw) + val encoded = Base32.encode(bytes) + val rawAid = "A00-$encoded-" + val sign = Base32.encode(Hasher.hash(rawAid.toByteArray())) + return "$rawAid$sign" + } + + private fun getSHA1(str: String): ByteArray { + var sha1: ByteArray = "".toByteArray() + try { + val digest = MessageDigest.getInstance("SHA1") + sha1 = digest.digest(str.toByteArray(StandardCharsets.UTF_8)) + } catch (e: Exception) { + e.printStackTrace() + } + return sha1 + } + + val newCUID: String + get() = "baidutiebaapp$uUID" + + val cUID: String + get() { + val androidId = androidId + var imei = MobileInfoUtil.getIMEI(INSTANCE) + if (TextUtils.isEmpty(imei)) { + imei = "0" + } + return MD5Util.toMd5((if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) imei + androidId + uUID else "com.baidu$androidId").toByteArray()) + .uppercase( + Locale.getDefault() + ) + } + + val finalCUID: String + get() { + var imei = MobileInfoUtil.getIMEI(INSTANCE) + if (TextUtils.isEmpty(imei)) { + imei = "0" + } + return cUID + "|" + StringBuffer(imei).reverse() + } + + @get:SuppressLint("ApplySharedPref") + val uUID: String + get() { + var uuid = SharedPreferencesUtil.get(INSTANCE, SharedPreferencesUtil.SP_APP_DATA) + .getString("uuid", null) + if (uuid == null) { + uuid = UUID.randomUUID().toString() + SharedPreferencesUtil.get(INSTANCE, SharedPreferencesUtil.SP_APP_DATA) + .edit() + .putString("uuid", uuid) + .apply() + } + return uuid + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Base32.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Base32.kt new file mode 100644 index 00000000..ef007bd5 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Base32.kt @@ -0,0 +1,54 @@ +package com.huanchengfly.tieba.post.utils.helios + +import java.io.ByteArrayOutputStream + +object Base32 { + fun encode(bytes: ByteArray): String { + val outputStream = ByteArrayOutputStream() + for (i in 0 until (bytes.size + 4) / 5) { + val shorts = ShortArray(5) + val ints = IntArray(8) + var i1 = 0 + var i2 = 5 + while (i1 < 5) { + if (i * 5 + i1 < bytes.size) { + shorts[i1] = (bytes[i * 5 + i1].toInt() and 255).toShort() + } else { + shorts[i1] = 0 + --i2 + } + ++i1 + } + val dt = transformInt(i2) + ints[0] = (shorts[0].toInt() shr 3 and 31).toByte().toInt() + ints[1] = + (shorts[0].toInt() and 7 shl 2 or (shorts[1].toInt() shr 6 and 3)).toByte().toInt() + ints[2] = (shorts[1].toInt() shr 1 and 31).toByte().toInt() + ints[3] = + (shorts[1].toInt() and 1 shl 4 or (shorts[2].toInt() shr 4 and 15)).toByte().toInt() + ints[4] = + (shorts[2].toInt() and 15 shl 1 or (shorts[3].toInt() shr 7 and 1)).toByte().toInt() + ints[5] = (shorts[3].toInt() shr 2 and 31).toByte().toInt() + ints[6] = + (shorts[3].toInt() and 3 shl 3 or (shorts[4].toInt() shr 5 and 7)).toByte().toInt() + ints[7] = (shorts[4].toInt() and 31).toByte().toInt() + i1 = 0 + while (i1 < ints.size - dt) { + outputStream.write(ALPHABET[ints[i1]].code) + ++i1 + } + } + return outputStream.toString() + } + + private const val ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=" + + private fun transformInt(i: Int): Int = when (i) { + 1 -> 6 + 2 -> 4 + 3 -> 3 + 4 -> 1 + 5 -> 0 + else -> -1 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/ByteArrayUtils.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/ByteArrayUtils.java new file mode 100644 index 00000000..62906eb5 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/ByteArrayUtils.java @@ -0,0 +1,40 @@ +package com.huanchengfly.tieba.post.utils.helios; + +import java.util.Arrays; + +class ByteArrayUtils { + public static void copyArray(byte[] dest, byte[] src, int destPos) { + if (destPos < 0) { + throw new IllegalArgumentException("start should be more than zero!"); + } else if (dest != null && dest.length != 0) { + if (src != null && src.length != 0) { + if (dest.length < src.length) { + throw new IllegalArgumentException("dst array length should be longer than:" + src.length); + } else { + int length = src.length; + if (dest.length < length + destPos) { + throw new IllegalArgumentException("start should be less than:" + (dest.length - src.length)); + } else { + System.arraycopy(src, 0, dest, destPos, src.length); + } + } + } else { + throw new IllegalArgumentException("src array should not be null or empty"); + } + } else { + throw new IllegalArgumentException("dst array should not be null or empty"); + } + } + + public static byte[] copyArray(byte[] src, int newLength) { + if (src != null && src.length != 0) { + if (newLength < 0) { + throw new IllegalArgumentException("length should be more than zero!"); + } else { + return Arrays.copyOf(src, newLength); + } + } else { + throw new IllegalArgumentException("original array should not be null or empty"); + } + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/CRC32Encoder.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/CRC32Encoder.java new file mode 100644 index 00000000..1848a011 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/CRC32Encoder.java @@ -0,0 +1,24 @@ +package com.huanchengfly.tieba.post.utils.helios; + +import java.util.zip.CRC32; + +final class CRC32Encoder extends IEncoder { + public CRC32Encoder(int start, int flag) { + this.length = 32; + this.start = start; + this.flag = flag; + } + + public EncodeResult encode(byte[] bytes, int off, int len) { + long result; + try { + CRC32 crc32 = new CRC32(); + crc32.update(bytes, off, len); + result = crc32.getValue(); + } catch (Exception var9) { + result = 4294967295L; + } + + return EncodeResult.a(new long[]{result}); + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/EncodeResult.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/EncodeResult.java new file mode 100644 index 00000000..355ff2d8 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/EncodeResult.java @@ -0,0 +1,712 @@ +package com.huanchengfly.tieba.post.utils.helios; + +import androidx.annotation.NonNull; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.LongBuffer; +import java.util.Arrays; + +public class EncodeResult implements Serializable, Cloneable { + static final boolean a; + + static { + a = !EncodeResult.class.desiredAssertionStatus(); + } + + private long[] g; + private transient int h = 0; + private transient boolean i = false; + + public EncodeResult() { + this.j(64); + this.i = false; + } + + public EncodeResult(int bits) { + if (bits < 0) { + throw new NegativeArraySizeException("nbits < 0: " + bits); + } else { + this.j(bits); + this.i = true; + } + } + + private EncodeResult(long[] var1) { + this.g = var1; + this.h = var1.length; + this.h(); + } + + public static EncodeResult a(ByteBuffer var0) { + int var1 = 0; + ByteBuffer var2 = var0.slice().order(ByteOrder.LITTLE_ENDIAN); + + int var3 = var2.remaining(); + while (var3 > 0 && var2.get(var3 - 1) == 0) --var3; + + long[] var5 = new long[(var3 + 7) / 8]; + var2.limit(var3); + + for (var3 = 0; var2.remaining() >= 8; ++var3) { + var5[var3] = var2.getLong(); + } + + for (int var4 = var2.remaining(); var1 < var4; ++var1) { + var5[var3] |= ((long) var2.get() & 255L) << var1 * 8; + } + + return new EncodeResult(var5); + } + + public static EncodeResult a(LongBuffer var0) { + var0 = var0.slice(); + + int var1 = var0.remaining(); + while (var1 > 0 && var0.get(var1 - 1) == 0L) --var1; + + long[] var2 = new long[var1]; + var0.get(var2); + return new EncodeResult(var2); + } + + public static EncodeResult a(byte[] var0) { + return a(ByteBuffer.wrap(var0)); + } + + public static EncodeResult a(long[] var0) { + int var1 = var0.length; + while (var1 > 0 && var0[var1 - 1] == 0) --var1; + + return new EncodeResult(Arrays.copyOf(var0, var1)); + } + + private static void checkIndex(int fromIndex, int toIndex) { + if (fromIndex < 0) { + throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex); + } else if (toIndex < 0) { + throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex); + } else if (fromIndex > toIndex) { + throw new IndexOutOfBoundsException("fromIndex: " + fromIndex + " > toIndex: " + toIndex); + } + } + + private static int i(int var0) { + return var0 >> 6; + } + + private void h() { + if (!a && this.h != 0 && this.g[this.h - 1] == 0L) { + throw new AssertionError(); + } else if (!a && this.h > this.g.length) { + throw new AssertionError(); + } else if (!a && this.h != this.g.length && this.g[this.h] != 0L) { + throw new AssertionError(); + } + } + + private void i() { + int var1 = this.h - 1; + while (var1 >= 0 && this.g[var1] == 0L) { + --var1; + } + this.h = var1 + 1; + } + + private void j() { + if (this.h != this.g.length) { + this.g = Arrays.copyOf(this.g, this.h); + this.h(); + } + } + + private void j(int bits) { + this.g = new long[i(bits - 1) + 1]; + } + + private void k(int var1) { + if (this.g.length < var1) { + var1 = Math.max(this.g.length * 2, var1); + this.g = Arrays.copyOf(this.g, var1); + this.i = false; + } + + } + + private void l(int var1) { + ++var1; + if (this.h < var1) { + this.k(var1); + this.h = var1; + } + + } + + public void a(int var1) { + if (var1 < 0) { + throw new IndexOutOfBoundsException("bitIndex < 0: " + var1); + } else { + int var2 = i(var1); + this.l(var2); + long[] var3 = this.g; + var3[var2] ^= 1L << var1; + this.i(); + this.h(); + } + } + + public void a(int fromIndex, int toIndex) { + checkIndex(fromIndex, toIndex); + if (fromIndex != toIndex) { + int var3 = i(fromIndex); + int var4 = i(toIndex - 1); + this.l(var4); + long var5 = -1L << fromIndex; + long var7 = -1L >>> -toIndex; + long[] var9 = this.g; + if (var3 == var4) { + var9[var3] ^= var5 & var7; + } else { + var9[var3] ^= var5; + + for (fromIndex = var3 + 1; fromIndex < var4; ++fromIndex) { + var9[fromIndex] = ~var9[fromIndex]; + } + + var9[var4] ^= var7; + } + + this.i(); + this.h(); + } + + } + + public void a(int fromIndex, int toIndex, boolean var3) { + if (var3) { + this.b(fromIndex, toIndex); + } else { + this.c(fromIndex, toIndex); + } + + } + + public void a(int var1, boolean var2) { + if (var2) { + this.b(var1); + } else { + this.c(var1); + } + + } + + public boolean a(EncodeResult var1) { + int var2 = Math.min(this.h, var1.h) - 1; + + boolean var3; + while (true) { + if (var2 < 0) { + var3 = false; + break; + } + + if ((this.g[var2] & var1.g[var2]) != 0L) { + var3 = true; + break; + } + + --var2; + } + + return var3; + } + + public byte[] a() { + byte var1 = 0; + int var2 = this.h; + byte[] var3; + if (var2 == 0) { + var3 = new byte[0]; + } else { + int var4 = (var2 - 1) * 8; + + long var5; + for (var5 = this.g[var2 - 1]; var5 != 0L; var5 >>>= 8) { + ++var4; + } + + byte[] var7 = new byte[var4]; + ByteBuffer var8 = ByteBuffer.wrap(var7).order(ByteOrder.LITTLE_ENDIAN); + + for (var4 = var1; var4 < var2 - 1; ++var4) { + var8.putLong(this.g[var4]); + } + + var5 = this.g[var2 - 1]; + + while (true) { + var3 = var7; + if (var5 == 0L) { + break; + } + + var8.put((byte) ((int) (255L & var5))); + var5 >>>= 8; + } + } + + return var3; + } + + public void b(int var1) { + if (var1 < 0) { + throw new IndexOutOfBoundsException("bitIndex < 0: " + var1); + } else { + int var2 = i(var1); + this.l(var2); + long[] var3 = this.g; + var3[var2] |= 1L << var1; + this.h(); + } + } + + public void b(int fromIndex, int toIndex) { + checkIndex(fromIndex, toIndex); + if (fromIndex != toIndex) { + int var3 = i(fromIndex); + int var4 = i(toIndex - 1); + this.l(var4); + long var5 = -1L << fromIndex; + long var7 = -1L >>> -toIndex; + long[] var9 = this.g; + if (var3 == var4) { + var9[var3] |= var5 & var7; + } else { + var9[var3] |= var5; + + for (fromIndex = var3 + 1; fromIndex < var4; ++fromIndex) { + this.g[fromIndex] = -1L; + } + + var9[var4] |= var7; + } + + this.h(); + } + + } + + public void b(EncodeResult var1) { + if (this != var1) { + while (true) { + long[] var2; + int var3; + if (this.h <= var1.h) { + for (var3 = 0; var3 < this.h; ++var3) { + var2 = this.g; + var2[var3] &= var1.g[var3]; + } + + this.i(); + this.h(); + break; + } + + var2 = this.g; + var3 = this.h - 1; + this.h = var3; + var2[var3] = 0L; + } + } + + } + + public long[] b() { + return Arrays.copyOf(this.g, this.h); + } + + public void c() { + while (this.h > 0) { + long[] var1 = this.g; + int var2 = this.h - 1; + this.h = var2; + var1[var2] = 0L; + } + + } + + public void c(int var1) { + if (var1 < 0) { + throw new IndexOutOfBoundsException("bitIndex < 0: " + var1); + } else { + int var2 = i(var1); + if (var2 < this.h) { + long[] var3 = this.g; + var3[var2] &= ~(1L << var1); + this.i(); + this.h(); + } + + } + } + + public void c(int fromIndex, int toIndex) { + checkIndex(fromIndex, toIndex); + if (fromIndex != toIndex) { + int var3 = i(fromIndex); + if (var3 < this.h) { + int var4 = i(toIndex - 1); + if (var4 >= this.h) { + toIndex = this.d(); + var4 = this.h - 1; + } + + long var5 = -1L << fromIndex; + long var7 = -1L >>> -toIndex; + long[] var9 = this.g; + if (var3 == var4) { + var9[var3] &= ~(var5 & var7); + } else { + var9[var3] &= ~var5; + + for (fromIndex = var3 + 1; fromIndex < var4; ++fromIndex) { + this.g[fromIndex] = 0L; + } + + var9[var4] &= ~var7; + } + + this.i(); + this.h(); + } + } + + } + + public void c(EncodeResult var1) { + if (this != var1) { + int var2 = Math.min(this.h, var1.h); + if (this.h < var1.h) { + this.k(var1.h); + this.h = var1.h; + } + + for (int var3 = 0; var3 < var2; ++var3) { + long[] var4 = this.g; + var4[var3] |= var1.g[var3]; + } + + if (var2 < var1.h) { + System.arraycopy(var1.g, var2, this.g, var2, this.h - var2); + } + + this.h(); + } + + } + + @NonNull + public Object clone() { + if (!this.i) { + this.j(); + } + + try { + EncodeResult var1 = (EncodeResult) super.clone(); + var1.g = this.g.clone(); + var1.h(); + return var1; + } catch (CloneNotSupportedException var2) { + throw new InternalError(); + } + } + + public int d() { + int var1; + if (this.h == 0) { + var1 = 0; + } else { + var1 = (this.h - 1) * 64 + (64 - Long.numberOfLeadingZeros(this.g[this.h - 1])); + } + + return var1; + } + + public EncodeResult d(int fromIndex, int toIndex) { + int var3 = 0; + checkIndex(fromIndex, toIndex); + this.h(); + int var4 = this.d(); + EncodeResult var5; + if (var4 > fromIndex && fromIndex != toIndex) { + int var6 = Math.min(toIndex, var4); + + var5 = new EncodeResult(var6 - fromIndex); + int var7 = i(var6 - fromIndex - 1) + 1; + var4 = i(fromIndex); + boolean var13; + var13 = (fromIndex & 63) == 0; + + long[] var8; + long var9; + while (var3 < var7 - 1) { + var8 = var5.g; + if (var13) { + var9 = this.g[var4]; + } else { + var9 = this.g[var4] >>> fromIndex | this.g[var4 + 1] << -fromIndex; + } + + var8[var3] = var9; + ++var3; + ++var4; + } + + var9 = -1L >>> -var6; + var8 = var5.g; + if ((var6 - 1 & 63) < (fromIndex & 63)) { + long var11 = this.g[var4]; + var9 = (var9 & this.g[var4 + 1]) << -fromIndex | var11 >>> fromIndex; + } else { + var9 = (var9 & this.g[var4]) >>> fromIndex; + } + + var8[var7 - 1] = var9; + var5.h = var7; + var5.i(); + var5.h(); + } else { + var5 = new EncodeResult(0); + } + + return var5; + } + + public void d(EncodeResult var1) { + int var2 = Math.min(this.h, var1.h); + if (this.h < var1.h) { + this.k(var1.h); + this.h = var1.h; + } + + for (int var3 = 0; var3 < var2; ++var3) { + long[] var4 = this.g; + var4[var3] ^= var1.g[var3]; + } + + if (var2 < var1.h) { + System.arraycopy(var1.g, var2, this.g, var2, var1.h - var2); + } + + this.i(); + this.h(); + } + + public boolean d(int var1) { + if (var1 < 0) { + throw new IndexOutOfBoundsException("bitIndex < 0: " + var1); + } else { + this.h(); + int var2 = i(var1); + boolean var3; + var3 = var2 < this.h && (this.g[var2] & 1L << var1) != 0L; + + return var3; + } + } + + public int e(int var1) { + byte var2 = -1; + if (var1 < 0) { + throw new IndexOutOfBoundsException("fromIndex < 0: " + var1); + } else { + this.h(); + int var3 = i(var1); + if (var3 >= this.h) { + var1 = var2; + } else { + long var4 = this.g[var3] & -1L << var1; + var1 = var3; + + while (true) { + if (var4 != 0L) { + var1 = var1 * 64 + Long.numberOfTrailingZeros(var4); + break; + } + + var3 = var1 + 1; + var1 = var2; + if (var3 == this.h) { + break; + } + + var4 = this.g[var3]; + var1 = var3; + } + } + + return var1; + } + } + + public void e(EncodeResult var1) { + for (int var2 = Math.min(this.h, var1.h) - 1; var2 >= 0; --var2) { + long[] var3 = this.g; + var3[var2] &= ~var1.g[var2]; + } + + this.i(); + this.h(); + } + + public boolean e() { + return this.h == 0; + } + + public boolean equals(Object var1) { + boolean var2 = false; + boolean var3; + if (!(var1 instanceof EncodeResult)) { + var3 = var2; + } else if (this == var1) { + var3 = true; + } else { + EncodeResult var5 = (EncodeResult) var1; + this.h(); + var5.h(); + var3 = var2; + if (this.h == var5.h) { + int var4 = 0; + + while (true) { + if (var4 >= this.h) { + var3 = true; + break; + } + + if (this.g[var4] != var5.g[var4]) { + break; + } + + ++var4; + } + } + } + + return var3; + } + + public int f() { + int var1 = 0; + + int var2; + for (var2 = 0; var1 < this.h; ++var1) { + var2 += Long.bitCount(this.g[var1]); + } + + return var2; + } + + public int f(int var1) { + if (var1 < 0) { + throw new IndexOutOfBoundsException("fromIndex < 0: " + var1); + } else { + this.h(); + int var2 = i(var1); + if (var2 < this.h) { + long var3 = ~this.g[var2] & -1L << var1; + + for (var1 = var2; var3 == 0L; var3 = ~this.g[var1]) { + ++var1; + if (var1 == this.h) { + var1 = this.h * 64; + return var1; + } + } + + var1 = var1 * 64 + Long.numberOfTrailingZeros(var3); + } + + return var1; + } + } + + public int h(int var1) { + int var2; + if (var1 < 0) { + if (var1 != -1) { + throw new IndexOutOfBoundsException("fromIndex < -1: " + var1); + } + + var2 = -1; + } else { + this.h(); + int var3 = i(var1); + var2 = var1; + if (var3 < this.h) { + long var4 = ~this.g[var3] & -1L >>> -(var1 + 1); + + for (var1 = var3; var4 == 0L; var1 = var2) { + var2 = var1 - 1; + if (var1 == 0) { + var2 = -1; + return var2; + } + + var4 = ~this.g[var2]; + } + + var2 = (var1 + 1) * 64 - 1 - Long.numberOfLeadingZeros(var4); + } + } + + return var2; + } + + public int hashCode() { + long var1 = 1234L; + int var3 = this.h; + + while (true) { + --var3; + if (var3 < 0) { + return (int) (var1 >> 32 ^ var1); + } + + var1 ^= this.g[var3] * (long) (var3 + 1); + } + } + + @NonNull + public String toString() { + this.h(); + int var1; + if (this.h > 128) { + var1 = this.f(); + } else { + var1 = this.h * 64; + } + + StringBuilder var2 = new StringBuilder(var1 * 6 + 2); + var2.append('{'); + var1 = this.e(0); + if (var1 != -1) { + var2.append(var1); + + int var4; + for (var1 = this.e(var1 + 1); var1 >= 0; var1 = this.e(var4 + 1)) { + int var3 = this.f(var1); + + do { + var2.append(", ").append(var1); + var4 = var1 + 1; + var1 = var4; + } while (var4 < var3); + } + } + + var2.append('}'); + return var2.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/HashResult.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/HashResult.java new file mode 100644 index 00000000..a682dbea --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/HashResult.java @@ -0,0 +1,38 @@ +package com.huanchengfly.tieba.post.utils.helios; + +class HashResult { + public static int BITS = 40; + private final EncodeResult mEncodeResult; + + public HashResult() { + this.mEncodeResult = new EncodeResult(BITS); + this.mEncodeResult.a(0, BITS, true); + } + + public void update(EncodeResult var1, int start, int length, int var4) { + EncodeResult var5 = this.mEncodeResult.d(start, start + length); + switch (var4) { + case 0: + var5.b(var1); + break; + case 2: + var5.e(var1); + break; + case 3: + var5.c(var1); + break; + case 1: + default: + var5.d(var1); + } + + for (var4 = 0; var4 < length; ++var4) { + this.mEncodeResult.a(start + var4, var5.d(var4)); + } + + } + + public byte[] getValue() { + return this.mEncodeResult.a(); + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Hasher.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Hasher.java new file mode 100644 index 00000000..2ab3a8e4 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/Hasher.java @@ -0,0 +1,22 @@ +package com.huanchengfly.tieba.post.utils.helios; + +import java.util.Arrays; + +public class Hasher { + static IEncoder[] sEncoders = new IEncoder[]{new CRC32Encoder(8, 0), new XXHashEncoder(0, 1), new XXHashEncoder(1, 1), new CRC32Encoder(7, 1)}; + + public static byte[] hash(byte[] bytes) { + HashResult result = new HashResult(); + byte[] newBytes = ByteArrayUtils.copyArray(bytes, bytes.length + (sEncoders.length + 1) * 5); + ByteArrayUtils.copyArray(newBytes, result.getValue(), bytes.length); + + for (int i = 0; i < sEncoders.length; i++) { + IEncoder encoder = sEncoders[i]; + int len = bytes.length + (i + 1) * 5; + result.update(encoder.encode(newBytes, 0, len), encoder.getStart(), encoder.getLength(), encoder.getFlag()); + ByteArrayUtils.copyArray(newBytes, result.getValue(), len); + } + + return Arrays.copyOf(result.getValue(), 5); + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/IEncoder.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/IEncoder.java new file mode 100644 index 00000000..48b0a002 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/IEncoder.java @@ -0,0 +1,24 @@ +package com.huanchengfly.tieba.post.utils.helios; + +abstract class IEncoder { + protected int length = 32; + protected int start; + protected int flag; + + IEncoder() { + } + + public int getStart() { + return this.start; + } + + public int getLength() { + return this.length; + } + + public int getFlag() { + return this.flag; + } + + public abstract EncodeResult encode(byte[] bytes, int off, int len); +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHash.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHash.java new file mode 100644 index 00000000..42b5d506 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHash.java @@ -0,0 +1,117 @@ +package com.huanchengfly.tieba.post.utils.helios; + +class XXHash { + private final int[] i; + private final byte[] j; + private final int k; + private int l; + private int m; + + protected XXHash() { + this(0); + } + + protected XXHash(int var1) { + this.i = new int[4]; + this.j = new byte[16]; + this.k = var1; + this.c(); + } + + private static int a(byte[] var0, int var1) { + return (int) (j(var0, var1) & 4294967295L); + } + + private static long j(byte[] var0, int var1) { + if (4 > 8) { + throw new IllegalArgumentException("can't read more than eight bytes into a long value"); + } else { + long var3 = 0L; + + for (int var5 = 0; var5 < 4; ++var5) { + var3 |= ((long) var0[var1 + var5] & 255L) << var5 * 8; + } + + return var3; + } + } + + private void c() { + this.i[0] = this.k - 1640531535 - 2048144777; + this.i[1] = this.k - 2048144777; + this.i[2] = this.k; + this.i[3] = this.k + 1640531535; + } + + private void g(byte[] var1, int var2) { + int var3 = this.i[0]; + int var4 = this.i[1]; + int var5 = this.i[2]; + int var6 = this.i[3]; + var3 = Integer.rotateLeft(var3 + a(var1, var2) * -2048144777, 13); + var4 = Integer.rotateLeft(var4 + a(var1, var2 + 4) * -2048144777, 13); + var5 = Integer.rotateLeft(var5 + a(var1, var2 + 8) * -2048144777, 13); + var2 = Integer.rotateLeft(var6 + a(var1, var2 + 12) * -2048144777, 13); + this.i[0] = var3 * -1640531535; + this.i[1] = var4 * -1640531535; + this.i[2] = var5 * -1640531535; + this.i[3] = var2 * -1640531535; + this.m = 0; + } + + protected void update(byte[] var1, int var2, int var3) { + if (var3 > 0) { + this.l += var3; + int var4 = var2 + var3; + if (this.m + var3 < 16) { + System.arraycopy(var1, var2, this.j, this.m, var3); + this.m += var3; + } else { + var3 = var2; + if (this.m > 0) { + var3 = 16 - this.m; + System.arraycopy(var1, var2, this.j, this.m, var3); + this.g(this.j, 0); + var3 += var2; + } + + while (var3 <= var4 - 16) { + this.g(var1, var3); + var3 += 16; + } + + if (var3 < var4) { + this.m = var4 - var3; + System.arraycopy(var1, var3, this.j, 0, this.m); + } + } + } + + } + + protected long getValue() { + int var1; + if (this.l > 16) { + var1 = Integer.rotateLeft(this.i[0], 1) + Integer.rotateLeft(this.i[1], 7) + Integer.rotateLeft(this.i[2], 12) + Integer.rotateLeft(this.i[3], 18); + } else { + var1 = this.i[2] + 374761393; + } + + int var2 = this.l; + int var3 = this.m; + var2 += var1; + + for (var1 = 0; var1 <= var3 - 4; var1 += 4) { + var2 = Integer.rotateLeft(var2 + a(this.j, var1) * -1028477379, 17) * 668265263; + } + + while (var1 < this.m) { + var2 = Integer.rotateLeft((this.j[var1] & 255) * 374761393 + var2, 11) * -1640531535; + ++var1; + } + + var1 = (var2 >>> 15 ^ var2) * -2048144777; + var1 = (var1 ^ var1 >>> 13) * -1028477379; + return (long) (var1 ^ var1 >>> 16) & 4294967295L; + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHashEncoder.java b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHashEncoder.java new file mode 100644 index 00000000..ef1d17b3 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/helios/XXHashEncoder.java @@ -0,0 +1,16 @@ +package com.huanchengfly.tieba.post.utils.helios; + +final class XXHashEncoder extends IEncoder { + public XXHashEncoder(int start, int flag) { + this.length = 32; + this.start = start; + this.flag = flag; + } + + public EncodeResult encode(byte[] bytes, int off, int len) { + XXHash xxHash = new XXHash(); + xxHash.update(bytes, off, len); + return EncodeResult.a(new long[]{xxHash.getValue()}); + } +} +