diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-29 21:43:24 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-29 21:43:24 +0100 |
| commit | 6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d (patch) | |
| tree | 08974eee67646435fd2c54030002b2b2d8d351a2 /src/client/ui.rs | |
| parent | v2.3.1: settle orphaned reservations on server restart (diff) | |
| download | zagan-bet-6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d.tar.gz zagan-bet-6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d.zip | |
v2.3.2: group hosts by certificate fingerprint
Diffstat (limited to '')
| -rw-r--r-- | src/client/ui.rs | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/src/client/ui.rs b/src/client/ui.rs index 1a35db1..0fe78ae 100644 --- a/src/client/ui.rs +++ b/src/client/ui.rs | |||
| @@ -247,14 +247,38 @@ pub fn first_contact_lines(addr: &str, fingerprint: &str) -> Vec<String> { | |||
| 247 | 247 | ||
| 248 | /// Format remembered hosts so a 64-character fingerprint does not wrap on an | 248 | /// Format remembered hosts so a 64-character fingerprint does not wrap on an |
| 249 | /// 80-column terminal. | 249 | /// 80-column terminal. |
| 250 | /// Render remembered hosts. | ||
| 251 | /// | ||
| 252 | /// Two addresses that present the same certificate key are the same server, so | ||
| 253 | /// they are grouped under one fingerprint: `127.0.0.1:11525` and | ||
| 254 | /// `10.0.0.100:11525` reached through different networks still show as one | ||
| 255 | /// entry. Hosts without a fingerprint are never merged, since nothing proves | ||
| 256 | /// they are related. | ||
| 250 | pub fn host_lines(hosts: &[(String, Option<String>)]) -> Vec<String> { | 257 | pub fn host_lines(hosts: &[(String, Option<String>)]) -> Vec<String> { |
| 251 | if hosts.is_empty() { | 258 | if hosts.is_empty() { |
| 252 | return vec!["No remembered hosts.".to_string()]; | 259 | return vec!["No remembered hosts.".to_string()]; |
| 253 | } | 260 | } |
| 254 | 261 | ||
| 255 | let mut lines = vec!["Remembered hosts:".to_string()]; | 262 | let mut groups: Vec<(Option<&str>, Vec<&str>)> = Vec::new(); |
| 256 | for (host, fingerprint) in hosts { | 263 | for (host, fingerprint) in hosts { |
| 257 | lines.push(format!(" {host}")); | 264 | match fingerprint { |
| 265 | Some(fingerprint) => { | ||
| 266 | match groups | ||
| 267 | .iter_mut() | ||
| 268 | .find(|(key, _)| *key == Some(fingerprint.as_str())) | ||
| 269 | { | ||
| 270 | Some((_, addresses)) => addresses.push(host), | ||
| 271 | None => groups.push((Some(fingerprint), vec![host])), | ||
| 272 | } | ||
| 273 | } | ||
| 274 | // An unknown key proves nothing about identity. | ||
| 275 | None => groups.push((None, vec![host])), | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | let mut lines = vec!["Remembered hosts:".to_string()]; | ||
| 280 | for (fingerprint, addresses) in groups { | ||
| 281 | lines.push(format!(" {}", addresses.join(", "))); | ||
| 258 | match fingerprint { | 282 | match fingerprint { |
| 259 | Some(fingerprint) => lines.push(format!(" fingerprint: {fingerprint}")), | 283 | Some(fingerprint) => lines.push(format!(" fingerprint: {fingerprint}")), |
| 260 | None => lines.push(" (no fingerprint)".to_string()), | 284 | None => lines.push(" (no fingerprint)".to_string()), |
