This repository has been archived on 2021-02-14. You can view files and clone it, but cannot push or open issues or pull requests.
kobo-gemini/main.go

174 lines
3.7 KiB
Go
Raw Normal View History

2021-01-27 11:02:15 +00:00
package main
import (
2021-01-27 17:59:42 +00:00
// "github.com/fogleman/gg"
2021-01-27 11:02:15 +00:00
"github.com/shermp/go-fbink-v2/gofbink"
"github.com/shermp/go-kobo-input/koboin"
2021-01-27 17:59:42 +00:00
"image"
2021-01-27 11:02:15 +00:00
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/tofu"
"crypto/x509"
// "time"
// "bytes"
"errors"
"net/url"
"bufio"
"io/ioutil"
"fmt"
"time"
2021-01-27 17:59:42 +00:00
"os"
"log"
2021-01-27 14:46:31 +00:00
"bytes"
2021-01-27 11:02:15 +00:00
)
var (
hosts tofu.KnownHosts
hostsfile *tofu.HostWriter
scanner *bufio.Scanner
)
var height int = 1080
var width int = 1440 // TODO get from device instead of hardcoding
2021-01-27 17:59:42 +00:00
// drawOSK renders the onscreen keyboard to an image.
func drawOSK(keymap []string) *image.RGBA {
var im image.RGBA
return &im
}
2021-01-27 14:46:31 +00:00
func trustCertificate(hostname string, cert *x509.Certificate) error {
host := tofu.NewHost(hostname, cert.Raw, cert.NotAfter)
2021-01-27 11:02:15 +00:00
knownHost, ok := hosts.Lookup(hostname)
if ok && time.Now().Before(knownHost.Expires) {
// Check fingerprint
if bytes.Equal(knownHost.Fingerprint, host.Fingerprint) {
return nil
}
return errors.New("error: fingerprint does not match!")
2021-01-27 14:46:31 +00:00
} else { // Expired cert or new host: TOFU
hosts.Add(host)
hostsfile.WriteHost(host)
return nil
}
return errors.New("error: fingerprint does not match!")
2021-01-27 11:02:15 +00:00
}
func do(req *gemini.Request, via []*gemini.Request) (*gemini.Response, error) {
client := gemini.Client{
TrustCertificate: trustCertificate,
}
resp, err := client.Do(req)
if err != nil {
return resp, err
}
switch resp.Status.Class() {
case gemini.StatusClassInput: // TODO implement input
/* input, ok := getInput(resp.Meta, resp.Status == gemini.StatusSensitiveInput)
if !ok {
break
}
req.URL.ForceQuery = true
req.URL.RawQuery = gemini.QueryEscape(input)
return do(req, via) */
case gemini.StatusClassRedirect:
via = append(via, req)
if len(via) > 5 {
return resp, errors.New("too many redirects")
}
target, err := url.Parse(resp.Meta)
if err != nil {
return resp, err
}
target = req.URL.ResolveReference(target)
redirect := *req
redirect.URL = target
return do(&redirect, via)
}
return resp, err
}
func main() {
// Framebuffer setup
fbinkOpts := gofbink.FBInkConfig{}
rOpts := gofbink.RestrictedConfig{}
fb := gofbink.New(&fbinkOpts, &rOpts)
fb.Open()
defer fb.Close()
fb.Init(&fbinkOpts)
fb.ClearScreen(&fbinkOpts)
fb.Refresh(0,0,0,0, gofbink.DitherPassthrough, &fbinkOpts)
// Touchscreen setup
touchPath := "/dev/input/event1"
t := koboin.New(touchPath, height, width)
if t == nil {
return
}
defer t.Close()
2021-01-27 17:59:42 +00:00
// Logging setup
var logFile, err= os.Create("/mnt/onboard/gemini.log")
var logger *log.Logger = log.New(logFile, "gemini", log.LstdFlags )
2021-01-27 11:02:15 +00:00
2021-01-27 14:46:31 +00:00
path := "/mnt/onboard/.adds/gemini/known-hosts" // TODO don't hardcode
2021-01-27 17:59:42 +00:00
if _, err := os.Stat(path); os.IsNotExist(err) {
os.Create(path)
fb.Println("Created hosts file")
}
// Load known hosts file
err = hosts.Load(path)
2021-01-27 11:02:15 +00:00
if err != nil {
fb.Println(err)
2021-01-27 17:59:42 +00:00
logger.Fatal(err)
2021-01-27 11:02:15 +00:00
}
hostsfile, err = tofu.NewHostsFile(path)
if err != nil {
fb.Println(err)
2021-01-27 17:59:42 +00:00
logger.Fatal(err)
2021-01-27 11:02:15 +00:00
}
2021-01-27 14:46:31 +00:00
url := "gemini://gemini.circumlunar.space"
2021-01-27 11:02:15 +00:00
req, err := gemini.NewRequest(url)
if err != nil {
fb.Println(err)
2021-01-27 17:59:42 +00:00
logger.Fatal(err)
2021-01-27 11:02:15 +00:00
}
resp, err := do(req, nil)
if err != nil {
fb.Println(err)
2021-01-27 17:59:42 +00:00
logger.Fatal(err)
2021-01-27 11:02:15 +00:00
}
defer resp.Body.Close()
// Handle response
if resp.Status.Class() == gemini.StatusClassSuccess {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fb.Println(err)
2021-01-27 17:59:42 +00:00
logger.Fatal(err)
2021-01-27 11:02:15 +00:00
}
fb.Println(string(body))
} else {
fb.Println(fmt.Sprintf("%d %s\n", resp.Status, resp.Meta))
}
for {
x, y, err := t.GetInput()
if err != nil {
continue
}
if x < 100 && y < 100 {
2021-01-27 17:59:42 +00:00
fb.Println("Exiting...")
2021-01-27 11:02:15 +00:00
break
}
}
2021-01-27 14:46:31 +00:00
hostsfile.Close()
2021-01-27 17:59:42 +00:00
}