js内添加source变量

pull/1259/head
gedoor 4 years ago
parent cbd204e25d
commit 99a269e864
  1. 25
      app/src/main/java/io/legado/app/data/entities/BaseSource.kt
  2. 7
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  3. 4
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  4. 4
      app/src/main/java/io/legado/app/data/entities/RssSource.kt
  5. 6
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
  6. 20
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  7. 2
      app/src/main/java/io/legado/app/model/rss/Rss.kt
  8. 2
      app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
  9. 2
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
  10. 4
      app/src/main/java/io/legado/app/model/webBook/BookContent.kt
  11. 2
      app/src/main/java/io/legado/app/model/webBook/BookInfo.kt
  12. 2
      app/src/main/java/io/legado/app/model/webBook/BookList.kt
  13. 39
      app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt

@ -1,17 +1,20 @@
package io.legado.app.data.entities package io.legado.app.data.entities
import android.util.Base64
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore import io.legado.app.help.http.CookieStore
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import java.util.*
import javax.script.SimpleBindings import javax.script.SimpleBindings
interface BaseSource : JsExtensions { interface BaseSource : JsExtensions {
fun getStoreUrl(): String
var header: String? var header: String?
fun getHeaderMap() = HashMap<String, String>().apply { fun getHeaderMap() = HashMap<String, String>().apply {
@ -31,6 +34,26 @@ interface BaseSource : JsExtensions {
} }
} }
fun getLoginHeader(): Map<String, String>? {
val cache = CacheManager.get("login_${getStoreUrl()}") ?: return null
val byteArrayB = Base64.decode(cache, Base64.DEFAULT)
val byteArrayA = EncoderUtils.decryptAES(byteArrayB, AppConst.androidId.toByteArray())
?: return null
val headerStr = String(byteArrayA)
return GSON.fromJsonObject(headerStr)
}
fun putLoginHeader(header: String) {
val data = Base64.encodeToString(
EncoderUtils.decryptAES(
header.toByteArray(),
AppConst.androidId.toByteArray()
),
Base64.DEFAULT
)
CacheManager.put("login_${getStoreUrl()}", data)
}
/** /**
* 执行JS * 执行JS
*/ */

@ -6,6 +6,7 @@ import androidx.room.ForeignKey
import androidx.room.Ignore import androidx.room.Ignore
import androidx.room.Index import androidx.room.Index
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.analyzeRule.RuleDataInterface
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
@ -39,16 +40,16 @@ data class BookChapter(
var startFragmentId: String? = null, //EPUB书籍当前章节的fragmentId var startFragmentId: String? = null, //EPUB书籍当前章节的fragmentId
var endFragmentId: String? = null, //EPUB书籍下一章节的fragmentId var endFragmentId: String? = null, //EPUB书籍下一章节的fragmentId
var variable: String? = null //变量 var variable: String? = null //变量
) : Parcelable { ) : Parcelable, RuleDataInterface {
@delegate:Transient @delegate:Transient
@delegate:Ignore @delegate:Ignore
@IgnoredOnParcel @IgnoredOnParcel
val variableMap by lazy { override val variableMap by lazy {
GSON.fromJsonObject<HashMap<String, String>>(variable) ?: HashMap() GSON.fromJsonObject<HashMap<String, String>>(variable) ?: HashMap()
} }
fun putVariable(key: String, value: String) { override fun putVariable(key: String, value: String) {
variableMap[key] = value variableMap[key] = value
variable = GSON.toJson(variableMap) variable = GSON.toJson(variableMap)
} }

@ -45,6 +45,10 @@ data class BookSource(
var ruleContent: ContentRule? = null // 正文页规则 var ruleContent: ContentRule? = null // 正文页规则
) : Parcelable, BaseSource { ) : Parcelable, BaseSource {
override fun getStoreUrl(): String {
return bookSourceUrl
}
@delegate:Transient @delegate:Transient
@delegate:Ignore @delegate:Ignore
@IgnoredOnParcel @IgnoredOnParcel

@ -43,6 +43,10 @@ data class RssSource(
var customOrder: Int = 0 var customOrder: Int = 0
) : Parcelable, BaseSource { ) : Parcelable, BaseSource {
override fun getStoreUrl(): String {
return sourceUrl
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other is RssSource) { if (other is RssSource) {
return other.sourceUrl == sourceUrl return other.sourceUrl == sourceUrl

@ -5,6 +5,7 @@ import androidx.annotation.Keep
import io.legado.app.constant.AppConst.SCRIPT_ENGINE import io.legado.app.constant.AppConst.SCRIPT_ENGINE
import io.legado.app.constant.AppPattern.JS_PATTERN import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BaseSource
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.CacheManager import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
@ -24,7 +25,7 @@ import kotlin.collections.HashMap
*/ */
@Keep @Keep
@Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate") @Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate")
class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions { class AnalyzeRule(val ruleData: RuleDataInterface, private val source: BaseSource) : JsExtensions {
var book = if (ruleData is BaseBook) ruleData else null var book = if (ruleData is BaseBook) ruleData else null
@ -626,6 +627,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager bindings["cache"] = CacheManager
bindings["source"] = source
bindings["book"] = book bindings["book"] = book
bindings["result"] = result bindings["result"] = result
bindings["baseUrl"] = baseUrl bindings["baseUrl"] = baseUrl
@ -642,7 +644,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
override fun ajax(urlStr: String): String? { override fun ajax(urlStr: String): String? {
return runBlocking { return runBlocking {
kotlin.runCatching { kotlin.runCatching {
val analyzeUrl = AnalyzeUrl(urlStr, book = book) val analyzeUrl = AnalyzeUrl(urlStr, book = book, source = source)
analyzeUrl.getStrResponse(urlStr).body analyzeUrl.getStrResponse(urlStr).body
}.onFailure { }.onFailure {
it.printStackTrace() it.printStackTrace()

@ -8,6 +8,7 @@ import io.legado.app.constant.AppConst.SCRIPT_ENGINE
import io.legado.app.constant.AppConst.UA_NAME import io.legado.app.constant.AppConst.UA_NAME
import io.legado.app.constant.AppPattern.JS_PATTERN import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BaseSource
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager import io.legado.app.help.CacheManager
@ -36,7 +37,8 @@ class AnalyzeUrl(
val book: BaseBook? = null, val book: BaseBook? = null,
val chapter: BookChapter? = null, val chapter: BookChapter? = null,
private val ruleData: RuleDataInterface? = null, private val ruleData: RuleDataInterface? = null,
headerMapF: Map<String, String>? = null private val source: BaseSource? = null,
headerMapF: Map<String, String>? = null,
) : JsExtensions { ) : JsExtensions {
companion object { companion object {
val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)") val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)")
@ -104,20 +106,9 @@ class AnalyzeUrl(
val analyze = RuleAnalyzer(ruleUrl) //创建解析 val analyze = RuleAnalyzer(ruleUrl) //创建解析
val bindings = SimpleBindings()
bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["baseUrl"] = baseUrl
bindings["page"] = page
bindings["key"] = key
bindings["speakText"] = speakText
bindings["speakSpeed"] = speakSpeed
bindings["book"] = book
//替换所有内嵌{{js}} //替换所有内嵌{{js}}
val url = analyze.innerRule("{{", "}}") { val url = analyze.innerRule("{{", "}}") {
val jsEval = SCRIPT_ENGINE.eval(it, bindings) ?: "" val jsEval = evalJS(it) ?: ""
when { when {
jsEval is String -> jsEval jsEval is String -> jsEval
jsEval is Double && jsEval % 1.0 == 0.0 -> String.format("%.0f", jsEval) jsEval is Double && jsEval % 1.0 == 0.0 -> String.format("%.0f", jsEval)
@ -234,6 +225,7 @@ class AnalyzeUrl(
private fun evalJS(jsStr: String, result: Any? = null): Any? { private fun evalJS(jsStr: String, result: Any? = null): Any? {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["java"] = this bindings["java"] = this
bindings["baseUrl"] = baseUrl
bindings["cookie"] = CookieStore bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager bindings["cache"] = CacheManager
bindings["page"] = page bindings["page"] = page
@ -241,8 +233,8 @@ class AnalyzeUrl(
bindings["speakText"] = speakText bindings["speakText"] = speakText
bindings["speakSpeed"] = speakSpeed bindings["speakSpeed"] = speakSpeed
bindings["book"] = book bindings["book"] = book
bindings["source"] = source
bindings["result"] = result bindings["result"] = result
bindings["baseUrl"] = baseUrl
return SCRIPT_ENGINE.eval(jsStr, bindings) return SCRIPT_ENGINE.eval(jsStr, bindings)
} }

@ -52,7 +52,7 @@ object Rss {
val body = analyzeUrl.getStrResponse(rssArticle.origin).body val body = analyzeUrl.getStrResponse(rssArticle.origin).body
Debug.log(rssSource.sourceUrl, "≡获取成功:${rssSource.sourceUrl}") Debug.log(rssSource.sourceUrl, "≡获取成功:${rssSource.sourceUrl}")
Debug.log(rssSource.sourceUrl, body, state = 20) Debug.log(rssSource.sourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(rssArticle) val analyzeRule = AnalyzeRule(rssArticle, rssSource)
analyzeRule.setContent(body) analyzeRule.setContent(body)
.setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link)) .setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
analyzeRule.getString(ruleContent) analyzeRule.getString(ruleContent)

@ -38,7 +38,7 @@ object RssParserByRule {
return RssParserDefault.parseXML(sortName, body, sourceUrl) return RssParserDefault.parseXML(sortName, body, sourceUrl)
} else { } else {
val articleList = mutableListOf<RssArticle>() val articleList = mutableListOf<RssArticle>()
val analyzeRule = AnalyzeRule(ruleData) val analyzeRule = AnalyzeRule(ruleData, rssSource)
analyzeRule.setContent(body).setBaseUrl(sortUrl) analyzeRule.setContent(body).setBaseUrl(sortUrl)
analyzeRule.setRedirectUrl(sortUrl) analyzeRule.setRedirectUrl(sortUrl)
var reverse = false var reverse = false

@ -140,7 +140,7 @@ object BookChapterList {
getNextUrl: Boolean = true, getNextUrl: Boolean = true,
log: Boolean = false log: Boolean = false
): ChapterData<List<String>> { ): ChapterData<List<String>> {
val analyzeRule = AnalyzeRule(book) val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl) analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(redirectUrl) analyzeRule.setRedirectUrl(redirectUrl)
//获取目录列表 //获取目录列表

@ -47,7 +47,7 @@ object BookContent {
val content = StringBuilder() val content = StringBuilder()
val nextUrlList = arrayListOf(baseUrl) val nextUrlList = arrayListOf(baseUrl)
val contentRule = bookSource.getContentRule() val contentRule = bookSource.getContentRule()
val analyzeRule = AnalyzeRule(book).setContent(body, baseUrl) val analyzeRule = AnalyzeRule(book, bookSource).setContent(body, baseUrl)
analyzeRule.setRedirectUrl(baseUrl) analyzeRule.setRedirectUrl(baseUrl)
analyzeRule.nextChapterUrl = mNextChapterUrl analyzeRule.nextChapterUrl = mNextChapterUrl
scope.ensureActive() scope.ensureActive()
@ -131,7 +131,7 @@ object BookContent {
nextChapterUrl: String?, nextChapterUrl: String?,
printLog: Boolean = true printLog: Boolean = true
): ContentData<List<String>> { ): ContentData<List<String>> {
val analyzeRule = AnalyzeRule(book) val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body, baseUrl) analyzeRule.setContent(body, baseUrl)
val rUrl = analyzeRule.setRedirectUrl(redirectUrl) val rUrl = analyzeRule.setRedirectUrl(redirectUrl)
analyzeRule.nextChapterUrl = nextChapterUrl analyzeRule.nextChapterUrl = nextChapterUrl

@ -32,7 +32,7 @@ object BookInfo {
) )
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}")
Debug.log(bookSource.bookSourceUrl, body, state = 20) Debug.log(bookSource.bookSourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(book) val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl) analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(redirectUrl) analyzeRule.setRedirectUrl(redirectUrl)
analyzeBookInfo(scope, book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName) analyzeBookInfo(scope, book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName)

@ -39,7 +39,7 @@ object BookList {
val bookList = ArrayList<SearchBook>() val bookList = ArrayList<SearchBook>()
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${analyzeUrl.ruleUrl}") Debug.log(bookSource.bookSourceUrl, "≡获取成功:${analyzeUrl.ruleUrl}")
Debug.log(bookSource.bookSourceUrl, body, state = 10) Debug.log(bookSource.bookSourceUrl, body, state = 10)
val analyzeRule = AnalyzeRule(variableBook) val analyzeRule = AnalyzeRule(variableBook, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl) analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(baseUrl) analyzeRule.setRedirectUrl(baseUrl)
bookSource.bookUrlPattern?.let { bookSource.bookUrlPattern?.let {

@ -2,28 +2,30 @@ package io.legado.app.ui.book.login
import android.os.Bundle import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.util.Base64
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
import io.legado.app.constant.AppConst import io.legado.app.data.appDb
import io.legado.app.data.entities.rule.LoginRule
import io.legado.app.databinding.DialogLoginBinding import io.legado.app.databinding.DialogLoginBinding
import io.legado.app.help.CacheManager
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.widget.text.EditText import io.legado.app.ui.widget.text.EditText
import io.legado.app.ui.widget.text.TextInputLayout import io.legado.app.ui.widget.text.TextInputLayout
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
class SourceLoginDialog : BaseDialogFragment() { class SourceLoginDialog : BaseDialogFragment() {
private val binding by viewBinding(DialogLoginBinding::bind) companion object {
fun start(fragmentManager: FragmentManager, sourceUrl: String) {
}
}
private val binding by viewBinding(DialogLoginBinding::bind)
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -35,19 +37,27 @@ class SourceLoginDialog : BaseDialogFragment() {
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
binding.toolBar.setBackgroundColor(primaryColor) binding.toolBar.setBackgroundColor(primaryColor)
val sourceUrl = arguments?.getString("sourceUrl") val sourceUrl = arguments?.getString("sourceUrl") ?: return
val loginRule = arguments?.getParcelable<LoginRule>("loginRule") val bookSource = appDb.bookSourceDao.getBookSource(sourceUrl) ?: return
val loginHeader = bookSource.getLoginHeader()
val loginRule = bookSource.loginUrl
loginRule?.ui?.forEachIndexed { index, rowUi -> loginRule?.ui?.forEachIndexed { index, rowUi ->
when (rowUi.type) { when (rowUi.type) {
"text" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root) "text" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root)
.apply { .apply {
id = index id = index
findViewById<EditText>(R.id.editText).apply {
setText(loginHeader?.get(rowUi.name))
}
} }
"password" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root) "password" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root)
.apply { .apply {
id = index id = index
findViewById<EditText>(R.id.editText)?.inputType = findViewById<EditText>(R.id.editText).apply {
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT inputType =
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
setText(loginHeader?.get(rowUi.name))
}
} }
} }
} }
@ -66,14 +76,7 @@ class SourceLoginDialog : BaseDialogFragment() {
} }
} }
} }
val data = Base64.encodeToString( bookSource.putLoginHeader(GSON.toJson(loginData))
EncoderUtils.decryptAES(
GSON.toJson(loginData).toByteArray(),
AppConst.androidId.toByteArray()
),
Base64.DEFAULT
)
CacheManager.put("login_$sourceUrl", data)
} }
} }
return@setOnMenuItemClickListener true return@setOnMenuItemClickListener true

Loading…
Cancel
Save