更新部分书源接口

master^2
fengyuecanzhu 2 years ago
parent b388dce8a5
commit 3da6aa8dd3
No known key found for this signature in database
GPG Key ID: 04B78AD06A9D6E6C
  1. 1
      .idea/misc.xml
  2. 4
      app/build.gradle
  3. 23
      app/src/main/java/xyz/fycz/myreader/greendao/service/CacheManager.kt
  4. 496
      app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsEncodeUtils.kt
  5. 268
      app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsExtensions.kt
  6. 31
      app/src/main/java/xyz/fycz/myreader/util/utils/StringExtensions.kt

@ -31,6 +31,7 @@
<entry key="..\:/android/FYReader/app/src/main/res/layout/layout_about_content.xml" value="0.12132725430597771" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/layout_about_content.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/layout_book_detail_content.xml" value="0.2296195652173913" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/layout_book_detail_content.xml" value="0.2296195652173913" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/listview_chapter_title_item.xml" value="0.2296195652173913" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/listview_chapter_title_item.xml" value="0.2296195652173913" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/toolbar.xml" value="0.2296195652173913" />
</map> </map>
</option> </option>
</component> </component>

@ -294,6 +294,10 @@ dependencies {
//https://github.com/fengyuecanzhu/Maple //https://github.com/fengyuecanzhu/Maple
implementation("me.fycz.maple:maple:2.0") implementation("me.fycz.maple:maple:2.0")
//,使
//noinspection GradleDependency,GradlePackageUpdate
implementation('cn.hutool:hutool-crypto:5.8.10')
} }
greendao { greendao {

@ -19,6 +19,7 @@
package xyz.fycz.myreader.greendao.service package xyz.fycz.myreader.greendao.service
import android.database.Cursor import android.database.Cursor
import androidx.collection.LruCache
import xyz.fycz.myreader.application.App import xyz.fycz.myreader.application.App
import xyz.fycz.myreader.greendao.DbManager import xyz.fycz.myreader.greendao.DbManager
import xyz.fycz.myreader.greendao.entity.Cache import xyz.fycz.myreader.greendao.entity.Cache
@ -31,6 +32,7 @@ import java.lang.Exception
object CacheManager { object CacheManager {
private val queryTTFMap = hashMapOf<String, Pair<Long, QueryTTF>>() private val queryTTFMap = hashMapOf<String, Pair<Long, QueryTTF>>()
private val memoryLruCache = object : LruCache<String, String>(100) {}
/** /**
* saveTime 单位为秒 * saveTime 单位为秒
@ -49,6 +51,19 @@ object CacheManager {
} }
} }
fun putMemory(key: String, value: String) {
memoryLruCache.put(key, value)
}
//从内存中获取数据 使用lruCache
fun getFromMemory(key: String): String? {
return memoryLruCache.get(key)
}
fun deleteMemory(key: String) {
memoryLruCache.remove(key)
}
fun get(key: String): String? { fun get(key: String): String? {
var str: String? = null var str: String? = null
try { try {
@ -94,6 +109,14 @@ object CacheManager {
return null return null
} }
fun putFile(key: String, value: String, saveTime: Int = 0) {
ACache.get().put(key, value, saveTime)
}
fun getFile(key: String): String? {
return ACache.get().getAsString(key)
}
fun delete(key: String) { fun delete(key: String) {
DbManager.getDaoSession().cacheDao.deleteByKey(key) DbManager.getDaoSession().cacheDao.deleteByKey(key)
ACache.get(App.getmContext()).remove(key) ACache.get(App.getmContext()).remove(key)

@ -0,0 +1,496 @@
/*
* This file is part of FYReader.
* FYReader is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FYReader is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FYReader. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 - 2022 fengyuecanzhu
*/
package xyz.fycz.myreader.model.third3.analyzeRule
import android.util.Base64
import cn.hutool.crypto.digest.DigestUtil
import cn.hutool.crypto.digest.HMac
import cn.hutool.crypto.symmetric.SymmetricCrypto
import xyz.fycz.myreader.util.utils.MD5Utils
/**
* js加解密扩展类, 在js中通过java变量调用
* 添加方法请更新文档/legado/app/src/main/assets/help/JsHelp.md
*/
interface JsEncodeUtils {
fun md5Encode(str: String): String {
return MD5Utils.md5Encode(str)
}
fun md5Encode16(str: String): String {
return MD5Utils.md5Encode16(str)
}
//******************对称加密解密************************//
/**
* 在js中这样使用
* java.createSymmetricCrypto(transformation, key, iv).decrypt(data)
* java.createSymmetricCrypto(transformation, key, iv).decryptStr(data)
* java.createSymmetricCrypto(transformation, key, iv).encrypt(data)
* java.createSymmetricCrypto(transformation, key, iv).encryptBase64(data)
* java.createSymmetricCrypto(transformation, key, iv).encryptHex(data)
*/
/* 调用SymmetricCrypto key为null时使用随机密钥*/
fun createSymmetricCrypto(
transformation: String,
key: ByteArray?,
iv: ByteArray?
): SymmetricCrypto {
val symmetricCrypto = SymmetricCrypto(transformation, key)
return if (iv != null && iv.isNotEmpty()) symmetricCrypto.setIv(iv) else symmetricCrypto
}
fun createSymmetricCrypto(
transformation: String,
key: ByteArray
): SymmetricCrypto {
return createSymmetricCrypto(transformation, key, null)
}
fun createSymmetricCrypto(
transformation: String,
key: String
): SymmetricCrypto {
return createSymmetricCrypto(transformation, key, null)
}
fun createSymmetricCrypto(
transformation: String,
key: String,
iv: String?
): SymmetricCrypto {
return createSymmetricCrypto(
transformation, key.encodeToByteArray(), iv?.encodeToByteArray()
)
}
//******************对称加密解密old************************//
/////AES
/**
* AES 解码为 ByteArray
* @param str 传入的AES加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(str)")
)
fun aesDecodeToByteArray(
str: String, key: String, transformation: String, iv: String
): ByteArray? {
return createSymmetricCrypto(transformation, key, iv).decrypt(str)
}
/**
* AES 解码为 String
* @param str 传入的AES加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(str)")
)
fun aesDecodeToString(
str: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).decryptStr(str)
}
/**
* AES解码为String算法参数经过Base64加密
*
* @param data 加密的字符串
* @param key Base64后的密钥
* @param mode 模式
* @param padding 补码方式
* @param iv Base64后的加盐
* @return 解密后的字符串
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun aesDecodeArgsBase64Str(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto(
"AES/${mode}/${padding}",
Base64.decode(key, Base64.NO_WRAP),
Base64.decode(iv, Base64.NO_WRAP)
).decryptStr(data)
}
/**
* 已经base64的AES 解码为 ByteArray
* @param str 传入的AES Base64加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(str)")
)
fun aesBase64DecodeToByteArray(
str: String, key: String, transformation: String, iv: String
): ByteArray? {
return createSymmetricCrypto(transformation, key, iv).decrypt(str)
}
/**
* 已经base64的AES 解码为 String
* @param str 传入的AES Base64加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(str)")
)
fun aesBase64DecodeToString(
str: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).decryptStr(str)
}
/**
* 加密aes为ByteArray
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(data)")
)
fun aesEncodeToByteArray(
data: String, key: String, transformation: String, iv: String
): ByteArray? {
return createSymmetricCrypto(transformation, key, iv).decrypt(data)
}
/**
* 加密aes为String
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun aesEncodeToString(
data: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).decryptStr(data)
}
/**
* 加密aes后Base64化的ByteArray
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data).toByteArray()")
)
fun aesEncodeToBase64ByteArray(
data: String, key: String, transformation: String, iv: String
): ByteArray? {
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data).toByteArray()
}
/**
* 加密aes后Base64化的String
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)")
)
fun aesEncodeToBase64String(
data: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data)
}
/**
* AES加密并转为Base64算法参数经过Base64加密
*
* @param data 被加密的字符串
* @param key Base64后的密钥
* @param mode 模式
* @param padding 补码方式
* @param iv Base64后的加盐
* @return 加密后的Base64
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)")
)
fun aesEncodeArgsBase64Str(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto("AES/${mode}/${padding}", key, iv).encryptBase64(data)
}
/////DES
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun desDecodeToString(
data: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).decryptStr(data)
}
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun desBase64DecodeToString(
data: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).decryptStr(data)
}
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encrypt(data)")
)
fun desEncodeToString(
data: String, key: String, transformation: String, iv: String
): String? {
return String(createSymmetricCrypto(transformation, key, iv).encrypt(data))
}
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)")
)
fun desEncodeToBase64String(
data: String, key: String, transformation: String, iv: String
): String? {
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data)
}
//////3DES
/**
* 3DES解密
*
* @param data 加密的字符串
* @param key 密钥
* @param mode 模式
* @param padding 补码方式
* @param iv 加盐
* @return 解密后的字符串
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun tripleDESDecodeStr(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto("DESede/${mode}/${padding}", key, iv).decryptStr(data)
}
/**
* 3DES解密算法参数经过Base64加密
*
* @param data 加密的字符串
* @param key Base64后的密钥
* @param mode 模式
* @param padding 补码方式
* @param iv Base64后的加盐
* @return 解密后的字符串
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)")
)
fun tripleDESDecodeArgsBase64Str(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto(
"DESede/${mode}/${padding}",
Base64.decode(key, Base64.NO_WRAP),
iv.encodeToByteArray()
).decryptStr(data)
}
/**
* 3DES加密并转为Base64
*
* @param data 被加密的字符串
* @param key 密钥
* @param mode 模式
* @param padding 补码方式
* @param iv 加盐
* @return 加密后的Base64
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)")
)
fun tripleDESEncodeBase64Str(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto("DESede/${mode}/${padding}", key, iv)
.encryptBase64(data)
}
/**
* 3DES加密并转为Base64算法参数经过Base64加密
*
* @param data 被加密的字符串
* @param key Base64后的密钥
* @param mode 模式
* @param padding 补码方式
* @param iv Base64后的加盐
* @return 加密后的Base64
*/
@Deprecated(
"过于繁琐弃用",
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)")
)
fun tripleDESEncodeArgsBase64Str(
data: String,
key: String,
mode: String,
padding: String,
iv: String
): String? {
return createSymmetricCrypto(
"DESede/${mode}/${padding}",
Base64.decode(key, Base64.NO_WRAP),
iv.encodeToByteArray()
).encryptBase64(data)
}
//******************消息摘要/散列消息鉴别码************************//
/**
* 生成摘要并转为16进制字符串
*
* @param data 被摘要数据
* @param algorithm 签名算法
* @return 16进制字符串
*/
fun digestHex(
data: String,
algorithm: String,
): String {
return DigestUtil.digester(algorithm).digestHex(data)
}
/**
* 生成摘要并转为Base64字符串
*
* @param data 被摘要数据
* @param algorithm 签名算法
* @return Base64字符串
*/
fun digestBase64Str(
data: String,
algorithm: String,
): String {
return Base64.encodeToString(DigestUtil.digester(algorithm).digest(data), Base64.NO_WRAP)
}
/**
* 生成散列消息鉴别码并转为16进制字符串
*
* @param data 被摘要数据
* @param algorithm 签名算法
* @param key 密钥
* @return 16进制字符串
*/
@Suppress("FunctionName")
fun HMacHex(
data: String,
algorithm: String,
key: String
): String {
return HMac(algorithm, key.toByteArray()).digestHex(data)
}
/**
* 生成散列消息鉴别码并转为Base64字符串
*
* @param data 被摘要数据
* @param algorithm 签名算法
* @param key 密钥
* @return Base64字符串
*/
@Suppress("FunctionName")
fun HMacBase64(
data: String,
algorithm: String,
key: String
): String {
return Base64.encodeToString(
HMac(algorithm, key.toByteArray()).digest(data),
Base64.NO_WRAP
)
}
}

@ -22,6 +22,7 @@ import android.net.Uri
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import androidx.annotation.Keep import androidx.annotation.Keep
import cn.hutool.core.util.HexUtil
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -34,7 +35,9 @@ import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.BaseSource import xyz.fycz.myreader.model.third3.BaseSource
import xyz.fycz.myreader.model.third3.Debug import xyz.fycz.myreader.model.third3.Debug
import xyz.fycz.myreader.model.third3.NoStackTraceException
import xyz.fycz.myreader.model.third3.http.* import xyz.fycz.myreader.model.third3.http.*
import xyz.fycz.myreader.util.ToastUtils
import xyz.fycz.myreader.util.ZipUtils import xyz.fycz.myreader.util.ZipUtils
import xyz.fycz.myreader.util.utils.* import xyz.fycz.myreader.util.utils.*
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
@ -54,7 +57,7 @@ import java.util.zip.ZipInputStream
*/ */
@Keep @Keep
@Suppress("unused") @Suppress("unused")
interface JsExtensions { interface JsExtensions : JsEncodeUtils {
val TAG: String? val TAG: String?
get() = JsExtensions::class.simpleName get() = JsExtensions::class.simpleName
@ -143,11 +146,50 @@ interface JsExtensions {
html = html, html = html,
javaScript = js, javaScript = js,
headerMap = getSource()?.getHeaderMap(true), headerMap = getSource()?.getHeaderMap(true),
tag = getSource()?.getKey() tag = getSource()?.getKey()
).getStrResponse().body ).getStrResponse().body
} }
} }
/**
* 可从网络本地文件(阅读私有缓存目录和书籍保存位置支持相对路径)导入JavaScript脚本
*/
fun importScript(path: String): String {
val result = when {
path.startsWith("http") -> cacheFile(path) ?: ""
path.isUri() -> String(DocumentUtil.readBytes(App.getmContext(), Uri.parse(path)))
path.startsWith("/storage") -> FileUtils.readText(path)
else -> readTxtFile(path)
}
if (result.isBlank()) throw NoStackTraceException("$path 内容获取失败或者为空")
return result
}
/**
* 缓存以文本方式保存的文件 .js .txt等
* @param urlStr 网络文件的链接
* @return 返回缓存后的文件内容
*/
fun cacheFile(urlStr: String): String? {
return cacheFile(urlStr, 0)
}
/**
* 缓存以文本方式保存的文件 .js .txt等
* @param saveTime 缓存时间单位
*/
fun cacheFile(urlStr: String, saveTime: Int): String? {
val key = md5Encode16(urlStr)
val cache = CacheManager.getFile(key)
if (cache.isNullOrBlank()) {
log("首次下载 $urlStr")
val value = ajax(urlStr) ?: return null
CacheManager.putFile(key, value, saveTime)
return value
}
return cache
}
/** /**
* 实现16进制字符串转文件 * 实现16进制字符串转文件
* @param content 需要转成文件的16进制字符串 * @param content 需要转成文件的16进制字符串
@ -174,20 +216,45 @@ interface JsExtensions {
* js实现重定向拦截,网络访问get * js实现重定向拦截,网络访问get
*/ */
fun get(urlStr: String, headers: Map<String, String>): Connection.Response { fun get(urlStr: String, headers: Map<String, String>): Connection.Response {
return Jsoup.connect(urlStr) val response = Jsoup.connect(urlStr)
.sslSocketFactory(SSLHelper.unsafeSSLSocketFactory) .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
.ignoreContentType(true) .ignoreContentType(true)
.followRedirects(false) .followRedirects(false)
.headers(headers) .headers(headers)
.method(Connection.Method.GET) .method(Connection.Method.GET)
.execute() .execute()
val cookies = response.cookies()
CookieStore.mapToCookie(cookies)?.let {
val domain = NetworkUtils.getSubDomain(urlStr)
CacheManager.putMemory("${domain}_cookieJar", it)
}
return response
}
/**
* js实现重定向拦截,网络访问head,不返回Response Body更省流量
*/
fun head(urlStr: String, headers: Map<String, String>): Connection.Response {
val response = Jsoup.connect(urlStr)
.sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
.ignoreContentType(true)
.followRedirects(false)
.headers(headers)
.method(Connection.Method.HEAD)
.execute()
val cookies = response.cookies()
CookieStore.mapToCookie(cookies)?.let {
val domain = NetworkUtils.getSubDomain(urlStr)
CacheManager.putMemory("${domain}_cookieJar", it)
}
return response
} }
/** /**
* 网络访问post * 网络访问post
*/ */
fun post(urlStr: String, body: String, headers: Map<String, String>): Connection.Response { fun post(urlStr: String, body: String, headers: Map<String, String>): Connection.Response {
return Jsoup.connect(urlStr) val response = Jsoup.connect(urlStr)
.sslSocketFactory(SSLHelper.unsafeSSLSocketFactory) .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
.ignoreContentType(true) .ignoreContentType(true)
.followRedirects(false) .followRedirects(false)
@ -195,6 +262,12 @@ interface JsExtensions {
.headers(headers) .headers(headers)
.method(Connection.Method.POST) .method(Connection.Method.POST)
.execute() .execute()
val cookies = response.cookies()
CookieStore.mapToCookie(cookies)?.let {
val domain = NetworkUtils.getSubDomain(urlStr)
CacheManager.putMemory("${domain}_cookieJar", it)
}
return response
} }
/** /**
@ -243,12 +316,19 @@ interface JsExtensions {
return EncoderUtils.base64Encode(str, flags) return EncoderUtils.base64Encode(str, flags)
} }
fun md5Encode(str: String): String { /* HexString 解码为字节数组 */
return MD5Utils.md5Encode(str) fun hexDecodeToByteArray(hex: String): ByteArray? {
return HexUtil.decodeHex(hex)
}
/* hexString 解码为utf8String*/
fun hexDecodeToString(hex: String): String? {
return HexUtil.decodeHexStr(hex)
} }
fun md5Encode16(str: String): String { /* utf8 编码为hexString */
return MD5Utils.md5Encode16(str) fun hexEncodeToString(utf8: String): String? {
return HexUtil.encodeHexStr(utf8)
} }
/** /**
@ -501,174 +581,48 @@ interface JsExtensions {
} }
/** /**
* 输出调试日志 * 弹窗提示
*/ */
fun log(msg: String): String { fun toast(msg: Any?) {
getSource()?.let { ToastUtils.showInfo("${getSource()?.getTag()}: ${msg.toString()}")
Debug.log(it.getKey(), msg)
} ?: Debug.log(msg)
if (App.isDebug()) {
Log.d(TAG + "-" + getSource()?.getKey(), msg)
}
return msg
} }
/** /**
* 生成UUID * 弹窗提示 停留时间较长
*/ */
fun randomUUID(): String { fun longToast(msg: Any?) {
return UUID.randomUUID().toString() toast(msg)
} }
/** /**
* AES 解码为 ByteArray * 输出调试日志
* @param str 传入的AES加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
fun aesDecodeToByteArray(
str: String, key: String, transformation: String, iv: String
): ByteArray? {
return try {
EncoderUtils.decryptAES(
data = str.encodeToByteArray(),
key = key.encodeToByteArray(),
transformation,
iv.encodeToByteArray()
)
} catch (e: Exception) {
Log.e(TAG, e.toString())
log(e.localizedMessage ?: "aesDecodeToByteArrayERROR")
null
}
}
/**
* AES 解码为 String
* @param str 传入的AES加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
fun aesDecodeToString(
str: String, key: String, transformation: String, iv: String
): String? {
return aesDecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
}
/**
* 已经base64的AES 解码为 ByteArray
* @param str 传入的AES Base64加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
fun aesBase64DecodeToByteArray(
str: String, key: String, transformation: String, iv: String
): ByteArray? {
return try {
EncoderUtils.decryptBase64AES(
str.encodeToByteArray(),
key.encodeToByteArray(),
transformation,
iv.encodeToByteArray()
)
} catch (e: Exception) {
Log.e(TAG, e.toString())
log(e.localizedMessage ?: "aesDecodeToByteArrayERROR")
null
}
}
/**
* 已经base64的AES 解码为 String
* @param str 传入的AES Base64加密的数据
* @param key AES 解密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
fun aesBase64DecodeToString(
str: String, key: String, transformation: String, iv: String
): String? {
return aesBase64DecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
}
/**
* 加密aes为ByteArray
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/ */
fun aesEncodeToByteArray( fun log(msg: String): String {
data: String, key: String, transformation: String, iv: String getSource()?.let {
): ByteArray? { Debug.log(it.getKey(), msg)
return try { } ?: Debug.log(msg)
EncoderUtils.encryptAES( if (App.isDebug()) {
data.encodeToByteArray(), Log.d(TAG + "-" + getSource()?.getKey(), msg)
key = key.encodeToByteArray(),
transformation,
iv.encodeToByteArray()
)
} catch (e: Exception) {
Log.e(TAG, e.toString())
log(e.localizedMessage ?: "aesEncodeToByteArrayERROR")
null
} }
return msg
} }
/** /**
* 加密aes为String * 输出对象类型
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
fun aesEncodeToString(
data: String, key: String, transformation: String, iv: String
): String? {
return aesEncodeToByteArray(data, key, transformation, iv)?.let { String(it) }
}
/**
* 加密aes后Base64化的ByteArray
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/ */
fun aesEncodeToBase64ByteArray( fun logType(any: Any?) {
data: String, key: String, transformation: String, iv: String if (any == null) {
): ByteArray? { log("null")
return try { } else {
EncoderUtils.encryptAES2Base64( log(any.javaClass.name)
data.encodeToByteArray(),
key.encodeToByteArray(),
transformation,
iv.encodeToByteArray()
)
} catch (e: Exception) {
Log.e(TAG, e.toString())
log(e.localizedMessage ?: "aesEncodeToBase64ByteArrayERROR")
null
} }
} }
/** /**
* 加密aes后Base64化的String * 生成UUID
* @param data 传入的原始数据
* @param key AES加密的key
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/ */
fun aesEncodeToBase64String( fun randomUUID(): String {
data: String, key: String, transformation: String, iv: String return UUID.randomUUID().toString()
): String? {
return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) }
} }
fun android(): String { fun android(): String {

@ -23,6 +23,7 @@ package xyz.fycz.myreader.util.utils
import android.icu.text.Collator import android.icu.text.Collator
import android.icu.util.ULocale import android.icu.util.ULocale
import android.net.Uri import android.net.Uri
import android.text.Editable
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -30,14 +31,19 @@ fun String?.safeTrim() = if (this.isNullOrBlank()) null else this.trim()
fun String?.isContentScheme(): Boolean = this?.startsWith("content://") == true fun String?.isContentScheme(): Boolean = this?.startsWith("content://") == true
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
fun String.parseToUri(): Uri { fun String.parseToUri(): Uri {
return if (isContentScheme()) { return if (isUri()) Uri.parse(this) else {
Uri.parse(this)
} else {
Uri.fromFile(File(this)) Uri.fromFile(File(this))
} }
} }
fun String?.isUri(): Boolean {
this ?: return false
return this.startsWith("file://", true) || isContentScheme()
}
fun String?.isAbsUrl() = fun String?.isAbsUrl() =
this?.let { this?.let {
it.startsWith("http://", true) || it.startsWith("https://", true) it.startsWith("http://", true) || it.startsWith("https://", true)
@ -65,8 +71,22 @@ fun String?.isJsonArray(): Boolean =
str.startsWith("[") && str.endsWith("]") str.startsWith("[") && str.endsWith("]")
} ?: false } ?: false
fun String.splitNotBlank(vararg delimiter: String): Array<String> = run { fun String?.isXml(): Boolean =
this.split(*delimiter).map { it.trim() }.filterNot { it.isBlank() }.toTypedArray() this?.run {
val str = this.trim()
str.startsWith("<") && str.endsWith(">")
} ?: false
fun String?.isTrue(nullIsTrue: Boolean = false): Boolean {
if (this.isNullOrBlank() || this == "null") {
return nullIsTrue
}
return !this.trim().matches("(?i)^(false|no|not|0)$".toRegex())
}
fun String.splitNotBlank(vararg delimiter: String, limit: Int = 0): Array<String> = run {
this.split(*delimiter, limit = limit).map { it.trim() }.filterNot { it.isBlank() }
.toTypedArray()
} }
fun String.splitNotBlank(regex: Regex, limit: Int = 0): Array<String> = run { fun String.splitNotBlank(regex: Regex, limit: Int = 0): Array<String> = run {
@ -97,3 +117,4 @@ fun String.toStringArray(): Array<String> {
} }
} }

Loading…
Cancel
Save