fix: sanitize station names and validate URLs in parsers

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-10 01:12:46 -04:00
parent fcf02c2595
commit bb14a6af53
7 changed files with 86 additions and 25 deletions

View File

@@ -27,6 +27,7 @@ object M3uParser {
trimmed.startsWith("#") -> continue
else -> {
val url = trimmed
if (url.isBlank()) continue
val name = currentName ?: deriveNameFromUrl(url)
result.add(ParsedStation(name = name, url = url, artworkUrl = currentArtworkUrl))
currentName = null
@@ -37,14 +38,4 @@ object M3uParser {
return result
}
private fun deriveNameFromUrl(url: String): String {
val path = try {
java.net.URI(url).path
} catch (_: Exception) {
url
}
val lastSegment = path.trimEnd('/').substringAfterLast('/')
return lastSegment.ifEmpty { url }
}
}

View File

@@ -0,0 +1,11 @@
package xyz.cottongin.radio247.data.importing
internal fun deriveNameFromUrl(url: String): String {
val path = try {
java.net.URI(url).path
} catch (_: Exception) {
url
}
val lastSegment = path.trimEnd('/').substringAfterLast('/')
return lastSegment.ifEmpty { url }
}

View File

@@ -7,7 +7,8 @@ object PlaylistExporter {
val sb = StringBuilder()
sb.append("#EXTM3U\n")
for (station in stations) {
sb.append("#EXTINF:-1,").append(station.name).append("\n")
val safeName = station.name.replace("\n", " ").replace("\r", " ")
sb.append("#EXTINF:-1,").append(safeName).append("\n")
if (station.defaultArtworkUrl != null) {
sb.append("#EXTIMG:").append(station.defaultArtworkUrl).append("\n")
}
@@ -20,8 +21,9 @@ object PlaylistExporter {
val sb = StringBuilder()
sb.append("[playlist]\n")
stations.forEachIndexed { index, station ->
val safeName = station.name.replace("\n", " ").replace("\r", " ")
sb.append("File").append(index + 1).append("=").append(station.url).append("\n")
sb.append("Title").append(index + 1).append("=").append(station.name).append("\n")
sb.append("Title").append(index + 1).append("=").append(safeName).append("\n")
}
sb.append("NumberOfEntries=").append(stations.size).append("\n")
sb.append("Version=2\n")

View File

@@ -34,26 +34,17 @@ object PlsParser {
}
}
return entries.keys.sorted().map { index ->
return entries.keys.sorted().mapNotNull { index ->
val entry = entries[index]!!
val url = entry["url"] ?: return@map null
val url = (entry["url"] ?: return@mapNotNull null).trim()
if (url.isBlank()) return@mapNotNull null
val name = entry["name"] ?: deriveNameFromUrl(url)
ParsedStation(name = name, url = url)
}.filterNotNull()
}
}
private fun parseIndex(key: String, prefix: String): Int? {
val suffix = key.removePrefix(prefix)
return suffix.toIntOrNull()
}
private fun deriveNameFromUrl(url: String): String {
val path = try {
java.net.URI(url).path
} catch (_: Exception) {
url
}
val lastSegment = path.trimEnd('/').substringAfterLast('/')
return lastSegment.ifEmpty { url }
}
}