Added unicode and HTML decoding to video titles.

This commit is contained in:
Koen 2023-09-28 10:31:39 +02:00
parent 3527d8bac6
commit c1a97f3843
6 changed files with 84 additions and 14 deletions

View File

@ -9,9 +9,7 @@ import android.graphics.BitmapFactory
import android.os.Build import android.os.Build
import android.os.Looper import android.os.Looper
import android.os.OperationCanceledException import android.os.OperationCanceledException
import android.util.DisplayMetrics
import android.util.TypedValue import android.util.TypedValue
import android.view.Display
import android.view.View import android.view.View
import android.view.WindowInsetsController import android.view.WindowInsetsController
import android.widget.TextView import android.widget.TextView
@ -22,17 +20,12 @@ import com.futo.platformplayer.api.media.models.video.IPlatformVideo
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.PlatformVideoWithTime import com.futo.platformplayer.models.PlatformVideoWithTime
import com.futo.platformplayer.others.PlatformLinkMovementMethod import com.futo.platformplayer.others.PlatformLinkMovementMethod
import com.futo.platformplayer.states.StatePlatform
import org.json.JSONArray
import org.json.JSONObject
import userpackage.Protocol
import java.io.File import java.io.File
import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.* import java.util.*
import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.ThreadLocalRandom
import kotlin.math.abs
import kotlin.math.min
private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "; private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
fun getRandomString(sizeOfRandomString: Int): String { fun getRandomString(sizeOfRandomString: Int): String {
@ -157,3 +150,56 @@ fun File.share(context: Context) {
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(chooserIntent); context.startActivity(chooserIntent);
} }
fun String.decodeUnicode(): String {
val sb = StringBuilder()
var i = 0
while (i < this.length) {
var ch = this[i]
if (ch == '\\' && i + 1 < this.length) {
i++
ch = this[i]
when (ch) {
'\\' -> sb.append('\\')
't' -> sb.append('\t')
'n' -> sb.append('\n')
'r' -> sb.append('\r')
'f' -> sb.append('\u000C')
'b' -> sb.append('\b')
'"' -> sb.append('"')
'\'' -> sb.append('\'')
'u' -> {
if (i + 4 < this.length) {
val unicode = this.substring(i + 1, i + 5)
try {
sb.append(unicode.toInt(16).toChar())
} catch (e: NumberFormatException) {
throw IOException("Invalid Unicode sequence: $unicode")
}
i += 4
} else {
throw IOException("Incomplete Unicode sequence")
}
}
in '0'..'7' -> {
val end = (i + 3).coerceAtMost(this.length)
val octal = this.substring(i, end).takeWhile { it in '0'..'7' }
try {
sb.append(octal.toInt(8).toChar())
i += octal.length - 1
} catch (e: NumberFormatException) {
throw IOException("Invalid Octal sequence: $octal")
}
}
else -> sb.append(ch)
}
} else {
sb.append(ch)
}
i++
}
return sb.toString()
}

View File

@ -5,7 +5,7 @@ import com.futo.platformplayer.api.media.models.comments.IPlatformComment
import com.futo.platformplayer.api.media.models.playback.IPlaybackTracker import com.futo.platformplayer.api.media.models.playback.IPlaybackTracker
import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.api.media.structures.IPager
interface IPlatformContentDetails: IPlatformContent { interface IPlatformContentDetails : IPlatformContent {
fun getComments(client: IPlatformClient): IPager<IPlatformComment>?; fun getComments(client: IPlatformClient): IPager<IPlatformComment>?;

View File

@ -1,5 +1,6 @@
package com.futo.platformplayer.api.media.platforms.js.models package com.futo.platformplayer.api.media.platforms.js.models
import androidx.core.text.HtmlCompat
import com.caoccao.javet.values.reference.V8ValueObject import com.caoccao.javet.values.reference.V8ValueObject
import com.futo.platformplayer.api.media.IPluginSourced import com.futo.platformplayer.api.media.IPluginSourced
import com.futo.platformplayer.api.media.PlatformID import com.futo.platformplayer.api.media.PlatformID
@ -7,8 +8,10 @@ import com.futo.platformplayer.api.media.models.PlatformAuthorLink
import com.futo.platformplayer.api.media.models.contents.ContentType import com.futo.platformplayer.api.media.models.contents.ContentType
import com.futo.platformplayer.api.media.models.contents.IPlatformContent import com.futo.platformplayer.api.media.models.contents.IPlatformContent
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
import com.futo.platformplayer.decodeUnicode
import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrDefault
import com.futo.platformplayer.getOrThrow import com.futo.platformplayer.getOrThrow
import com.futo.platformplayer.logging.Logger
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.time.ZoneOffset import java.time.ZoneOffset
@ -38,7 +41,8 @@ open class JSContent : IPlatformContent, IPluginSourced {
val contextName = "PlatformContent"; val contextName = "PlatformContent";
id = PlatformID.fromV8(_pluginConfig, _content.getOrThrow(config, "id", contextName)); id = PlatformID.fromV8(_pluginConfig, _content.getOrThrow(config, "id", contextName));
name = _content.getOrThrow(config, "name", contextName); name = HtmlCompat.fromHtml(_content.getOrThrow<String>(config, "name", contextName).decodeUnicode(), HtmlCompat.FROM_HTML_MODE_LEGACY).toString();
Logger.i("JSContent", "name=$name");
author = PlatformAuthorLink.fromV8(_pluginConfig, _content.getOrThrow(config, "author", contextName)); author = PlatformAuthorLink.fromV8(_pluginConfig, _content.getOrThrow(config, "author", contextName));
val datetimeInt = _content.getOrThrow<Int>(config, "datetime", contextName).toLong(); val datetimeInt = _content.getOrThrow<Int>(config, "datetime", contextName).toLong();

View File

@ -3,6 +3,7 @@ package com.futo.platformplayer.fragment.mainactivity.main
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.os.Bundle import android.os.Bundle
import android.text.Html
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View

View File

@ -1,19 +1,19 @@
package com.futo.platformplayer package com.futo.platformplayer
import com.futo.platformplayer.payment.StatePayment import com.futo.platformplayer.states.StatePayment
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
class PaymentTests { class PaymentTests {
private val PAYMENT_KEY_TEST = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+PeflxecURXXi0WLVbXnUF0XwOKBleXOERBBGxW57X76mqIBC7FddogV/Z5Ym/YtxDNmAWxBRjO0iz8bz1iNT5AdGQ1y+kFvPaSKbJILmte2cWmFn2ga1uqAesUnLVVeWF9uA/nScABb7o1DaAhsONQfosfTz8X87S7r8g28A4wjYB5WR657NiSdXHOIyyIFrozM1JvHfGXQ7PlER1lBkbExDC6aLc7LRQY/++5pPWS9m/O+9EpeztqBkQZLIql6BvCZVYhOgMzLNCsYvvIN/mmY27eTYeCAm7v2fDWSZ1Badc083HOecpqDq2XCDewzf5Ea5t/SI93XhPiEi9UewIDAQAB"; /*private val PAYMENT_KEY_TEST = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+PeflxecURXXi0WLVbXnUF0XwOKBleXOERBBGxW57X76mqIBC7FddogV/Z5Ym/YtxDNmAWxBRjO0iz8bz1iNT5AdGQ1y+kFvPaSKbJILmte2cWmFn2ga1uqAesUnLVVeWF9uA/nScABb7o1DaAhsONQfosfTz8X87S7r8g28A4wjYB5WR657NiSdXHOIyyIFrozM1JvHfGXQ7PlER1lBkbExDC6aLc7LRQY/++5pPWS9m/O+9EpeztqBkQZLIql6BvCZVYhOgMzLNCsYvvIN/mmY27eTYeCAm7v2fDWSZ1Badc083HOecpqDq2XCDewzf5Ea5t/SI93XhPiEi9UewIDAQAB";
@Test @Test
fun `check payment validation`() { fun `check payment validation`() {
val lkey = "Q42S-48S8-EJJZ-N9HH-ARAZ-GKBC-F1JV-K49E"; val lkey = "Q42S-48S8-EJJZ-N9HH-ARAZ-GKBC-F1JV-K49E";
val activationKey = "m3VoUrXfhZumP4AoVqE6tRpxw5yJYSr49wRX_BO7-urNjjkAjWFFtNFR1Ytl8hsUo8zY_WP17uQP62W0Ocq8I8p46giyKXvFL8VbtqMSn4s4YUX6kYxgtKlzOd6-yNOF7RLd1DZJqHhpJ5juO3qmi9fKWfO9XiV368s-H7HNBWY8hSkprf40ANdKJ7m7QZ2Gf7kSM8Ld8KWmXCHooVfjfpl6vx5GXEvEumCPDKhwg-EYd2MBizUaDszdm_dufzcjC9EwpxO9SS-EjBdhpOSSRWU7gebDON8d4zTKBgkH0T6PBhF_iEuvFTmeIp7V5f_g1dCUuUCDEq6NvwikH3SrXA"; val activationKey = "m3VoUrXfhZumP4AoVqE6tRpxw5yJYSr49wRX_BO7-urNjjkAjWFFtNFR1Ytl8hsUo8zY_WP17uQP62W0Ocq8I8p46giyKXvFL8VbtqMSn4s4YUX6kYxgtKlzOd6-yNOF7RLd1DZJqHhpJ5juO3qmi9fKWfO9XiV368s-H7HNBWY8hSkprf40ANdKJ7m7QZ2Gf7kSM8Ld8KWmXCHooVfjfpl6vx5GXEvEumCPDKhwg-EYd2MBizUaDszdm_dufzcjC9EwpxO9SS-EjBdhpOSSRWU7gebDON8d4zTKBgkH0T6PBhF_iEuvFTmeIp7V5f_g1dCUuUCDEq6NvwikH3SrXA";
val validator = StatePayment.LicenseValidator(PAYMENT_KEY_TEST); val validator = StatePayment(PAYMENT_KEY_TEST);
Assert.assertTrue(validator.validate(lkey, activationKey)); Assert.assertTrue(validator.validate(lkey, activationKey));
} }*/
} }

View File

@ -2,9 +2,12 @@ package com.futo.platformplayer
import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertTrue import junit.framework.TestCase.assertTrue
import org.junit.Assert.assertThrows
import org.junit.Test import org.junit.Test
import java.io.IOException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
class UtilityTests { class UtilityTests {
private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "; private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
@ -33,4 +36,20 @@ class UtilityTests {
val result = findNonRuntimeException(runtimeException) val result = findNonRuntimeException(runtimeException)
assertEquals(innerException, result) assertEquals(innerException, result)
} }
@Test
fun testDecodeString() {
assertThrows(IOException::class.java) { "\\u02-3".decodeUnicode() }
assertEquals("", "".decodeUnicode())
assertEquals("test", "test".decodeUnicode())
assertEquals("\ntest\b", "\\ntest\\b".decodeUnicode())
assertEquals("\u123425foo\ntest\b", "\\u123425foo\\ntest\\b".decodeUnicode())
assertEquals("'\u000coo\teste\r", "\\'\\u000coo\\teste\\r".decodeUnicode())
assertEquals("\\", "\\".decodeUnicode())
assertEquals("\uABCDx", "\\uabcdx".decodeUnicode())
assertEquals("\uABCDx", "\\uABCDx".decodeUnicode())
assertEquals("\uABCD", "\\uabcd".decodeUnicode())
assertEquals("\ud83d\udc80\ud83d\udd14", "\\ud83d\\udc80\\ud83d\\udd14".decodeUnicode())
assertEquals("String with a slash (/) in it", "String with a slash (/) in it".decodeUnicode())
}
} }