Begun work on gopher module
This commit is contained in:
parent
a6d1f45be8
commit
b7d7d021ed
121
gopher/gopher.go
121
gopher/gopher.go
|
@ -5,7 +5,7 @@ package gopher
|
|||
|
||||
import (
|
||||
"errors"
|
||||
// "fmt"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
|
@ -21,17 +21,21 @@ import (
|
|||
var types = map[string]string{
|
||||
"0": "TXT",
|
||||
"1": "MAP",
|
||||
"h": "HTM",
|
||||
"3": "ERR",
|
||||
"4": "BIN",
|
||||
"5": "DOS",
|
||||
"s": "SND",
|
||||
"g": "GIF",
|
||||
"I": "IMG",
|
||||
"9": "BIN",
|
||||
"7": "FTS",
|
||||
"6": "UUE",
|
||||
"7": "FTS",
|
||||
"8": "TEL",
|
||||
"9": "BIN",
|
||||
"g": "GIF",
|
||||
"G": "GEM",
|
||||
"h": "HTM",
|
||||
"I": "IMG",
|
||||
"p": "PNG",
|
||||
"s": "SND",
|
||||
"S": "SSH",
|
||||
"T": "TEL",
|
||||
}
|
||||
|
||||
//------------------------------------------------\\
|
||||
|
@ -43,25 +47,22 @@ var types = map[string]string{
|
|||
// available to use directly, but in most implementations
|
||||
// using the "Visit" receiver of the History struct will
|
||||
// be better.
|
||||
func Retrieve(u Url) ([]byte, error) {
|
||||
func Retrieve(host, port, resource string) ([]byte, error) {
|
||||
nullRes := make([]byte, 0)
|
||||
timeOut := time.Duration(5) * time.Second
|
||||
|
||||
if u.Host == "" || u.Port == "" {
|
||||
if host == "" || port == "" {
|
||||
return nullRes, errors.New("Incomplete request url")
|
||||
}
|
||||
|
||||
addr := u.Host + ":" + u.Port
|
||||
addr := host + ":" + port
|
||||
|
||||
conn, err := net.DialTimeout("tcp", addr, timeOut)
|
||||
if err != nil {
|
||||
return nullRes, err
|
||||
}
|
||||
|
||||
send := u.Resource + "\n"
|
||||
if u.Scheme == "http" || u.Scheme == "https" {
|
||||
send = u.Gophertype
|
||||
}
|
||||
send := resource + "\n"
|
||||
|
||||
_, err = conn.Write([]byte(send))
|
||||
if err != nil {
|
||||
|
@ -73,43 +74,27 @@ func Retrieve(u Url) ([]byte, error) {
|
|||
return nullRes, err
|
||||
}
|
||||
|
||||
return result, err
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Visit is a high level combination of a few different
|
||||
// types that makes it easy to create a Url, make a request
|
||||
// to that Url, and add the response and Url to a View.
|
||||
// Returns a copy of the view and an error (or nil).
|
||||
func Visit(addr, openhttp string) (View, error) {
|
||||
u, err := MakeUrl(addr)
|
||||
// Visit handles the making of the request, parsing of maps, and returning
|
||||
// the correct information to the client
|
||||
func Visit(gophertype, host, port, resource string) (string, []string, error) {
|
||||
resp, err := Retrieve(host, port, resource)
|
||||
text := string(resp)
|
||||
links := []string{}
|
||||
|
||||
if err != nil {
|
||||
return View{}, err
|
||||
return "", []string{}, err
|
||||
} else if IsDownloadOnly(gophertype) {
|
||||
return text, []string{}, nil
|
||||
}
|
||||
|
||||
// if u.Gophertype == "h" {
|
||||
// if res, tf := isWebLink(u.Resource); tf && strings.ToUpper(openhttp) == "TRUE" {
|
||||
// err := OpenBrowser(res)
|
||||
// if err != nil {
|
||||
// return View{}, err
|
||||
// }
|
||||
//
|
||||
// return View{}, fmt.Errorf("")
|
||||
// }
|
||||
// }
|
||||
|
||||
text, err := Retrieve(u)
|
||||
if err != nil {
|
||||
return View{}, err
|
||||
if gophertype == "1" {
|
||||
text, links = parseMap(text)
|
||||
}
|
||||
|
||||
var pageContent []string
|
||||
if u.IsBinary && u.Gophertype != "7" {
|
||||
pageContent = []string{string(text)}
|
||||
} else {
|
||||
pageContent = strings.Split(string(text), "\n")
|
||||
}
|
||||
|
||||
return MakeView(u, pageContent), nil
|
||||
return text, links, nil
|
||||
}
|
||||
|
||||
func getType(t string) string {
|
||||
|
@ -127,3 +112,51 @@ func isWebLink(resource string) (string, bool) {
|
|||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// TODO Make sure when parsing maps that links have the correct
|
||||
// protocol rather than 'gopher', where applicable (telnet, gemini, etc).
|
||||
func parseMap(text string) (string, []string) {
|
||||
splitContent := strings.Split(text, "\n")
|
||||
links := make([]string, 0, 10)
|
||||
|
||||
for i, e := range splitContent {
|
||||
e = strings.Trim(e, "\r\n")
|
||||
if e == "." {
|
||||
splitContent[i] = ""
|
||||
continue
|
||||
}
|
||||
|
||||
line := strings.Split(e, "\t")
|
||||
var title string
|
||||
// TODO REFACTOR LINE == HERE
|
||||
// - - - - - - - - - - - - - -
|
||||
if len(line[0]) > 1 {
|
||||
title = line[0][1:]
|
||||
} else {
|
||||
title = ""
|
||||
}
|
||||
if len(line) > 1 && len(line[0]) > 0 && string(line[0][0]) == "i" {
|
||||
splitContent[i] = " " + string(title)
|
||||
} else if len(line) >= 4 {
|
||||
fulllink := fmt.Sprintf("%s://%s:%s/%s%s", "protocol" ,line[2], line[3], string(line[0][0]), line[1])
|
||||
links = append(links, fulllink)
|
||||
linktext := fmt.Sprintf("(%s) %2d %s", getType(string(line[0][0])), len(links), title)
|
||||
splitContent[i] = linktext
|
||||
}
|
||||
}
|
||||
return "", links
|
||||
}
|
||||
|
||||
// Returns false for all text formats (including html
|
||||
// even though it may link out. Things like telnet
|
||||
// should never make it into the retrieve call for
|
||||
// this module, having been handled in the client
|
||||
// based on their protocol.
|
||||
func IsDownloadOnly(gophertype string) bool {
|
||||
switch gophertype {
|
||||
case "0", "1", "3", "7", "h":
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue