Skip to content

Commit

Permalink
Url encode templated values by default
Browse files Browse the repository at this point in the history
  • Loading branch information
kunyavskiy authored and kbats183 committed Mar 1, 2024
1 parent 88ecfb0 commit 40692ad
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 20 deletions.
14 changes: 7 additions & 7 deletions config/vkoshp/2023/advanced.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@
"screen": {
"type": "WebRTCGrabberConnection",
"peerName": "{grabberPeerName}",
"url": "{grabberUrl}",
"url": "http://{grabberIp}:8080",
"streamType": "desktop",
"credential": "live"
},
"camera": {
"type": "WebRTCGrabberConnection",
"url": "{grabberUrl}",
"url": "http://{grabberIp}:8080",
"peerName": "{grabberPeerName}",
"streamType": "webcam",
"credential": "live"
Expand Down Expand Up @@ -125,11 +125,11 @@
"nsk(\\d\\d\\d)": "N$1",
"kaz(\\d\\d\\d)": "K$1"
},
"grabberUrl": {
"spb(\\d\\d\\d)": "http://192.168.0.112:8000",
"geo(\\d\\d\\d)": "http://192.168.0.175:8000",
"nsk(\\d\\d\\d)": "http://192.168.0.175:8000",
"kaz(\\d\\d\\d)": "http://192.168.0.175:8000"
"grabberIp": {
"spb(\\d\\d\\d)": "192.168.0.112",
"geo(\\d\\d\\d)": "192.168.0.175",
"nsk(\\d\\d\\d)": "192.168.0.175",
"kaz(\\d\\d\\d)": "192.168.0.175"
}
},
"groupRegex": {
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ktor-client-auth = { version.ref = "ktor", group = "io.ktor", name = "ktor
ktor-client-contentNegotiation = { version.ref = "ktor", group = "io.ktor", name = "ktor-client-content-negotiation" }

ktor-serialization-kotlinx-json = { version.ref = "ktor", group = "io.ktor", name = "ktor-serialization-kotlinx-json" }
ktor-http = { version.ref = "ktor", group = "io.ktor", name = "ktor-http" }

ktor-server-auth = { version.ref = "ktor", group = "io.ktor", name = "ktor-server-auth" }
ktor-server-autoHeadResponse = { version.ref = "ktor", group = "io.ktor", name = "ktor-server-auto-head-response" }
Expand Down
1 change: 1 addition & 0 deletions src/cds/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
implementation(projects.cds.utils)
implementation(libs.kotlin.reflect)
implementation(libs.kotlinx.serialization.json5)
implementation(libs.ktor.http)
ksp(projects.ksp)
compileOnly(projects.ksp)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package org.icpclive.cds.adapters

import io.ktor.http.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
Expand All @@ -21,18 +22,27 @@ private data object Trigger : AdvancedAdapterEvent

internal object AdvancedPropertiesAdapter

private val templateRegex = kotlin.text.Regex("\\{([a-z0-9A-Z_-]*)}")
private val templateRegex = kotlin.text.Regex("\\{(!?[a-z0-9A-Z_-]*)}")

private fun String.applyTemplate(valueProvider: (String) -> String?) =
replace(templateRegex) { valueProvider(it.groups[1]!!.value) ?: it.value }

private fun urlEncoded(block: (String) -> String?) : (String) -> String? = l@{
block(it.removePrefix("!"))?.run {
if (it.startsWith("!"))
this
else
encodeURLParameter()
}
}

private fun MediaType.applyTemplate(valueProvider: (String) -> String?) = when (this) {
is MediaType.Photo -> copy(url = url.applyTemplate(valueProvider))
is MediaType.Video -> copy(url = url.applyTemplate(valueProvider))
is MediaType.Object -> copy(url = url.applyTemplate(valueProvider))
is MediaType.WebRTCProxyConnection -> copy(url = url.applyTemplate(valueProvider))
is MediaType.Photo -> copy(url = url.applyTemplate(urlEncoded(valueProvider)))
is MediaType.Video -> copy(url = url.applyTemplate(urlEncoded(valueProvider)))
is MediaType.Object -> copy(url = url.applyTemplate(urlEncoded(valueProvider)))
is MediaType.WebRTCProxyConnection -> copy(url = url.applyTemplate(urlEncoded(valueProvider)))
is MediaType.WebRTCGrabberConnection -> copy(
url = url.applyTemplate(valueProvider),
url = url.applyTemplate(urlEncoded(valueProvider)),
peerName = peerName.applyTemplate(valueProvider),
credential = credential?.applyTemplate(valueProvider)
)
Expand Down Expand Up @@ -139,15 +149,20 @@ private fun <K, V> mergeMaps(original: Map<K, V>, override: Map<K, V?>) = buildM
private fun TeamOverrideTemplate.instantiateTemplate(
teams: List<TeamInfo>,
valueProvider: TeamInfo.(String) -> String?,
) = teams.associate {
it.contestSystemId to TeamInfoOverride(
hashTag = hashTag?.applyTemplate { name -> it.valueProvider(name) },
fullName = fullName?.applyTemplate { name -> it.valueProvider(name) },
displayName = displayName?.applyTemplate { name -> it.valueProvider(name) },
medias = medias?.mapValues { (_, v) -> v?.applyTemplate { name -> it.valueProvider(name) } }
)
) = teams.associate { team ->
team.contestSystemId to instantiateTemplate { team.valueProvider(it) }
}

internal fun TeamOverrideTemplate.instantiateTemplate(
valueProvider: (String) -> String?,
): TeamInfoOverride = TeamInfoOverride(
hashTag = hashTag?.applyTemplate(valueProvider),
fullName = fullName?.applyTemplate(valueProvider),
displayName = displayName?.applyTemplate(valueProvider),
medias = medias?.mapValues { (_, v) -> v?.applyTemplate(valueProvider) }
)


private fun List<TeamInfo>.filterNotSubmitted(show: Boolean?, submittedTeams: Set<Int>) = if (show != false) {
this
} else {
Expand Down
38 changes: 38 additions & 0 deletions src/cds/core/src/test/kotlin/TeamInfoOverrideTemplateTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import org.icpclive.cds.adapters.instantiateTemplate
import org.icpclive.cds.api.MediaType
import org.icpclive.cds.api.TeamMediaType
import org.icpclive.cds.tunning.TeamOverrideTemplate
import kotlin.test.*

object TeamInfoOverrideTemplateTest {
private fun TeamOverrideTemplate.instantiate(map: Map<String, String>) = instantiateTemplate {
map[it]
}

@Test
fun `check url encodes`() {
val template = TeamOverrideTemplate(
displayName = "{teamName}",
medias = mapOf(
TeamMediaType.CAMERA to MediaType.Photo("http://photos-server/{teamName}"),
TeamMediaType.REACTION_VIDEO to MediaType.WebRTCGrabberConnection(
url = "{!grabberUrl}",
peerName = "{teamName}",
streamType = "",
credential = null
)
)
)
val teamName = "Team name with spaces & other / strange : symbols?"
val teamReplaced = "Team%20name%20with%20spaces%20%26%20other%20%2F%20strange%20%3A%20symbols%3F"
val url = "http://this-should-not-be-replaced:12345/url"
val instantiated = template.instantiate(mapOf(
"teamName" to teamName,
"grabberUrl" to url
))
assertEquals(teamName, instantiated.displayName)
assertEquals("http://photos-server/${teamReplaced}", (instantiated.medias?.get(TeamMediaType.CAMERA) as MediaType.Photo).url)
assertEquals(url, (instantiated.medias?.get(TeamMediaType.REACTION_VIDEO) as MediaType.WebRTCGrabberConnection).url)
assertEquals(teamName, (instantiated.medias?.get(TeamMediaType.REACTION_VIDEO) as MediaType.WebRTCGrabberConnection).peerName)
}
}

0 comments on commit 40692ad

Please sign in to comment.