Revert "Improve dummy-lock handling"
authorLanius Trolling <lanius@laniustrolling.dev>
Sun, 22 Dec 2024 20:52:29 +0000 (15:52 -0500)
committerLanius Trolling <lanius@laniustrolling.dev>
Sun, 22 Dec 2024 20:52:29 +0000 (15:52 -0500)
This reverts commit addb9066729fdda5be277dd72b99859973226c5b.

src/main/kotlin/info/mechyrdia/route/ResourceWebDav.kt

index 46c57957035660fee60bc34f1c9207b250a50fad..c33a6dff505643e04cc559939b1380b17cbcfb3a 100644 (file)
@@ -34,13 +34,7 @@ import io.ktor.server.routing.Route
 import io.ktor.server.routing.method
 import io.ktor.server.routing.route
 import io.ktor.util.AttributeKey
-import kotlinx.html.a
-import kotlinx.html.body
-import kotlinx.html.h1
-import kotlinx.html.head
-import kotlinx.html.li
-import kotlinx.html.title
-import kotlinx.html.ul
+import kotlinx.html.*
 import java.net.URI
 import java.time.Instant
 import java.time.ZoneOffset
@@ -75,10 +69,7 @@ sealed class WebDavProperties : XmlInsertable {
                                        resourceProps()
                                        "supportedlock" {
                                                "lockentry" {
-                                                       "lockscope" {
-                                                               "shared"()
-                                                               "exclusive"()
-                                                       }
+                                                       "lockscope" { "shared"() }
                                                        "locktype" { "write"() }
                                                }
                                        }
@@ -365,139 +356,28 @@ suspend fun ApplicationCall.webDavDelete(path: StoragePath) {
                respond(HttpStatusCode.NotFound)
 }
 
-private sealed interface WebDavLockInfo {
-       @JvmInline
-       value class Scalar(val value: String?) : WebDavLockInfo
-       
-       @JvmInline
-       value class Complex(val subTags: Map<String, WebDavLockInfo>) : WebDavLockInfo
-}
-
-private fun XmlTag.webDavLockInfo(info: WebDavLockInfo, tag: String) {
-       when (info) {
-               is WebDavLockInfo.Scalar -> {
-                       info.value?.let {
-                               tag { +it }
-                       } ?: tag()
-               }
-               
-               is WebDavLockInfo.Complex -> {
-                       tag {
-                               for ((k, v) in info.subTags)
-                                       webDavLockInfo(v, k)
-                       }
-               }
-       }
-}
-
-private fun getXmlTagPrefix(line: String): String {
-       val xmlnsIndex = line.indexOf("xmlns:")
-       if (xmlnsIndex < 0)
-               return ""
-       
-       val namespace = line.substring(xmlnsIndex + 6).substringBefore('=')
-       return "$namespace:"
-}
-
-private enum class XmlTagType {
-       SCALAR, OPEN, CLOSE
-}
-
-private fun getXmlTagType(line: String, prefix: String): Triple<String, XmlTagType, String?>? {
-       val (isClose, lineMinusAngleBracket) = if (line.startsWith("</"))
-               Pair(true, line.substring(2))
-       else if (line.startsWith("<"))
-               Pair(false, line.substring(1))
-       else
-               return null
-       
-       val lineMinusPrefix = lineMinusAngleBracket.removePrefix(prefix)
-       val tag = lineMinusPrefix.substringBefore('>')
-       if (isClose)
-               return Triple(tag, XmlTagType.CLOSE, null)
-       
-       if (tag.endsWith("/"))
-               return Triple(tag.substring(0, tag.length - 1), XmlTagType.SCALAR, null)
-       
-       if (lineMinusPrefix.endsWith("</$prefix$tag>"))
-               return Triple(tag, XmlTagType.SCALAR, lineMinusPrefix.substring(tag.length + 1, tag.length + prefix.length + 3))
-       
-       return Triple(tag, XmlTagType.OPEN, null)
-}
-
-private fun <T : Any> Iterator<T>.nextOrNull(): T? = if (hasNext()) next() else null
-
-private fun Iterator<String>.buildLockInfoTree(xmlTagPrefix: String? = null): Pair<Pair<String, WebDavLockInfo>?, Boolean> {
-       val line = nextOrNull()?.trim() ?: return Pair(null, false)
-       if (line.isBlank() || line.startsWith("<?"))
-               return Pair(null, true)
-       
-       val prefix = xmlTagPrefix ?: getXmlTagPrefix(line)
-       val (tagName, tagType, tagValue) = getXmlTagType(line, prefix) ?: return Pair(null, true)
-       
-       when (tagType) {
-               XmlTagType.SCALAR -> return Pair(Pair(tagName, WebDavLockInfo.Scalar(tagValue)), true)
-               XmlTagType.OPEN -> {
-                       val subTrees = buildMap {
-                               do {
-                                       val (subTree, hasNext) = buildLockInfoTree(prefix)
-                                       subTree?.let { (k, v) -> put(k, v) }
-                               } while (hasNext)
-                       }
-                       
-                       return Pair(Pair(tagName, WebDavLockInfo.Complex(subTrees)), true)
-               }
-               
-               XmlTagType.CLOSE -> return Pair(null, false)
-       }
-}
-
-private val defaultLockInfo: WebDavLockInfo.Complex = WebDavLockInfo.Complex(
-       mapOf(
-               "lockscope" to WebDavLockInfo.Complex(
-                       mapOf(
-                               "shared" to WebDavLockInfo.Scalar(null)
-                       )
-               ),
-               "locktype" to WebDavLockInfo.Complex(
-                       mapOf(
-                               "write" to WebDavLockInfo.Scalar(null)
-                       )
-               ),
-               "owner" to WebDavLockInfo.Scalar(null),
-       )
-)
-
-private const val InfiniteTimeout: String = "Second-31556925000"
-
-private suspend fun ApplicationCall.parseRequestLockInfo(): WebDavLockInfo.Complex {
-       val depth = request.header(HttpHeaders.Depth) ?: "Infinity"
-       val (requestLockInfoTag, _) = receiveText().lineSequence().iterator().buildLockInfoTree()
-       val requestLockInfo = requestLockInfoTag?.takeIf { it.first == "lockinfo" }?.second as? WebDavLockInfo.Complex ?: defaultLockInfo
-       
-       return WebDavLockInfo.Complex(
-               requestLockInfo.subTags + mapOf(
-                       "depth" to WebDavLockInfo.Scalar(depth),
-                       "timeout" to WebDavLockInfo.Scalar(InfiniteTimeout),
-                       "locktoken" to WebDavLockInfo.Complex(
-                               mapOf(
-                                       "href" to WebDavLockInfo.Scalar("opaquelocktoken:${UUID.randomUUID()}")
-                               )
-                       )
-               )
-       )
-}
-
 suspend fun ApplicationCall.webDavLock(path: StoragePath) {
        beforeWebDav()
        
-       val info = parseRequestLockInfo()
+       if (request.header(HttpHeaders.ContentType) != null)
+               receiveText()
+       
+       val depth = request.header(HttpHeaders.Depth) ?: "Infinity"
        
        respondXml {
                declaration()
                        .root("prop", namespace = "DAV:") {
                                "lockdiscovery" {
-                                       webDavLockInfo(info, "activeLock")
+                                       "activelock" {
+                                               "lockscope" { "shared"() }
+                                               "locktype" { "write"() }
+                                               "depth" { +depth }
+                                               "owner"()
+                                               "timeout" { +"Second-86400" }
+                                               "locktoken" {
+                                                       "href" { +"opaquelocktoken:${UUID.randomUUID()}" }
+                                               }
+                                       }
                                }
                        }
        }