diff options
| author | Lena <lena@omega> | 2026-08-23 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-08-23 00:00:00 +0000 |
| commit | e8c6c4ebb3d76ee280043bb66cf499584c591310 (patch) | |
| tree | b3ba91a370140a74f689d1d27155fc3830a278a8 /app/src/main/java/invalid | |
| parent | 82c21c0177c162902985ab6edf762ef7e4e3d099 (diff) | |
| download | rsend-e8c6c4ebb3d76ee280043bb66cf499584c591310.tar.gz | |
app: report config limits instead of crashing
The remote and folder counts and the serialized config size are enforced
only inside save, which throws. Every other rule an editor can break is
reported in the form, so a config that outgrew a limit crashed the
activity instead of saying so. overLimit answers before the entry is
added, and the editors report the answer.
hostKeyAllowed reconstructs the known_hosts address that rsh writes with
knownhosts.Normalize, and nothing recorded or tested that coupling.
Normalize leaves the host bare on port 22 for IPv6 literals too, so
bracketing them here looks right and would reject every IPv6 pin.
Diffstat (limited to 'app/src/main/java/invalid')
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/Config.kt | 16 | ||||
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/FolderEditActivity.kt | 8 | ||||
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/RemoteActivity.kt | 5 |
3 files changed, 28 insertions, 1 deletions
diff --git a/app/src/main/java/invalid/lena/rsend/Config.kt b/app/src/main/java/invalid/lena/rsend/Config.kt index 25bf338..a38fbde 100644 --- a/app/src/main/java/invalid/lena/rsend/Config.kt +++ b/app/src/main/java/invalid/lena/rsend/Config.kt @@ -57,6 +57,9 @@ object RemoteRules { if (remote.hostKey.length > MAX_HOST_KEY_CHARS) return false val parts = remote.hostKey.split(' ') if (parts.size != 3 || parts.any(String::isEmpty)) return false + // Must be exactly the address rsh writes, which is knownhosts.Normalize: + // the bare host on port 22, including an IPv6 literal, "[host]:port" + // otherwise. A different form here silently stops matching the pin. val address = if (remote.port == 22) remote.host else "[${remote.host}]:${remote.port}" if (parts[0] != address || parts[1] !in hostKeyTypes) return false return try { @@ -187,6 +190,19 @@ data class Config( } } + // overLimit reports why c cannot be persisted, or null. These are the + // only save failures a form cannot rule out on its own, so the editors + // ask before adding an entry and report the answer. Every other rule + // fromJson enforces is already checked field by field; one firing there + // is a bug and must throw. + fun overLimit(c: Config): String? = when { + c.remotes.size > MAX_REMOTES -> "Too many remotes; the limit is $MAX_REMOTES." + c.folders.size > MAX_FOLDERS -> "Too many folders; the limit is $MAX_FOLDERS." + c.toJson().toString(2).toByteArray(Charsets.UTF_8).size > MAX_CONFIG_BYTES -> + "Configuration is too large; the limit is $MAX_CONFIG_BYTES bytes." + else -> null + } + // legacyShape reports whether o is the pre-0.2 config 0.1.x wrote: one // "remote" object instead of a "remotes" array. fun legacyShape(o: JSONObject): Boolean = diff --git a/app/src/main/java/invalid/lena/rsend/FolderEditActivity.kt b/app/src/main/java/invalid/lena/rsend/FolderEditActivity.kt index 5565bff..47961c1 100644 --- a/app/src/main/java/invalid/lena/rsend/FolderEditActivity.kt +++ b/app/src/main/java/invalid/lena/rsend/FolderEditActivity.kt @@ -161,7 +161,13 @@ class FolderEditActivity : AppCompatActivity() { } val list = cfg.folders.toMutableList() if (index in list.indices) list[index] = f else list.add(f) - Config.save(this, cfg.copy(folders = list)) + val next = cfg.copy(folders = list) + val limit = Config.overLimit(next) + if (limit != null) { + Toast.makeText(this, limit, Toast.LENGTH_LONG).show() + return false + } + Config.save(this, next) return true } diff --git a/app/src/main/java/invalid/lena/rsend/RemoteActivity.kt b/app/src/main/java/invalid/lena/rsend/RemoteActivity.kt index 994e233..83f499d 100644 --- a/app/src/main/java/invalid/lena/rsend/RemoteActivity.kt +++ b/app/src/main/java/invalid/lena/rsend/RemoteActivity.kt @@ -130,6 +130,11 @@ class RemoteActivity : AppCompatActivity() { "folder \"${b.name.ifEmpty { b.remotePath }}\"." return -1 } + val limit = Config.overLimit(next) + if (limit != null) { + status.text = limit + return -1 + } Config.save(this, next) Scheduler.apply(this) return at |