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"
2020-05-09 18:04:06 +00:00
"strconv"
2019-04-28 19:46:47 +00:00
"strings"
2019-10-10 06:05:50 +00:00
"syscall"
2020-05-09 18:04:06 +00:00
"time"
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"
2020-05-18 04:36:49 +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-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" } ,
2019-12-11 05:56:41 +00:00
"theme" : [ ] string { "normal" , "inverse" , "color" } ,
2019-12-07 06:19:25 +00:00
"defaultscheme" : [ ] string { "gopher" , "gemini" , "http" , "https" } ,
2020-02-14 05:26:23 +00:00
"showimages" : [ ] string { "true" , "false" } ,
2020-05-18 04:36:49 +00:00
"geminiblocks" : [ ] string { "block" , "neither" , "alt" , "both" } ,
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 {
2020-05-18 04:36:49 +00:00
case "webmode" , "theme" , "defaultscheme" , "showimages" , "geminiblocks" :
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-12-11 05:56:41 +00:00
// Read only
2019-09-10 02:35:16 +00:00
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
2020-05-18 04:36:49 +00:00
if lowerkey == "geminiblocks" {
gemini . BlockBehavior = v . Value
}
2019-09-24 04:18:46 +00:00
} 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 {
2020-05-09 18:04:06 +00:00
// 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 )
2019-09-27 05:08:57 +00:00
}
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-12-19 03:57:40 +00:00
Syntax : bombadillo [ options ] [ url ]
2019-10-22 03:45:39 +00:00
2019-10-22 04:00:01 +00:00
Examples : bombadillo gopher : //bombadillo.colorfield.space
2019-12-19 03:57:40 +00:00
bombadillo - t
2019-10-22 04:00:01 +00:00
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-12-19 03:57:40 +00:00
addTitleToXWindow := flag . Bool ( "t" , false , "Set the window title to 'Bombadillo'. Can be used in a GUI environment, however not all terminals support this feature." )
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-17 03:40:52 +00:00
if * addTitleToXWindow {
fmt . Print ( "\033[22;0t" ) // Store window title on terminal stack
fmt . Print ( "\033]0;Bombadillo\007" ) // Update window title
}
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
}
}