From 552e21113902ba5e37aeca6e91541a2608a61008 Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Tue, 22 Oct 2019 22:02:32 -0700 Subject: [PATCH 1/9] Adds web support in lynx mode --- bombadillo.1 | 9 +++++++-- client.go | 44 +++++++++++++++++++++++++++++++----------- defaults.go | 2 +- http/lynx_mode.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++ main.go | 4 +++- 5 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 http/lynx_mode.go diff --git a/bombadillo.1 b/bombadillo.1 index 1fea65a..c03d56f 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -215,8 +215,13 @@ homeurl The url that \fBbombadillo\fP navigates to when the program loads or when the \fIhome\fP or \fIh\fP LINE COMMAND is issued. This should be a valid url. If a scheme/protocol is not included, gopher will be assumed. .TP .B +lynxmode +Will use lynx as a rendering engine for http/https requests if lynx is installed and \fIopenhttp\fP is set to \fItrue\fP. Valid values are \fItrue\fP and \fIfalse\fP. +.TP +.B openhttp -Tells the client whether or not to try to follow web (http/https) links. If set to \fItrue\fP, \fBbombadillo\fP will try to open a user's default web browser to the link in question. Any value other than \fItrue\fP is considered false. +Tells the client whether or not to try to follow web (http/https) links. If set to \fItrue\fP, \fBbombadillo\fP will try to open a user's default web browser to the link in question. Valid values are \fItrue\fP and \fIfalse\fP. + .TP .B savelocation @@ -232,7 +237,7 @@ Tells the client what command to use to start a telnet session. Should be a vali .TP .B terminalonly -Sets whether or not to try to open non-text files served via gemini in gui programs or not. If set to \fItrue\fP, bombdaillo will only attempt to use terminal programs to open files. If set to anything else, \fBbombadillo\fP may choose from the appropriate programs installed on the system, if one is present. +Sets whether or not to try to open non-text files served via gemini in gui programs or not. If set to \fItrue\fP \fBbombdaillo\fP will only attempt to use terminal programs to open files. If set to \fIfalse\fP \fBbombadillo\fP may choose from the appropriate programs installed on the system, including graphical ones. .TP .B theme diff --git a/client.go b/client.go index 71b998d..4b49f77 100644 --- a/client.go +++ b/client.go @@ -972,19 +972,41 @@ func (c *client) Visit(url string) { } c.Draw() case "http", "https": - c.SetMessage("Attempting to open in web browser", false) - c.DrawMessage() - if strings.ToUpper(c.Options["openhttp"]) == "TRUE" { - msg, err := http.OpenInBrowser(u.Full) - if err != nil { - c.SetMessage(err.Error(), true) - } else { - c.SetMessage(msg, false) - } - c.DrawMessage() - } else { + if strings.ToUpper(c.Options["openhttp"]) != "TRUE" { c.SetMessage("'openhttp' is not set to true, cannot open web link", false) c.DrawMessage() + return + } + switch strings.ToUpper(c.Options["lynxmode"]) { + case "TRUE": + page, err := http.Visit(u.Full, c.Width - 1) + if err != nil { + c.SetMessage(fmt.Sprintf("Lynx error: %s", err.Error()), true) + c.DrawMessage() + return + } + pg := MakePage(u, page.Content, page.Links) + pg.WrapContent(c.Width - 1) + c.PageState.Add(pg) + c.SetPercentRead() + c.ClearMessage() + c.SetHeaderUrl() + c.Draw() + default: + if strings.ToUpper(c.Options["terminalonly"]) == "TRUE" { + c.SetMessage("'terminalonly' is set to true and 'lynxmode' is not enabled, cannot open web link", false) + c.DrawMessage() + } else { + c.SetMessage("Attempting to open in web browser", false) + c.DrawMessage() + msg, err := http.OpenInBrowser(u.Full) + if err != nil { + c.SetMessage(err.Error(), true) + } else { + c.SetMessage(msg, false) + } + c.DrawMessage() + } } case "local": content, err := local.Open(u.Resource) diff --git a/defaults.go b/defaults.go index e3273d2..a7d1661 100644 --- a/defaults.go +++ b/defaults.go @@ -16,12 +16,12 @@ var defaultOptions = map[string]string{ "savelocation": userinfo.HomeDir, "searchengine": "gopher://gopher.floodgap.com:70/7/v2/vs", "openhttp": "false", - "httpbrowser": "lynx", "telnetcommand": "telnet", "configlocation": userinfo.HomeDir, "theme": "normal", // "normal", "inverted" "terminalonly": "true", "tlscertificate": "", "tlskey": "", + "lynxmode": "false", } diff --git a/http/lynx_mode.go b/http/lynx_mode.go new file mode 100644 index 0000000..325b759 --- /dev/null +++ b/http/lynx_mode.go @@ -0,0 +1,49 @@ +package http + +import ( + "fmt" + "os/exec" + "strings" +) + +type page struct { + Content string + Links []string +} + +func Visit(url string, width int) (page, error) { + if width > 80 { + width = 80 + } + w := fmt.Sprintf("-width=%d", width) + c, err := exec.Command("lynx", "-dump", w, url).Output() + if err != nil { + return page{}, err + } + return parseLinks(string(c)), nil +} + +func parseLinks(c string) page { + var out page + contentUntil := strings.LastIndex(c, "References") + if contentUntil >= 1 { + out.Content = c[:contentUntil] + } else { + out.Content = c + out.Links = make([]string, 0) + return out + } + links := c[contentUntil+11:] + links = strings.TrimSpace(links) + linkSlice := strings.Split(links, "\n") + out.Links = make([]string, 0, len(linkSlice)) + for _, link := range linkSlice { + ls := strings.SplitN(link, ".", 2) + if len(ls) < 2 { + continue + } + out.Links = append(out.Links, strings.TrimSpace(ls[1])) + } + return out + +} diff --git a/main.go b/main.go index 249139d..69eba38 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main -// Bombadillo is a gopher and gemini client for the terminal of unix or unix-like systems. +// Bombadillo is an internet client for the terminal of unix or +// unix-like systems. // // Copyright (C) 2019 Brian Evans // @@ -68,6 +69,7 @@ func validateOpt(opt, val string) bool { "openhttp": []string{"true", "false"}, "theme": []string{"normal", "inverse"}, "terminalonly": []string{"true", "false"}, + "lynxmode": []string{"true", "false"}, } opt = strings.ToLower(opt) From 231ccc36d32b6f19f230478d307f623705a0af6f Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Tue, 22 Oct 2019 22:13:08 -0700 Subject: [PATCH 2/9] Ran go fmt on a few files --- client.go | 3 +-- http/lynx_mode.go | 4 ++-- main.go | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client.go b/client.go index 4b49f77..107e1c7 100644 --- a/client.go +++ b/client.go @@ -979,7 +979,7 @@ func (c *client) Visit(url string) { } switch strings.ToUpper(c.Options["lynxmode"]) { case "TRUE": - page, err := http.Visit(u.Full, c.Width - 1) + page, err := http.Visit(u.Full, c.Width-1) if err != nil { c.SetMessage(fmt.Sprintf("Lynx error: %s", err.Error()), true) c.DrawMessage() @@ -1057,7 +1057,6 @@ func (c *client) ReloadPage() error { return nil } - //------------------------------------------------\\ // + + + F U N C T I O N S + + + \\ //--------------------------------------------------\\ diff --git a/http/lynx_mode.go b/http/lynx_mode.go index 325b759..6b431e5 100644 --- a/http/lynx_mode.go +++ b/http/lynx_mode.go @@ -7,8 +7,8 @@ import ( ) type page struct { - Content string - Links []string + Content string + Links []string } func Visit(url string, width int) (page, error) { diff --git a/main.go b/main.go index 69eba38..a755cc5 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,6 @@ package main -// Bombadillo is an internet client for the terminal of unix or +// Bombadillo is an internet client for the terminal of unix or // unix-like systems. // // Copyright (C) 2019 Brian Evans From e5c0bd74432c9bdedf809b4b39b210d33f86b9e1 Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Wed, 23 Oct 2019 19:52:22 -0700 Subject: [PATCH 3/9] Updated man page --- bombadillo.1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bombadillo.1 b/bombadillo.1 index e554608..02c2b6d 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -44,7 +44,7 @@ Telnet is not supported directly, but addresses will be followed and opened as a .TP .B http, https -Neither of the world wide web protocols are supported directly. However, bombadillo is capable of attempting to open web links in a user's default web browser. This feature is opt-in only and controlled in a user's settings. This feature does not function properly in a terminal only environment at present. +Neither of the world wide web protocols are supported directly. However,\fBbombadillo\fPis capable of attempting to open web links in a user's default web browser. This feature is opt-in only and controlled in a user's settings. Opening in a default web browser only works if a user has a gui environment available. An alternate option to get web content directly in the client is to install the lynx web browser on the system and turn on 'lynxmode' in the settings (and opt in to following http links). Doing so will allow web content, rendered by lynx, to be viewable directly in \fBbombadillo\fP. .SH COMMANDS .SS KEY COMMANDS These commands work as a single keypress anytime \fBbombadillo\fP is not taking in a line based command. This is the default command mode of \fBbombadillo\fP. @@ -269,3 +269,4 @@ Gopher Homepage gopher://bombadillo.colorfield.space .SH AUTHORS \fBbombadillo\fP was primarily developed by sloum, with kind and patient assistance from ~asdf and jboverf. + From 67d7df680443566d5c526938cdac7f5b3058ab90 Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Fri, 25 Oct 2019 20:06:13 -0700 Subject: [PATCH 4/9] Reworks the protocol handling and makes html downloads work --- client.go | 402 ++++++++++++++++++++++++++-------------------- http/lynx_mode.go | 36 +++++ 2 files changed, 261 insertions(+), 177 deletions(-) diff --git a/client.go b/client.go index 107e1c7..f106183 100644 --- a/client.go +++ b/client.go @@ -514,6 +514,8 @@ func (c *client) saveFile(u Url, name string) { file, err = gopher.Retrieve(u.Host, u.Port, u.Resource) case "gemini": file, err = gemini.Fetch(u.Host, u.Port, u.Resource, &c.Certs) + case "http", "https": + file, err = http.Fetch(u.Full) default: c.SetMessage(fmt.Sprintf("Saving files over %s is not supported", u.Scheme), true) c.DrawMessage() @@ -737,6 +739,21 @@ func (c *client) Scroll(amount int) { c.Draw() } +func (c *client) ReloadPage() error { + if c.PageState.Length < 1 { + return fmt.Errorf("There is no page to reload") + } + url := c.PageState.History[c.PageState.Position].Location.Full + err := c.PageState.NavigateHistory(-1) + if err != nil { + return err + } + length := c.PageState.Length + c.Visit(url) + c.PageState.Length = length + return nil +} + func (c *client) SetPercentRead() { page := c.PageState.History[c.PageState.Position] var percentRead int @@ -834,6 +851,8 @@ func (c *client) SetHeaderUrl() { } } +// Visit functions as a controller/router to the +// appropriate protocol handler func (c *client) Visit(url string) { c.SetMessage("Loading...", false) c.DrawMessage() @@ -848,137 +867,199 @@ func (c *client) Visit(url string) { switch u.Scheme { case "gopher": - if u.DownloadOnly { - nameSplit := strings.Split(u.Resource, "/") - filename := nameSplit[len(nameSplit)-1] - filename = strings.Trim(filename, " \t\r\n\v\f\a") - if filename == "" { - filename = "gopherfile" - } - c.saveFile(u, filename) - } else if u.Mime == "7" { - c.search("", u.Full, "?") - } else { - content, links, err := gopher.Visit(u.Mime, u.Host, u.Port, u.Resource) - if err != nil { - c.SetMessage(err.Error(), true) - c.DrawMessage() - return - } - pg := MakePage(u, content, links) + c.handleGopher(u) + case "gemini": + c.handleGemini(u) + case "telnet": + c.handleTelnet(u) + case "http", "https": + c.handleWeb(u) + case "local": + c.handleLocal(u) + case "finger": + c.handleFinger(u) + default: + c.SetMessage(fmt.Sprintf("%q is not a supported protocol", u.Scheme), true) + c.DrawMessage() + } +} + + +// +++ Begin Protocol Handlers +++ + +func (c *client) handleGopher(u Url) { + if u.DownloadOnly { + nameSplit := strings.Split(u.Resource, "/") + filename := nameSplit[len(nameSplit)-1] + filename = strings.Trim(filename, " \t\r\n\v\f\a") + if filename == "" { + filename = "gopherfile" + } + c.saveFile(u, filename) + } else if u.Mime == "7" { + c.search("", u.Full, "?") + } else { + content, links, err := gopher.Visit(u.Mime, u.Host, u.Port, u.Resource) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + return + } + pg := MakePage(u, content, links) + pg.WrapContent(c.Width - 1) + c.PageState.Add(pg) + c.SetPercentRead() + c.ClearMessage() + c.SetHeaderUrl() + c.Draw() + } +} + +func (c *client) handleGemini(u Url) { + capsule, err := gemini.Visit(u.Host, u.Port, u.Resource, &c.Certs) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + return + } + go saveConfig() + switch capsule.Status { + case 1: + c.search("", u.Full, capsule.Content) + case 2: + if capsule.MimeMaj == "text" { + pg := MakePage(u, capsule.Content, capsule.Links) pg.WrapContent(c.Width - 1) c.PageState.Add(pg) c.SetPercentRead() c.ClearMessage() c.SetHeaderUrl() c.Draw() - } - case "gemini": - capsule, err := gemini.Visit(u.Host, u.Port, u.Resource, &c.Certs) - if err != nil { - c.SetMessage(err.Error(), true) - c.DrawMessage() - return - } - go saveConfig() - switch capsule.Status { - case 1: - c.search("", u.Full, capsule.Content) - case 2: - if capsule.MimeMaj == "text" { - pg := MakePage(u, capsule.Content, capsule.Links) - pg.WrapContent(c.Width - 1) - c.PageState.Add(pg) - c.SetPercentRead() - c.ClearMessage() - c.SetHeaderUrl() - c.Draw() - } else { - c.SetMessage("The file is non-text: (o)pen or (w)rite to disk", false) - c.DrawMessage() - var ch rune - for { - ch = cui.Getch() - if ch == 'o' || ch == 'w' { - break - } - } - switch ch { - case 'o': - mime := fmt.Sprintf("%s/%s", capsule.MimeMaj, capsule.MimeMin) - var term bool - if c.Options["terminalonly"] == "true" { - term = true - } else { - term = false - } - mcEntry, err := mc.FindMatch(mime, "view", term) - if err != nil { - c.SetMessage(err.Error(), true) - c.DrawMessage() - return - } - file, err := ioutil.TempFile("/tmp/", "bombadillo-*.tmp") - if err != nil { - c.SetMessage("Unable to create temporary file for opening, aborting file open", true) - c.DrawMessage() - return - } - // defer os.Remove(file.Name()) - file.Write([]byte(capsule.Content)) - com, e := mcEntry.Command(file.Name()) - if e != nil { - c.SetMessage(e.Error(), true) - c.DrawMessage() - return - } - com.Stdin = os.Stdin - com.Stdout = os.Stdout - com.Stderr = os.Stderr - if c.Options["terminalonly"] == "true" { - cui.Clear("screen") - } - com.Run() - c.SetMessage("File opened by an appropriate program", true) - c.DrawMessage() - c.Draw() - case 'w': - nameSplit := strings.Split(u.Resource, "/") - filename := nameSplit[len(nameSplit)-1] - c.saveFileFromData(capsule.Content, filename) - } - } - case 3: - c.SetMessage("[3] Redirect. Follow redirect? y or any other key for no", false) - c.DrawMessage() - ch := cui.Getch() - if ch == 'y' || ch == 'Y' { - c.Visit(capsule.Content) - } else { - c.SetMessage("Redirect aborted", false) - c.DrawMessage() - } - } - case "telnet": - c.SetMessage("Attempting to start telnet session", false) - c.DrawMessage() - msg, err := telnet.StartSession(u.Host, u.Port) - if err != nil { - c.SetMessage(err.Error(), true) - c.DrawMessage() } else { - c.SetMessage(msg, true) + c.SetMessage("The file is non-text: (o)pen or (w)rite to disk", false) + c.DrawMessage() + var ch rune + for { + ch = cui.Getch() + if ch == 'o' || ch == 'w' { + break + } + } + switch ch { + case 'o': + mime := fmt.Sprintf("%s/%s", capsule.MimeMaj, capsule.MimeMin) + var term bool + if c.Options["terminalonly"] == "true" { + term = true + } else { + term = false + } + mcEntry, err := mc.FindMatch(mime, "view", term) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + return + } + file, err := ioutil.TempFile("/tmp/", "bombadillo-*.tmp") + if err != nil { + c.SetMessage("Unable to create temporary file for opening, aborting file open", true) + c.DrawMessage() + return + } + // defer os.Remove(file.Name()) + file.Write([]byte(capsule.Content)) + com, e := mcEntry.Command(file.Name()) + if e != nil { + c.SetMessage(e.Error(), true) + c.DrawMessage() + return + } + com.Stdin = os.Stdin + com.Stdout = os.Stdout + com.Stderr = os.Stderr + if c.Options["terminalonly"] == "true" { + cui.Clear("screen") + } + com.Run() + c.SetMessage("File opened by an appropriate program", true) + c.DrawMessage() + c.Draw() + case 'w': + nameSplit := strings.Split(u.Resource, "/") + filename := nameSplit[len(nameSplit)-1] + c.saveFileFromData(capsule.Content, filename) + } + } + case 3: + c.SetMessage("[3] Redirect. Follow redirect? y or any other key for no", false) + c.DrawMessage() + ch := cui.Getch() + if ch == 'y' || ch == 'Y' { + c.Visit(capsule.Content) + } else { + c.SetMessage("Redirect aborted", false) c.DrawMessage() } - c.Draw() - case "http", "https": - if strings.ToUpper(c.Options["openhttp"]) != "TRUE" { - c.SetMessage("'openhttp' is not set to true, cannot open web link", false) - c.DrawMessage() - return - } - switch strings.ToUpper(c.Options["lynxmode"]) { - case "TRUE": + } +} + +func (c *client) handleTelnet(u Url) { + c.SetMessage("Attempting to start telnet session", false) + c.DrawMessage() + msg, err := telnet.StartSession(u.Host, u.Port) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + } else { + c.SetMessage(msg, true) + c.DrawMessage() + } + c.Draw() +} + +func (c *client) handleLocal(u Url) { + content, err := local.Open(u.Resource) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + return + } + pg := MakePage(u, content, []string{}) + pg.WrapContent(c.Width - 1) + c.PageState.Add(pg) + c.SetPercentRead() + c.ClearMessage() + c.SetHeaderUrl() + c.Draw() +} + +func (c *client) handleFinger(u Url) { + content, err := finger.Finger(u.Host, u.Port, u.Resource) + if err != nil { + c.SetMessage(err.Error(), true) + c.DrawMessage() + return + } + pg := MakePage(u, content, []string{}) + pg.WrapContent(c.Width - 1) + c.PageState.Add(pg) + c.SetPercentRead() + c.ClearMessage() + c.SetHeaderUrl() + c.Draw() +} + +func (c *client) handleWeb(u Url) { + // Following http is disabled + if strings.ToUpper(c.Options["openhttp"]) != "TRUE" { + c.SetMessage("'openhttp' is not set to true, cannot open web link", false) + c.DrawMessage() + return + } + + // Use lynxmode + if strings.ToUpper(c.Options["lynxmode"]) == "TRUE" { + if http.IsTextFile(u.Full) { page, err := http.Visit(u.Full, c.Width-1) if err != nil { c.SetMessage(fmt.Sprintf("Lynx error: %s", err.Error()), true) @@ -992,70 +1073,37 @@ func (c *client) Visit(url string) { c.ClearMessage() c.SetHeaderUrl() c.Draw() - default: - if strings.ToUpper(c.Options["terminalonly"]) == "TRUE" { - c.SetMessage("'terminalonly' is set to true and 'lynxmode' is not enabled, cannot open web link", false) - c.DrawMessage() + } else { + c.SetMessage("The file is non-text: writing to disk...", false) + c.DrawMessage() + var fn string + if i := strings.LastIndex(u.Full, "/"); i > 0 && i + 1 < len(u.Full) { + fn = u.Full[i + 1:] } else { - c.SetMessage("Attempting to open in web browser", false) - c.DrawMessage() - msg, err := http.OpenInBrowser(u.Full) - if err != nil { - c.SetMessage(err.Error(), true) - } else { - c.SetMessage(msg, false) - } - c.DrawMessage() + fn = "bombadillo.download" } + c.saveFile(u, fn) } - case "local": - content, err := local.Open(u.Resource) - if err != nil { - c.SetMessage(err.Error(), true) + + // Open in default web browser if available + } else { + if strings.ToUpper(c.Options["terminalonly"]) == "TRUE" { + c.SetMessage("'terminalonly' is set to true and 'lynxmode' is not enabled, cannot open web link", false) c.DrawMessage() - return - } - pg := MakePage(u, content, []string{}) - pg.WrapContent(c.Width - 1) - c.PageState.Add(pg) - c.SetPercentRead() - c.ClearMessage() - c.SetHeaderUrl() - c.Draw() - case "finger": - content, err := finger.Finger(u.Host, u.Port, u.Resource) - if err != nil { - c.SetMessage(err.Error(), true) + } else { + c.SetMessage("Attempting to open in web browser", false) + c.DrawMessage() + msg, err := http.OpenInBrowser(u.Full) + if err != nil { + c.SetMessage(err.Error(), true) + } else { + c.SetMessage(msg, false) + } c.DrawMessage() - return } - pg := MakePage(u, content, []string{}) - pg.WrapContent(c.Width - 1) - c.PageState.Add(pg) - c.SetPercentRead() - c.ClearMessage() - c.SetHeaderUrl() - c.Draw() - default: - c.SetMessage(fmt.Sprintf("%q is not a supported protocol", u.Scheme), true) - c.DrawMessage() } } -func (c *client) ReloadPage() error { - if c.PageState.Length < 1 { - return fmt.Errorf("There is no page to reload") - } - url := c.PageState.History[c.PageState.Position].Location.Full - err := c.PageState.NavigateHistory(-1) - if err != nil { - return err - } - length := c.PageState.Length - c.Visit(url) - c.PageState.Length = length - return nil -} //------------------------------------------------\\ // + + + F U N C T I O N S + + + \\ diff --git a/http/lynx_mode.go b/http/lynx_mode.go index 6b431e5..d329d1d 100644 --- a/http/lynx_mode.go +++ b/http/lynx_mode.go @@ -2,6 +2,8 @@ package http import ( "fmt" + "io/ioutil" + "net/http" "os/exec" "strings" ) @@ -23,6 +25,24 @@ func Visit(url string, width int) (page, error) { return parseLinks(string(c)), nil } +// Returns false on err or non-text type +// Else returns true +func IsTextFile(url string) bool { + c, err := exec.Command("lynx", "-dump", "-head", url).Output() + if err != nil { + return false + } + content := string(c) + content = strings.ToLower(content) + headers := strings.Split(content, "\n") + for _, header := range headers { + if strings.Contains(header, "content-type:") && strings.Contains(header, "text") { + return true + } + } + return false +} + func parseLinks(c string) page { var out page contentUntil := strings.LastIndex(c, "References") @@ -47,3 +67,19 @@ func parseLinks(c string) page { return out } + +func Fetch(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return []byte{}, err + } + defer resp.Body.Close() + + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return []byte{}, err + } + + return bodyBytes, nil +} + From ceeaa2d0f04b1782263d95acf92a3f25d1b5b119 Mon Sep 17 00:00:00 2001 From: asdf Date: Sun, 27 Oct 2019 11:31:06 +1100 Subject: [PATCH 5/9] Spelling/syntax errors, suggested rewrite of web section --- bombadillo.1 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/bombadillo.1 b/bombadillo.1 index 02c2b6d..62eb5af 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -1,4 +1,4 @@ -.TH "bombadillo" 1 "12 OCT 2019" "" "General Opperation Manual" +.TH "bombadillo" 1 "12 OCT 2019" "" "General Operation Manual" .SH NAME \fBbombadillo \fP- a non-web client .SH SYNOPSIS @@ -32,7 +32,7 @@ Gemini is supported, but as a new protocol with an incomplete specification, fea .TP .B finger -Basic support is provided for the finger protocol. The format is: \fIfinger://[[username@]][hostname]\fP. Many servers still support finger and it can be fun to see if friends are online or read about the users who's phlogs you follow. +Basic support is provided for the finger protocol. The format is: \fIfinger://[[username@]][hostname]\fP. Many servers still support finger and it can be fun to see if friends are online or read about the users whose phlogs you follow. .TP .B local @@ -44,7 +44,11 @@ Telnet is not supported directly, but addresses will be followed and opened as a .TP .B http, https -Neither of the world wide web protocols are supported directly. However,\fBbombadillo\fPis capable of attempting to open web links in a user's default web browser. This feature is opt-in only and controlled in a user's settings. Opening in a default web browser only works if a user has a gui environment available. An alternate option to get web content directly in the client is to install the lynx web browser on the system and turn on 'lynxmode' in the settings (and opt in to following http links). Doing so will allow web content, rendered by lynx, to be viewable directly in \fBbombadillo\fP. +Neither of the world wide web protocols are supported directly. However, \fBbombadillo\fP can open web links in a user's default web browser, or display web content directly in the client via the lynx web browser. Opening http links is opt-in only, controlled by the \fIopenhttp\fP setting. +.IP +Opening links in a default web browser only works if a GUI environment is available. +.IP +Opening web content directly in the client requires the lynx web browser, and is enabled using the \fIlynxmode\fP setting. Web content is processed using lynx, and then displayed in the client. .SH COMMANDS .SS KEY COMMANDS These commands work as a single keypress anytime \fBbombadillo\fP is not taking in a line based command. This is the default command mode of \fBbombadillo\fP. @@ -238,11 +242,11 @@ Tells the client what command to use to start a telnet session. Should be a vali .TP .B terminalonly -Sets whether or not to try to open non-text files served via gemini in gui programs or not. If set to \fItrue\fP \fBbombdaillo\fP will only attempt to use terminal programs to open files. If set to \fIfalse\fP \fBbombadillo\fP may choose from the appropriate programs installed on the system, including graphical ones. +Sets whether or not to try to open non-text files served via gemini in GUI programs or not. If set to \fItrue\fP \fBbombadillo\fP will only attempt to use terminal programs to open files. If set to \fIfalse\fP \fBbombadillo\fP may choose from the appropriate programs installed on the system, including graphical ones. .TP .B theme -Can toggle between visual modes. Valid values are \fInormal\fP and \fIinverse\fP. When set to ivnerse, the terminal color mode is inversed. +Can toggle between visual modes. Valid values are \fInormal\fP and \fIinverse\fP. When set to inverse, the terminal color mode is inverted. .TP .B tlscertificate @@ -250,7 +254,7 @@ A path to a tls certificate file on a user's local filesystem. Defaults to NULL. .TP .B tlskey -A path the a tls key that pairs with the tlscertificate setting, on a user's local filesystem. Defaults to NULL. Both \fItlskey\fP and \fItlscertificate\fP must be set for client certificates to work in gemini. +A path to a tls key that pairs with the tlscertificate setting, on a user's local filesystem. Defaults to NULL. Both \fItlskey\fP and \fItlscertificate\fP must be set for client certificates to work in gemini. .SH BUGS There are very likely bugs. Many known bugs can be found in the issues section of \fBbombadillo\fP's software repository (see \fIlinks\fP). .SH LINKS From 9d77c3cea085b2d534762c4f55e390320524fb58 Mon Sep 17 00:00:00 2001 From: asdf Date: Sun, 27 Oct 2019 11:48:03 +1100 Subject: [PATCH 6/9] Removed empty line at end of man page --- bombadillo.1 | 1 - 1 file changed, 1 deletion(-) diff --git a/bombadillo.1 b/bombadillo.1 index 62eb5af..72baf04 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -273,4 +273,3 @@ Gopher Homepage gopher://bombadillo.colorfield.space .SH AUTHORS \fBbombadillo\fP was primarily developed by sloum, with kind and patient assistance from ~asdf and jboverf. - From 9c2caf4a6f2c43a6b96d8064b188244a1aeaa18a Mon Sep 17 00:00:00 2001 From: sloumdrone Date: Sun, 27 Oct 2019 11:09:45 -0700 Subject: [PATCH 7/9] Updates man page --- README.md | 6 ++++-- bombadillo.1 | 4 ++-- client.go | 58 +++++----------------------------------------------- main.go | 6 ------ 4 files changed, 11 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 7593b85..eb09b0f 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,11 @@ These instructions will get a copy of the project up and running on your local m ### Prerequisites -If building from source, you will need to have [Go](https://golang.org/) version >= 1.12. +If building from source, you will need to have [Go](https://golang.org/) version >= 1.11. -While Bombadillo has one external dependency of [Mailcap](https://tildegit.org/sloum/mailcap), no action is typically required to download this, as it is handled automatically during the build process. +#### Optional + +[Lynx](https://lynx.invisible-island.net/), the text based web browser, can be used as a parsing engine for http/https. This is a totally optional item and Lynx is in no way required in order to compile or run Bombadillo. Having it available on the system can help create a richer experience by allowing users to navigate directly to web content in Bombadillo. Many users may wish to avoid this entirely,a nd the default configuration does not have this behavior turned on. To turn it on from within Bombadillo enter the command `set lynxmode true`. ### Installing diff --git a/bombadillo.1 b/bombadillo.1 index 72baf04..b694e3a 100644 --- a/bombadillo.1 +++ b/bombadillo.1 @@ -1,4 +1,4 @@ -.TH "bombadillo" 1 "12 OCT 2019" "" "General Operation Manual" +.TH "bombadillo" 1 "27 OCT 2019" "" "General Operation Manual" .SH NAME \fBbombadillo \fP- a non-web client .SH SYNOPSIS @@ -28,7 +28,7 @@ Gopher is the default protocol for \fBbombadillo\fP. Any textual item types will .TP .B gemini -Gemini is supported, but as a new protocol with an incomplete specification, features may change over time. At present Bombadillo supports TLS with a trust on first use certificate pinning system (similar to SSH). Client certificates are also supported via option configuration. Gemini maps and other text types are rendered in the client and non-text types will trigger a prompt to the user to download or open in an appropriate program. +Gemini is supported, but as a new protocol with an incomplete specification, features may change over time. At present Bombadillo supports TLS with a trust on first use certificate pinning system (similar to SSH). Client certificates are also supported via option configuration. Gemini maps and other text types are rendered in the client and non-text types will be downloaded. .TP .B finger diff --git a/client.go b/client.go index f106183..452dad1 100644 --- a/client.go +++ b/client.go @@ -936,62 +936,14 @@ func (c *client) handleGemini(u Url) { c.SetHeaderUrl() c.Draw() } else { - c.SetMessage("The file is non-text: (o)pen or (w)rite to disk", false) + c.SetMessage("The file is non-text: writing to disk...", false) c.DrawMessage() - var ch rune - for { - ch = cui.Getch() - if ch == 'o' || ch == 'w' { - break - } - } - switch ch { - case 'o': - mime := fmt.Sprintf("%s/%s", capsule.MimeMaj, capsule.MimeMin) - var term bool - if c.Options["terminalonly"] == "true" { - term = true - } else { - term = false - } - mcEntry, err := mc.FindMatch(mime, "view", term) - if err != nil { - c.SetMessage(err.Error(), true) - c.DrawMessage() - return - } - file, err := ioutil.TempFile("/tmp/", "bombadillo-*.tmp") - if err != nil { - c.SetMessage("Unable to create temporary file for opening, aborting file open", true) - c.DrawMessage() - return - } - // defer os.Remove(file.Name()) - file.Write([]byte(capsule.Content)) - com, e := mcEntry.Command(file.Name()) - if e != nil { - c.SetMessage(e.Error(), true) - c.DrawMessage() - return - } - com.Stdin = os.Stdin - com.Stdout = os.Stdout - com.Stderr = os.Stderr - if c.Options["terminalonly"] == "true" { - cui.Clear("screen") - } - com.Run() - c.SetMessage("File opened by an appropriate program", true) - c.DrawMessage() - c.Draw() - case 'w': - nameSplit := strings.Split(u.Resource, "/") - filename := nameSplit[len(nameSplit)-1] - c.saveFileFromData(capsule.Content, filename) - } + nameSplit := strings.Split(u.Resource, "/") + filename := nameSplit[len(nameSplit)-1] + c.saveFileFromData(capsule.Content, filename) } case 3: - c.SetMessage("[3] Redirect. Follow redirect? y or any other key for no", false) + c.SetMessage(fmt.Sprintf("Follow redirect (y/n): %s?", capsule.Content), false) c.DrawMessage() ch := cui.Getch() if ch == 'y' || ch == 'Y' { diff --git a/main.go b/main.go index 6108ebc..2e1860e 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,6 @@ import ( "tildegit.org/sloum/bombadillo/config" "tildegit.org/sloum/bombadillo/cui" _ "tildegit.org/sloum/bombadillo/gemini" - "tildegit.org/sloum/mailcap" ) var version string @@ -39,7 +38,6 @@ var build string var bombadillo *client var helplocation string = "gopher://bombadillo.colorfield.space:70/1/user-guide.map" var settings config.Config -var mc *mailcap.Mailcap func saveConfig() error { var opts strings.Builder @@ -194,10 +192,6 @@ func main() { } args := flag.Args() - // Build the mailcap db - // So that we can open files from gemini - mc = mailcap.NewMailcap() - cui.InitTerm() defer cui.Exit() err := initClient() From 73c77fd625f29da4e6327bf2a648b2ca51f1e000 Mon Sep 17 00:00:00 2001 From: asdf Date: Mon, 28 Oct 2019 11:10:03 +1100 Subject: [PATCH 8/9] Corrected spelling error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb09b0f..141e1a5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If building from source, you will need to have [Go](https://golang.org/) version #### Optional -[Lynx](https://lynx.invisible-island.net/), the text based web browser, can be used as a parsing engine for http/https. This is a totally optional item and Lynx is in no way required in order to compile or run Bombadillo. Having it available on the system can help create a richer experience by allowing users to navigate directly to web content in Bombadillo. Many users may wish to avoid this entirely,a nd the default configuration does not have this behavior turned on. To turn it on from within Bombadillo enter the command `set lynxmode true`. +[Lynx](https://lynx.invisible-island.net/), the text based web browser, can be used as a parsing engine for http/https. This is a totally optional item and Lynx is in no way required in order to compile or run Bombadillo. Having it available on the system can help create a richer experience by allowing users to navigate directly to web content in Bombadillo. Many users may wish to avoid this entirely, and the default configuration does not have this behavior turned on. To turn it on from within Bombadillo enter the command `set lynxmode true`. ### Installing From b441ac4624133dd9ccfc0a6b94ea5f64b3da73ff Mon Sep 17 00:00:00 2001 From: asdf Date: Mon, 28 Oct 2019 11:21:07 +1100 Subject: [PATCH 9/9] go.mod, go.sum mailcap cleanup, version decrement --- go.mod | 4 +--- go.sum | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 go.sum diff --git a/go.mod b/go.mod index 609acc7..acb6d6f 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ module tildegit.org/sloum/bombadillo -go 1.12 - -require tildegit.org/sloum/mailcap v0.0.0-20190706214029-b787a49e9db2 +go 1.11 diff --git a/go.sum b/go.sum deleted file mode 100644 index 60768f8..0000000 --- a/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -tildegit.org/sloum/mailcap v0.0.0-20190706214029-b787a49e9db2 h1:tAPIFBpXwOq1Ytxk8aGsDjCutnwUC01BVkK77QS1bdU= -tildegit.org/sloum/mailcap v0.0.0-20190706214029-b787a49e9db2/go.mod h1:m4etAw9DbXsdanDUNS8oERhL+7y4II82ZLHWzw2yibg=