diff --git a/VERSION b/VERSION index c043eea..276cbf9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.1 +2.3.0 diff --git a/bombadillo.1 b/bombadillo.1 index ef3e479..b337a8e 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -59,7 +59,7 @@ Displaying web content directly in \fBbombadillo\fP requires lynx, w3m or elinks These commands work as a single keypress anytime \fBbombadillo\fP is not taking in a line based command or when the user is being prompted for action. This is the default command mode of \fBbombadillo\fP. .TP .B -b +b, h Navigate back one place in your document history. .TP .B @@ -71,7 +71,7 @@ d Scroll down an amount corresponding to 75% of your terminal window height in the current document. .TP .B -f +f, l Navigate forward one place in your document history. .TP .B @@ -95,6 +95,7 @@ n Jump to next found text item. .TP .B +N Jump to previous found text item. .TP .B diff --git a/client.go b/client.go index b74e2c0..d21c39e 100644 --- a/client.go +++ b/client.go @@ -168,15 +168,15 @@ func (c *client) TakeControlInput() { } else { c.goToLink(string(input)) } - case 'j', 'J': + case 'j': // scroll down one line c.ClearMessage() c.Scroll(1) - case 'k', 'K': + case 'k': // scroll up one line c.ClearMessage() c.Scroll(-1) - case 'q', 'Q': + case 'q': // quit bombadillo cui.Exit(0, "") case 'g': @@ -197,7 +197,7 @@ func (c *client) TakeControlInput() { c.ClearMessage() distance := c.Height - c.Height/4 c.Scroll(-distance) - case 'b': + case 'b', 'h': // go back c.ClearMessage() err := c.PageState.NavigateHistory(-1) @@ -222,7 +222,7 @@ func (c *client) TakeControlInput() { // open the bookmarks browser c.BookMarks.ToggleOpen() c.Draw() - case 'f', 'F': + case 'f', 'l': // go forward c.ClearMessage() err := c.PageState.NavigateHistory(1) @@ -711,11 +711,11 @@ func (c *client) search(query, url, question string) { } switch u.Scheme { case "gopher": - go c.Visit(fmt.Sprintf("%s\t%s", u.Full, entry)) + c.Visit(fmt.Sprintf("%s\t%s", u.Full, entry)) case "gemini": // TODO url escape the entry variable escapedEntry := entry - go c.Visit(fmt.Sprintf("%s?%s", u.Full, escapedEntry)) + c.Visit(fmt.Sprintf("%s?%s", u.Full, escapedEntry)) case "http", "https": c.Visit(u.Full) default: diff --git a/gemini/gemini.go b/gemini/gemini.go index e90fe98..a721152 100644 --- a/gemini/gemini.go +++ b/gemini/gemini.go @@ -49,8 +49,8 @@ func (t *TofuDigest) Purge(host string) error { return fmt.Errorf("Invalid host %q", host) } -func (t *TofuDigest) Add(host, hash string) { - t.certs[strings.ToLower(host)] = hash +func (t *TofuDigest) Add(host, hash string, time int64) { + t.certs[strings.ToLower(host)] = fmt.Sprintf("%s|%d", hash, time) } func (t *TofuDigest) Exists(host string) bool { @@ -67,12 +67,11 @@ func (t *TofuDigest) Find(host string) (string, error) { return "", fmt.Errorf("Invalid hostname, no key saved") } -func (t *TofuDigest) Match(host string, cState *tls.ConnectionState) error { - host = strings.ToLower(host) +func (t *TofuDigest) Match(host, localCert string, cState *tls.ConnectionState) error { now := time.Now() for _, cert := range cState.PeerCertificates { - if t.certs[host] != hashCert(cert.Raw) { + if localCert != hashCert(cert.Raw) { continue } @@ -118,13 +117,40 @@ func (t *TofuDigest) newCert(host string, cState *tls.ConnectionState) error { continue } - t.Add(host, hashCert(cert.Raw)) + t.Add(host, hashCert(cert.Raw), cert.NotAfter.Unix()) return nil } return fmt.Errorf(reasons.String()) } +func (t *TofuDigest) GetCertAndTimestamp(host string) (string, int64, error) { + certTs, err := t.Find(host) + if err != nil { + return "", -1, err + } + certTsSplit := strings.SplitN(certTs, "|", -1) + if len(certTsSplit) < 2 { + _ = t.Purge(host) + return certTsSplit[0], -1, fmt.Errorf("Invalid certstring, no delimiter") + } + ts, err := strconv.ParseInt(certTsSplit[1], 10, 64) + if err != nil { + _ = t.Purge(host) + return certTsSplit[0], -1, err + } + now := time.Now() + if ts < now.Unix() { + // Ignore error return here since an error would indicate + // the host does not exist and we have already checked for + // that and the desired outcome of the action is that the + // host will no longer exist, so we are good either way + _ = t.Purge(host) + return "", -1, fmt.Errorf("Expired cert") + } + return certTsSplit[0], ts, nil +} + func (t *TofuDigest) IniDump() string { if len(t.certs) < 1 { return "" @@ -176,9 +202,11 @@ func Retrieve(host, port, resource string, td *TofuDigest) (string, error) { return "", fmt.Errorf("Insecure, no certificates offered by server") } - if td.Exists(host) { + localCert, localTs, err := td.GetCertAndTimestamp(host) + + if localTs > 0 { // See if we have a matching cert - err := td.Match(host, &connState) + err := td.Match(host, localCert, &connState) if err != nil && err.Error() != "EXP" { // If there is no match and it isnt because of an expiration // just return the error diff --git a/main.go b/main.go index 53918f7..1266eeb 100644 --- a/main.go +++ b/main.go @@ -25,8 +25,10 @@ import ( "os" "os/signal" "path/filepath" + "strconv" "strings" "syscall" + "time" "tildegit.org/sloum/bombadillo/config" "tildegit.org/sloum/bombadillo/cui" @@ -132,7 +134,20 @@ func loadConfig() { } for _, v := range settings.Certs { - bombadillo.Certs.Add(v.Key, v.Value) + // Remove expired certs + vals := strings.SplitN(v.Value, "|", -1) + if len(vals) < 2 { + continue + } + ts, err := strconv.ParseInt(vals[1], 10, 64) + now := time.Now() + if err != nil || now.Unix() > ts { + continue + } + // Satisfied that the cert is not expired + // or malformed: add to the current client + // instance + bombadillo.Certs.Add(v.Key, vals[0], ts) } } diff --git a/page.go b/page.go index 4ca0842..6973a7c 100644 --- a/page.go +++ b/page.go @@ -70,7 +70,9 @@ func (p *Page) WrapContent(width int, color bool) { p.RenderImage(width) return } + width = min(width, 100) counter := 0 + spacer := " " var content strings.Builder var esc strings.Builder escape := false @@ -124,7 +126,6 @@ func (p *Page) WrapContent(width int, color bool) { content.WriteRune('\n') counter = 0 if p.Location.Mime == "1" { - spacer := " " content.WriteString(spacer) counter += len(spacer) } @@ -188,3 +189,10 @@ func MakePage(url Url, content string, links []string) Page { p := Page{make([]string, 0), content, links, url, 0, make([]int, 0), "", 0, "", 40, false} return p } + +func min(a, b int) int { + if a < b { + return a + } + return b +}