**Formatted values.** A revealed value is shown as it reads best: JSON indented, and PEM certificates as subject, issuer, valid dates, names and SHA-1 thumbprint instead of base64. Any other PEM block (a private key in a bundle) is named, `EC PRIVATE KEY (not shown)`, never shown. Anything else shows as before. `y` copies the value exactly as stored, and the hints line says so (`JSON, formatted: y copies it as stored`). **Errors in the status pane.** This session's errors, newest first, up to 20, with the time and what they were about (`12:32 kv-restricted: 403 Forbidden: …`): lists that couldn't load, values and details that couldn't be read, sources, saving the cache, and whatever the footer flashed (a failed copy) before you moved on. A repeat moves to the top. Sign-ins aren't listed (the footer and the account say those). Only the first line of each, and not kept after quitting. `y` copies one. **No access list for Databricks scopes.** It was the one request of its own left (one call per scope). Removed with its tests and docs; refusals still say what to check. **Copying over SSH: checked, nothing to change.** Over SSH (`SSH_TTY`/`SSH_CONNECTION`), `y` copies with OSC 52, and the 30-second clear works the same way. Your tmux (3.7, `set-clipboard on`) passes it through and kitty (`clipboard_control write-clipboard`) accepts it; docs/config.md already says what's needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com> Reviewed-on: #19
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package panes
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"crypto/x509"
|
|
"encoding/json"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// A revealed value is shown as it reads best: JSON indented, and PEM
|
|
// certificates as what they say (subject, issuer, dates, names) rather
|
|
// than base64, with any other PEM block, a private key say, named but not
|
|
// shown. Anything else is shown as it is. y copies it as stored.
|
|
|
|
// valueView is how to show v, and what's been done to it ("" when it's
|
|
// shown as it is).
|
|
func valueView(v string) (lines []string, note string) {
|
|
if lines, ok := pemView(v); ok {
|
|
return lines, "certificate"
|
|
}
|
|
if t := strings.TrimSpace(v); (strings.HasPrefix(t, "{") || strings.HasPrefix(t, "[")) && json.Valid([]byte(t)) {
|
|
var b bytes.Buffer
|
|
if json.Indent(&b, []byte(t), "", " ") == nil {
|
|
return strings.Split(b.String(), "\n"), "JSON, formatted"
|
|
}
|
|
}
|
|
return strings.Split(v, "\n"), ""
|
|
}
|
|
|
|
// pemView describes the PEM blocks in v, if it's PEM with a certificate.
|
|
func pemView(v string) ([]string, bool) {
|
|
rest := []byte(strings.TrimSpace(v))
|
|
var out []string
|
|
certs := 0
|
|
for len(rest) > 0 {
|
|
block, after := pem.Decode(rest)
|
|
if block == nil {
|
|
return nil, false // text that isn't PEM: show it all
|
|
}
|
|
rest = bytes.TrimSpace(after)
|
|
if len(out) > 0 {
|
|
out = append(out, "")
|
|
}
|
|
if block.Type != "CERTIFICATE" {
|
|
out = append(out, block.Type+" (not shown)")
|
|
continue
|
|
}
|
|
cert, err := x509.ParseCertificate(block.Bytes)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
certs++
|
|
out = append(out, certLines(cert)...)
|
|
}
|
|
return out, certs > 0
|
|
}
|
|
|
|
func certLines(c *x509.Certificate) []string {
|
|
day := func(t time.Time) string { return t.UTC().Format("2006-01-02") }
|
|
out := []string{
|
|
"subject " + c.Subject.String(),
|
|
"issuer " + c.Issuer.String(),
|
|
"valid " + day(c.NotBefore) + " to " + day(c.NotAfter),
|
|
}
|
|
names := append([]string{}, c.DNSNames...)
|
|
for _, ip := range c.IPAddresses {
|
|
names = append(names, ip.String())
|
|
}
|
|
names = append(names, c.EmailAddresses...)
|
|
if len(names) > 0 {
|
|
out = append(out, "names "+strings.Join(names, ", "))
|
|
}
|
|
sum := sha1.Sum(c.Raw) // what Azure and Windows call the thumbprint
|
|
return append(out, "SHA-1 "+fmt.Sprintf("%X", sum[:]))
|
|
}
|