2019-02-25 01:43:10 +00:00
|
|
|
package main
|
2019-10-10 06:05:50 +00:00
|
|
|
|
2019-10-23 05:13:08 +00:00
|
|
|
// Bombadillo is an internet client for the terminal of unix or
|
2019-10-23 05:02:32 +00:00
|
|
|
// unix-like systems.
|
2019-09-23 15:49:33 +00:00
|
|
|
//
|
|
|
|
// Copyright (C) 2019 Brian Evans
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2019-02-25 01:43:10 +00:00
|
|
|
|
|
|
|
import (
|
2019-09-20 16:18:16 +00:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2019-03-17 16:58:39 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2019-10-10 06:05:50 +00:00
|
|
|
"os/signal"
|
2019-10-27 12:24:52 +00:00
|
|
|
"path/filepath"
|
2019-04-28 19:46:47 +00:00
|
|
|
"strings"
|
2019-10-10 06:05:50 +00:00
|
|
|
"syscall"
|
2019-05-01 22:25:45 +00:00
|
|
|
|
2019-04-28 19:46:47 +00:00
|
|
|
"tildegit.org/sloum/bombadillo/config"
|
|
|
|
"tildegit.org/sloum/bombadillo/cui"
|
2019-10-10 06:05:50 +00:00
|
|
|
_ "tildegit.org/sloum/bombadillo/gemini"
|
2019-02-25 01:43:10 +00:00
|
|
|
)
|
|
|
|
|
2019-10-14 23:29:40 +00:00
|
|
|
var version string
|
|
|
|
var build string
|
2019-09-20 16:18:16 +00:00
|
|
|
|
2019-09-10 02:35:16 +00:00
|
|
|
var bombadillo *client
|
2019-10-15 03:27:40 +00:00
|
|
|
var helplocation string = "gopher://bombadillo.colorfield.space:70/1/user-guide.map"
|
2019-03-17 16:58:39 +00:00
|
|
|
var settings config.Config
|
2019-09-10 02:35:16 +00:00
|
|
|
|
2019-05-01 00:18:28 +00:00
|
|
|
func saveConfig() error {
|
2019-09-16 04:24:45 +00:00
|
|
|
var opts strings.Builder
|
2019-09-10 02:35:16 +00:00
|
|
|
bkmrks := bombadillo.BookMarks.IniDump()
|
2019-09-27 05:08:57 +00:00
|
|
|
certs := bombadillo.Certs.IniDump()
|
2019-09-16 04:24:45 +00:00
|
|
|
|
|
|
|
opts.WriteString("\n[SETTINGS]\n")
|
2019-09-10 02:35:16 +00:00
|
|
|
for k, v := range bombadillo.Options {
|
2019-09-21 21:12:18 +00:00
|
|
|
if k == "theme" && v != "normal" && v != "inverse" {
|
|
|
|
v = "normal"
|
|
|
|
bombadillo.Options["theme"] = "normal"
|
|
|
|
}
|
2019-09-16 04:24:45 +00:00
|
|
|
opts.WriteString(k)
|
|
|
|
opts.WriteRune('=')
|
|
|
|
opts.WriteString(v)
|
|
|
|
opts.WriteRune('\n')
|
2019-03-17 16:58:39 +00:00
|
|
|
}
|
2019-05-01 00:18:28 +00:00
|
|
|
|
2019-09-27 05:08:57 +00:00
|
|
|
opts.WriteString(bkmrks)
|
|
|
|
|
|
|
|
opts.WriteString(certs)
|
|
|
|
|
2019-10-27 12:24:52 +00:00
|
|
|
return ioutil.WriteFile(filepath.Join(bombadillo.Options["configlocation"], ".bombadillo.ini"), []byte(opts.String()), 0644)
|
2019-03-17 16:58:39 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 04:18:46 +00:00
|
|
|
func validateOpt(opt, val string) bool {
|
|
|
|
var validOpts = map[string][]string{
|
2019-12-07 06:19:25 +00:00
|
|
|
"webmode": []string{"none", "gui", "lynx", "w3m", "elinks"},
|
|
|
|
"theme": []string{"normal", "inverse"},
|
|
|
|
"defaultscheme": []string{"gopher", "gemini", "http", "https"},
|
2019-09-24 04:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
opt = strings.ToLower(opt)
|
|
|
|
val = strings.ToLower(val)
|
|
|
|
|
|
|
|
if _, ok := validOpts[opt]; ok {
|
|
|
|
for _, item := range validOpts[opt] {
|
|
|
|
if item == val {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2019-11-10 19:35:52 +00:00
|
|
|
return true
|
2019-09-24 04:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func lowerCaseOpt(opt, val string) string {
|
|
|
|
switch opt {
|
2019-12-07 06:19:25 +00:00
|
|
|
case "webmode", "theme", "defaultscheme":
|
2019-09-24 04:18:46 +00:00
|
|
|
return strings.ToLower(val)
|
|
|
|
default:
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:55:07 +00:00
|
|
|
func loadConfig() {
|
2019-12-04 08:18:01 +00:00
|
|
|
err := os.MkdirAll(bombadillo.Options["configlocation"], 0755)
|
2019-12-04 03:58:18 +00:00
|
|
|
if err != nil {
|
2019-12-07 00:14:16 +00:00
|
|
|
exitMsg := fmt.Sprintf("Error creating 'configlocation' directory: %s", err.Error())
|
2019-12-06 06:01:22 +00:00
|
|
|
cui.Exit(3, exitMsg)
|
2019-12-04 03:58:18 +00:00
|
|
|
}
|
|
|
|
|
2019-12-04 08:18:01 +00:00
|
|
|
fp := filepath.Join(bombadillo.Options["configlocation"], ".bombadillo.ini")
|
2019-12-04 03:58:18 +00:00
|
|
|
file, err := os.Open(fp)
|
2019-03-19 03:11:02 +00:00
|
|
|
if err != nil {
|
2019-05-01 00:18:28 +00:00
|
|
|
err = saveConfig()
|
|
|
|
if err != nil {
|
2019-12-07 00:14:16 +00:00
|
|
|
exitMsg := fmt.Sprintf("Error writing config file during bootup: %s", err.Error())
|
2019-12-06 06:01:22 +00:00
|
|
|
cui.Exit(4, exitMsg)
|
2019-05-01 00:18:28 +00:00
|
|
|
}
|
2019-03-19 03:11:02 +00:00
|
|
|
}
|
2019-05-01 00:18:28 +00:00
|
|
|
|
2019-03-17 16:58:39 +00:00
|
|
|
confparser := config.NewParser(file)
|
|
|
|
settings, _ = confparser.Parse()
|
2019-11-11 00:18:27 +00:00
|
|
|
_ = file.Close()
|
2019-03-17 16:58:39 +00:00
|
|
|
for _, v := range settings.Settings {
|
|
|
|
lowerkey := strings.ToLower(v.Key)
|
2019-09-10 02:35:16 +00:00
|
|
|
if lowerkey == "configlocation" {
|
2019-10-14 23:29:40 +00:00
|
|
|
// The config defaults to the home folder.
|
|
|
|
// Users cannot really edit this value. But
|
2019-10-22 03:45:39 +00:00
|
|
|
// a compile time override is available.
|
2019-09-10 02:35:16 +00:00
|
|
|
// It is still stored in the ini and as a part
|
|
|
|
// of the options map.
|
|
|
|
continue
|
2019-03-17 16:58:39 +00:00
|
|
|
}
|
2019-05-01 00:18:28 +00:00
|
|
|
|
2019-09-10 02:35:16 +00:00
|
|
|
if _, ok := bombadillo.Options[lowerkey]; ok {
|
2019-10-10 06:05:50 +00:00
|
|
|
if validateOpt(lowerkey, v.Value) {
|
2019-09-24 04:18:46 +00:00
|
|
|
bombadillo.Options[lowerkey] = v.Value
|
|
|
|
} else {
|
|
|
|
bombadillo.Options[lowerkey] = defaultOptions[lowerkey]
|
2019-09-21 21:12:18 +00:00
|
|
|
}
|
2019-04-11 05:29:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 03:57:48 +00:00
|
|
|
for i, v := range settings.Bookmarks.Titles {
|
2019-11-11 00:18:27 +00:00
|
|
|
_, _ = bombadillo.BookMarks.Add([]string{v, settings.Bookmarks.Links[i]})
|
2019-09-13 03:57:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-27 05:08:57 +00:00
|
|
|
for _, v := range settings.Certs {
|
|
|
|
bombadillo.Certs.Add(v.Key, v.Value)
|
|
|
|
}
|
2019-03-19 03:11:02 +00:00
|
|
|
}
|
|
|
|
|
2019-12-06 05:55:07 +00:00
|
|
|
func initClient() {
|
2019-09-10 02:35:16 +00:00
|
|
|
bombadillo = MakeClient(" ((( Bombadillo ))) ")
|
2019-12-06 05:55:07 +00:00
|
|
|
loadConfig()
|
2019-10-02 04:38:13 +00:00
|
|
|
if bombadillo.Options["tlscertificate"] != "" && bombadillo.Options["tlskey"] != "" {
|
|
|
|
bombadillo.Certs.LoadCertificate(bombadillo.Options["tlscertificate"], bombadillo.Options["tlskey"])
|
|
|
|
}
|
2019-05-28 21:23:35 +00:00
|
|
|
}
|
|
|
|
|
2019-10-24 02:25:31 +00:00
|
|
|
// In the event of specific signals, ensure the display is shown correctly.
|
|
|
|
// Accepts a signal, blocking until it is received. Once not blocked, corrects
|
2019-10-24 02:42:38 +00:00
|
|
|
// terminal display settings as appropriate for that signal. Loops
|
|
|
|
// indefinitely, does not return.
|
2019-10-24 02:25:31 +00:00
|
|
|
func handleSignals(c <-chan os.Signal) {
|
2019-10-11 01:04:19 +00:00
|
|
|
for {
|
2019-10-24 02:42:38 +00:00
|
|
|
switch <-c {
|
|
|
|
case syscall.SIGTSTP:
|
|
|
|
cui.CleanupTerm()
|
2019-11-11 00:18:27 +00:00
|
|
|
_ = syscall.Kill(syscall.Getpid(), syscall.SIGSTOP)
|
2019-10-24 02:42:38 +00:00
|
|
|
case syscall.SIGCONT:
|
|
|
|
cui.InitTerm()
|
|
|
|
bombadillo.Draw()
|
|
|
|
case syscall.SIGINT:
|
2019-12-06 06:01:22 +00:00
|
|
|
cui.Exit(130, "")
|
2019-10-24 02:42:38 +00:00
|
|
|
}
|
2019-10-11 01:04:19 +00:00
|
|
|
}
|
2019-10-10 06:05:50 +00:00
|
|
|
}
|
|
|
|
|
2019-10-22 03:45:39 +00:00
|
|
|
//printHelp produces a nice display message when the --help flag is used
|
|
|
|
func printHelp() {
|
2019-11-14 04:01:27 +00:00
|
|
|
art := `Bombadillo - a non-web browser
|
2019-10-22 03:45:39 +00:00
|
|
|
|
2019-10-22 04:00:01 +00:00
|
|
|
Syntax: bombadillo [url]
|
|
|
|
bombadillo [options...]
|
2019-10-22 03:45:39 +00:00
|
|
|
|
2019-10-22 04:00:01 +00:00
|
|
|
Examples: bombadillo gopher://bombadillo.colorfield.space
|
|
|
|
bombadillo -v
|
2019-10-22 03:45:39 +00:00
|
|
|
|
|
|
|
Options:
|
|
|
|
`
|
2019-11-11 00:18:27 +00:00
|
|
|
_, _ = fmt.Fprint(os.Stdout, art)
|
2019-10-22 03:45:39 +00:00
|
|
|
flag.PrintDefaults()
|
|
|
|
}
|
|
|
|
|
2019-03-17 16:58:39 +00:00
|
|
|
func main() {
|
2019-10-22 04:07:37 +00:00
|
|
|
getVersion := flag.Bool("v", false, "Display version information and exit")
|
2019-10-22 03:45:39 +00:00
|
|
|
flag.Usage = printHelp
|
2019-09-20 16:18:16 +00:00
|
|
|
flag.Parse()
|
|
|
|
if *getVersion {
|
2019-10-22 03:45:39 +00:00
|
|
|
fmt.Printf("Bombadillo %s - build %s\n", version, build)
|
2019-09-20 16:18:16 +00:00
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
args := flag.Args()
|
|
|
|
|
2019-10-24 02:25:31 +00:00
|
|
|
cui.InitTerm()
|
2019-12-06 06:01:22 +00:00
|
|
|
defer cui.Exit(0, "")
|
2019-12-06 05:55:07 +00:00
|
|
|
initClient()
|
2019-05-01 00:18:28 +00:00
|
|
|
|
2019-10-24 02:25:31 +00:00
|
|
|
// watch for signals, send them to be handled
|
2019-10-11 01:04:19 +00:00
|
|
|
c := make(chan os.Signal, 1)
|
2019-10-24 02:25:31 +00:00
|
|
|
signal.Notify(c, syscall.SIGTSTP, syscall.SIGCONT, syscall.SIGINT)
|
|
|
|
go handleSignals(c)
|
2019-10-11 01:04:19 +00:00
|
|
|
|
2019-09-10 02:35:16 +00:00
|
|
|
// Start polling for terminal size changes
|
|
|
|
go bombadillo.GetSize()
|
2019-02-25 01:43:10 +00:00
|
|
|
|
2019-09-20 16:18:16 +00:00
|
|
|
if len(args) > 0 {
|
2019-09-10 02:35:16 +00:00
|
|
|
// If a url was passed, move it down the line
|
|
|
|
// Goroutine so keypresses can be made during
|
|
|
|
// page load
|
2019-09-20 16:18:16 +00:00
|
|
|
bombadillo.Visit(args[0])
|
2019-05-09 00:16:59 +00:00
|
|
|
} else {
|
2019-09-10 02:35:16 +00:00
|
|
|
// Otherwise, load the homeurl
|
|
|
|
// Goroutine so keypresses can be made during
|
|
|
|
// page load
|
2019-09-14 22:45:23 +00:00
|
|
|
bombadillo.Visit(bombadillo.Options["homeurl"])
|
2019-05-09 00:16:59 +00:00
|
|
|
}
|
2019-03-17 16:58:39 +00:00
|
|
|
|
2019-09-10 02:35:16 +00:00
|
|
|
// Loop indefinitely on user input
|
2019-05-09 00:16:59 +00:00
|
|
|
for {
|
2019-09-10 02:35:16 +00:00
|
|
|
bombadillo.TakeControlInput()
|
2019-02-25 01:43:10 +00:00
|
|
|
}
|
|
|
|
}
|