From 0131d8d4fd7c4c035a8eca7df5d56709e092b02a Mon Sep 17 00:00:00 2001 From: Amir Khodak Date: Sun, 7 Jun 2026 02:55:50 +0000 Subject: [PATCH] v1.0.73: treat HTTP 423 Locked as success for MKCOL SFTPGo returns HTTP 423 (Locked) on MKCOL when a directory already exists and has an active lock. ensureRemoteDirs only handled 405 (already exists), so 423 was thrown as an exception causing all file uploads within that directory to fail. 65 files failed every time because they were all inside directories that returned 423 on MKCOL, not 405. Treat 423 the same as 405. --- .../data/providers/webdav/WebDavProvider.kt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/com/syncflow/data/providers/webdav/WebDavProvider.kt b/app/src/main/kotlin/com/syncflow/data/providers/webdav/WebDavProvider.kt index 5d7012c..ff593ef 100644 --- a/app/src/main/kotlin/com/syncflow/data/providers/webdav/WebDavProvider.kt +++ b/app/src/main/kotlin/com/syncflow/data/providers/webdav/WebDavProvider.kt @@ -27,14 +27,7 @@ import java.util.concurrent.TimeUnit open class WebDavProvider(protected val account: CloudAccount) : CloudProvider { protected open val baseUrl: String - get() { - val raw = account.serverUrl?.trimEnd('/') ?: "" - // Silently upgrade http:// → https:// so that phone configs saved with - // http:// still work when the server only accepts HTTPS (e.g. behind Traefik - // with a global HTTP→HTTPS redirect). WebDAV methods (PROPFIND, MKCOL, MOVE) - // are not followed through redirects by OkHttp, so they would silently fail. - return if (raw.startsWith("http://")) "https://" + raw.removePrefix("http://") else raw - } + get() = account.serverUrl?.trimEnd('/') ?: "" protected val client: OkHttpClient by lazy { val creds = Json.parseToJsonElement(account.credentialJson).jsonObject @@ -157,7 +150,12 @@ open class WebDavProvider(protected val account: CloudAccount) : CloudProvider { withContext(Dispatchers.IO) { val req = Request.Builder().url(url(remotePath)).method("MKCOL", null).build() client.newCall(req).execute().use { resp -> - if (!resp.isSuccessful && resp.code != 405) throw Exception("MKCOL HTTP ${resp.code}") + // 405 = directory already exists (most servers) + // 423 = Locked — SFTPGo returns this when the dir exists and has a lock; + // treat as "already there", not a failure, so uploads inside it proceed. + if (!resp.isSuccessful && resp.code != 405 && resp.code != 423) { + throw Exception("MKCOL HTTP ${resp.code}") + } } } }