Merge remote-tracking branch 'origin/master'

pull/32/head
Administrator 5 years ago
commit 0f70ab546b
  1. 4
      app/build.gradle
  2. 3
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt
  3. 42
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  4. 6
      app/src/main/java/io/legado/app/model/book/All.kt
  5. 5
      app/src/main/java/io/legado/app/model/book/BookChapterList.kt
  6. 5
      app/src/main/java/io/legado/app/model/book/BookContent.kt
  7. 5
      app/src/main/java/io/legado/app/model/book/BookInfo.kt
  8. 5
      app/src/main/java/io/legado/app/model/book/BookList.kt
  9. 28
      app/src/main/java/io/legado/app/utils/Encoder.kt
  10. 22
      app/src/main/java/io/legado/app/utils/FileUtils.kt
  11. 34
      app/src/main/java/io/legado/app/utils/NetworkUtils.kt
  12. 1
      app/src/main/java/io/legado/app/utils/README.md
  13. 2
      app/src/main/java/io/legado/app/utils/StringExtensions.kt

@ -80,8 +80,8 @@ dependencies {
//androidX //androidX
implementation 'androidx.core:core-ktx:1.2.0-alpha02' implementation 'androidx.core:core-ktx:1.2.0-alpha02'
implementation 'androidx.appcompat:appcompat:1.1.0-beta01' implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.preference:preference:1.1.0-beta01' implementation 'androidx.preference:preference:1.1.0-rc01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
implementation 'com.google.android.material:material:1.1.0-alpha07' implementation 'com.google.android.material:material:1.1.0-alpha07'
implementation 'com.google.android:flexbox:1.1.0' implementation 'com.google.android:flexbox:1.1.0'

@ -2,7 +2,6 @@ package io.legado.app.model.analyzeRule
import android.text.TextUtils.isEmpty import android.text.TextUtils.isEmpty
import android.text.TextUtils.join import android.text.TextUtils.join
import io.legado.app.utils.startWithIgnoreCase
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Collector import org.jsoup.select.Collector
@ -414,7 +413,7 @@ class AnalyzeByJSoup {
var replacement = "" var replacement = ""
init { init {
if (ruleStr.startWithIgnoreCase("@CSS:")) { if (ruleStr.startsWith("@CSS:", true)) {
isCss = true isCss = true
elementsRule = ruleStr.substring(5).trim { it <= ' ' } elementsRule = ruleStr.substring(5).trim { it <= ' ' }
} else { } else {

@ -6,10 +6,9 @@ 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.Pattern.EXP_PATTERN import io.legado.app.constant.Pattern.EXP_PATTERN
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.utils.Encoder import io.legado.app.utils.*
import io.legado.app.utils.GSON import okhttp3.FormBody
import io.legado.app.utils.NetworkUtils import okhttp3.MediaType
import io.legado.app.utils.fromJsonObject
import okhttp3.RequestBody import okhttp3.RequestBody
import java.net.URLEncoder import java.net.URLEncoder
import java.util.* import java.util.*
@ -33,6 +32,7 @@ class AnalyzeUrl(
) { ) {
companion object { companion object {
private val pagePattern = Pattern.compile("<(.*?)>") private val pagePattern = Pattern.compile("<(.*?)>")
private val jsonType = MediaType.parse("application/json; charset=utf-8")
} }
lateinit var url: String lateinit var url: String
@ -43,7 +43,7 @@ class AnalyzeUrl(
private set private set
var queryStr: String? = null var queryStr: String? = null
private set private set
private val queryMap = LinkedHashMap<String, String>() private val fieldMap = LinkedHashMap<String, String>()
private val headerMap = HashMap<String, String>() private val headerMap = HashMap<String, String>()
private var charset: String? = null private var charset: String? = null
private var bodyTxt: String? = null private var bodyTxt: String? = null
@ -55,9 +55,9 @@ class AnalyzeUrl(
val postData: ByteArray val postData: ByteArray
get() { get() {
val builder = StringBuilder() val builder = StringBuilder()
val keys = queryMap.keys val keys = fieldMap.keys
for (key in keys) { for (key in keys) {
builder.append(String.format("%s=%s&", key, queryMap[key])) builder.append(String.format("%s=%s&", key, fieldMap[key]))
} }
builder.deleteCharAt(builder.lastIndexOf("&")) builder.deleteCharAt(builder.lastIndexOf("&"))
return builder.toString().toByteArray() return builder.toString().toByteArray()
@ -130,9 +130,7 @@ class AnalyzeUrl(
options?.let { options?.let {
options["method"]?.let { if (it.equals("POST", true)) method = Method.POST } options["method"]?.let { if (it.equals("POST", true)) method = Method.POST }
options["headers"]?.let { headers -> options["headers"]?.let { headers ->
GSON.fromJsonObject<Map<String, String>>( GSON.fromJsonObject<Map<String, String>>(headers)?.let { headerMap.putAll(it) }
headers
)?.let { headerMap.putAll(it) }
} }
options["body"]?.let { bodyTxt = it } options["body"]?.let { bodyTxt = it }
options["charset"]?.let { charset = it } options["charset"]?.let { charset = it }
@ -143,11 +141,21 @@ class AnalyzeUrl(
urlArray = url.split("\\?".toRegex()) urlArray = url.split("\\?".toRegex())
url = urlArray[0] url = urlArray[0]
if (urlArray.size > 1) { if (urlArray.size > 1) {
analyzePutFields(urlArray[1]) analyzeFields(urlArray[1])
} }
} }
Method.POST -> { Method.POST -> {
bodyTxt bodyTxt?.let {
if (it.isJson()) {
body = RequestBody.create(jsonType, it)
} else {
analyzeFields(it)
val builder = FormBody.Builder()
for (item in fieldMap)
builder.add(item.key, item.value)
body = builder.build()
}
}
} }
} }
} }
@ -157,7 +165,7 @@ class AnalyzeUrl(
* 解析QueryMap * 解析QueryMap
*/ */
@Throws(Exception::class) @Throws(Exception::class)
private fun analyzePutFields(fieldsTxt: String) { private fun analyzeFields(fieldsTxt: String) {
queryStr = fieldsTxt queryStr = fieldsTxt
val queryS = fieldsTxt.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() val queryS = fieldsTxt.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (query in queryS) { for (query in queryS) {
@ -165,14 +173,14 @@ class AnalyzeUrl(
val value = if (queryM.size > 1) queryM[1] else "" val value = if (queryM.size > 1) queryM[1] else ""
if (TextUtils.isEmpty(charset)) { if (TextUtils.isEmpty(charset)) {
if (NetworkUtils.hasUrlEncoded(value)) { if (NetworkUtils.hasUrlEncoded(value)) {
queryMap[queryM[0]] = value fieldMap[queryM[0]] = value
} else { } else {
queryMap[queryM[0]] = URLEncoder.encode(value, "UTF-8") fieldMap[queryM[0]] = URLEncoder.encode(value, "UTF-8")
} }
} else if (charset == "escape") { } else if (charset == "escape") {
queryMap[queryM[0]] = Encoder.escape(value) fieldMap[queryM[0]] = Encoder.escape(value)
} else { } else {
queryMap[queryM[0]] = URLEncoder.encode(value, charset) fieldMap[queryM[0]] = URLEncoder.encode(value, charset)
} }
} }
} }

@ -0,0 +1,6 @@
package io.legado.app.model.book
class All {
}

@ -0,0 +1,5 @@
package io.legado.app.model.book
class BookChapterList {
}

@ -0,0 +1,5 @@
package io.legado.app.model.book
class BookContent {
}

@ -0,0 +1,5 @@
package io.legado.app.model.book
class BookInfo {
}

@ -0,0 +1,5 @@
package io.legado.app.model.book
class BookList {
}

@ -3,26 +3,20 @@ package io.legado.app.utils
object Encoder { object Encoder {
fun escape(src: String): String { fun escape(src: String): String {
var i = 0
var char: Char
val tmp = StringBuilder() val tmp = StringBuilder()
tmp.ensureCapacity(src.length * 6) for (char in src) {
while (i < src.length) { val charCode = char.toInt()
char = src[i] if (charCode in 48..57 || charCode in 65..90 || charCode in 97..122) {
if (Character.isDigit(char) || Character.isLowerCase(char)
|| Character.isUpperCase(char)
)
tmp.append(char) tmp.append(char)
else if (char.toInt() < 256) { continue
tmp.append("%")
if (char.toInt() < 16)
tmp.append("0")
tmp.append(char.toInt().toString(16))
} else {
tmp.append("%u")
tmp.append(char.toInt().toString(16))
} }
i++
val prefix = when {
charCode < 16 -> "%0"
charCode < 256 -> "%"
else -> "%u"
}
tmp.append(prefix).append(charCode.toString(16))
} }
return tmp.toString() return tmp.toString()
} }

@ -21,20 +21,7 @@ object FileUtils {
fun getSdPath() = Environment.getExternalStorageDirectory().absolutePath fun getSdPath() = Environment.getExternalStorageDirectory().absolutePath
fun getFileByPath(filePath: String): File? { fun getFileByPath(filePath: String): File? {
return if (isSpace(filePath)) null else File(filePath) return if (filePath.isBlank()) null else File(filePath)
}
fun isSpace(s: String?): Boolean {
if (s == null) return true
var i = 0
val len = s.length
while (i < len) {
if (!Character.isWhitespace(s[i])) {
return false
}
++i
}
return true
} }
fun getSdCardPath(): String { fun getSdCardPath(): String {
@ -101,12 +88,9 @@ object FileUtils {
return paths return paths
} }
@TargetApi(Build.VERSION_CODES.KITKAT)
fun getPath(context: Context, uri: Uri): String? { fun getPath(context: Context, uri: Uri): String? {
val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
// DocumentProvider // DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { if (DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider // ExternalStorageProvider
if (isExternalStorageDocument(uri)) { if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri) val docId = DocumentsContract.getDocumentId(uri)
@ -119,7 +103,7 @@ object FileUtils {
} else if (isDownloadsDocument(uri)) { } else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri) val id = DocumentsContract.getDocumentId(uri)
val split = id.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() val split = id.split(":").dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0] val type = split[0]
if ("raw".equals( if ("raw".equals(
type, type,

@ -8,37 +8,18 @@ object NetworkUtils {
private val notNeedEncoding: BitSet by lazy { private val notNeedEncoding: BitSet by lazy {
val bitSet = BitSet(256) val bitSet = BitSet(256)
var i: Int = 'a'.toInt() for (i in 'a'.toInt()..'z'.toInt()) {
while (i <= 'z'.toInt()) {
bitSet.set(i) bitSet.set(i)
i++
} }
i = 'A'.toInt() for (i in 'A'.toInt()..'Z'.toInt()) {
while (i <= 'Z'.toInt()) {
bitSet.set(i) bitSet.set(i)
i++
} }
i = '0'.toInt() for (i in '0'.toInt()..'9'.toInt()) {
while (i <= '9'.toInt()) {
bitSet.set(i) bitSet.set(i)
i++
} }
bitSet.set('+'.toInt()) for (char in "+-_.$:()!*@&#,[]") {
bitSet.set('-'.toInt()) bitSet.set(char.toInt())
bitSet.set('_'.toInt()) }
bitSet.set('.'.toInt())
bitSet.set('$'.toInt())
bitSet.set(':'.toInt())
bitSet.set('('.toInt())
bitSet.set(')'.toInt())
bitSet.set('!'.toInt())
bitSet.set('*'.toInt())
bitSet.set('@'.toInt())
bitSet.set('&'.toInt())
bitSet.set('#'.toInt())
bitSet.set(','.toInt())
bitSet.set('['.toInt())
bitSet.set(']'.toInt())
return@lazy bitSet return@lazy bitSet
} }
@ -69,7 +50,6 @@ object NetworkUtils {
// 其他字符,肯定需要urlEncode // 其他字符,肯定需要urlEncode
needEncode = true needEncode = true
break break
i++
} }
return !needEncode return !needEncode
@ -79,7 +59,7 @@ object NetworkUtils {
* 判断c是否是16进制的字符 * 判断c是否是16进制的字符
*/ */
private fun isDigit16Char(c: Char): Boolean { private fun isDigit16Char(c: Char): Boolean {
return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' return c in '0'..'9' || c in 'A'..'F' || c in 'a'..'f'
} }
/** /**

@ -17,7 +17,7 @@ fun String?.isJson(): Boolean = this?.run {
} ?: false } ?: false
fun String?.htmlFormat(): String = if (this.isNullOrBlank()) "" else fun String?.htmlFormat(): String = if (this.isNullOrBlank()) "" else
this.replace("(?i)<(br[\\s/]*|/*p.*?|/*div.*?)>".toRegex(), "\n")// 替换特定标签为换行符 this.replace("(?i)<(br[\\s/]*|/*p\\b.*?|/*div\\b.*?)>".toRegex(), "\n")// 替换特定标签为换行符
.replace("<[script>]*.*?>|&nbsp;".toRegex(), "")// 删除script标签对和空格转义符 .replace("<[script>]*.*?>|&nbsp;".toRegex(), "")// 删除script标签对和空格转义符
.replace("\\s*\\n+\\s*".toRegex(), "\n  ")// 移除空行,并增加段前缩进2个汉字 .replace("\\s*\\n+\\s*".toRegex(), "\n  ")// 移除空行,并增加段前缩进2个汉字
.replace("^[\\n\\s]+".toRegex(), "  ")//移除开头空行,并增加段前缩进2个汉字 .replace("^[\\n\\s]+".toRegex(), "  ")//移除开头空行,并增加段前缩进2个汉字

Loading…
Cancel
Save