You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
package gopher
|
|
|
|
import (
|
|
"gophi/core"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// Gophermap line formatting constants
|
|
const (
|
|
maxSelectorLen = 255
|
|
nullHost = "null.host"
|
|
nullPort = "0"
|
|
errorSelector = "/error_selector_length"
|
|
)
|
|
|
|
var (
|
|
// pageWidth is the maximum set page width of a gophermap document to render to
|
|
pageWidth int
|
|
|
|
// footer holds the formatted footer text (if supplied), and gophermap last-line
|
|
footer []byte
|
|
)
|
|
|
|
// formatName formats a gopher line name string
|
|
func formatName(name string) string {
|
|
if len(name) > pageWidth {
|
|
return name[:pageWidth-4] + "...\t"
|
|
}
|
|
return name + "\t"
|
|
}
|
|
|
|
// formatSelector formats a gopher line selector string
|
|
func formatSelector(selector string) string {
|
|
if len(selector) > maxSelectorLen {
|
|
return errorSelector + "\t"
|
|
}
|
|
return selector + "\t"
|
|
}
|
|
|
|
// formatHostPort formats a gopher line host + port
|
|
func formatHostPort(host, port string) string {
|
|
return host + "\t" + port
|
|
}
|
|
|
|
// replacePlacementStrs replaces any placement strings found in the line (e.g $hostname, $port)
|
|
func replacePlacementStrs(line string) string {
|
|
split := strings.Split(line, "\t")
|
|
|
|
// Either invalid line, or information line without host + port
|
|
if len(split) != 4 {
|
|
return line
|
|
}
|
|
|
|
// Return recombined (and replaced! string)
|
|
return split[0] + "\t" +
|
|
split[1] + "\t" +
|
|
strings.Replace(split[2], "$host", core.Hostname, 1) + "\t" +
|
|
strings.Replace(split[3], "$port", core.FwdPort, 1)
|
|
}
|
|
|
|
// buildLine builds a gopher line string
|
|
func buildLine(t ItemType, name, selector, host, port string) []byte {
|
|
return []byte(string(t) + formatName(name) + formatSelector(selector) + formatHostPort(host, port) + "\r\n")
|
|
}
|
|
|
|
// buildInfoLine builds a gopher info line string
|
|
func buildInfoLine(line string) []byte {
|
|
return []byte(string(typeInfo) + formatName(line) + formatHostPort(nullHost, nullPort) + "\r\n")
|
|
}
|
|
|
|
// buildErrorLine builds a gopher error line string
|
|
func buildErrorLine(selector string) []byte {
|
|
return []byte(string(typeError) + selector + "\r\n" + ".\r\n")
|
|
}
|
|
|
|
// appendFileListing formats and appends a new file entry as part of a directory listing
|
|
func appendFileListing(b []byte, file os.FileInfo, p *core.Path) []byte {
|
|
switch {
|
|
case file.Mode()&os.ModeDir != 0:
|
|
return append(b, buildLine(typeDirectory, file.Name(), p.Selector(), core.Hostname, core.FwdPort)...)
|
|
case file.Mode()&os.ModeType == 0:
|
|
t := getItemType(file.Name())
|
|
return append(b, buildLine(t, file.Name(), p.Selector(), core.Hostname, core.FwdPort)...)
|
|
default:
|
|
return b
|
|
}
|
|
}
|
|
|
|
// buildFooter formats a raw gopher footer ready to attach to end of gophermaps (including DOS line-end)
|
|
func buildFooter(raw string) []byte {
|
|
ret := make([]byte, 0)
|
|
|
|
if raw != "" {
|
|
ret = append(ret, buildInfoLine(footerLineSeparator())...)
|
|
|
|
for _, line := range strings.Split(raw, "\n") {
|
|
ret = append(ret, buildInfoLine(line)...)
|
|
}
|
|
}
|
|
|
|
return append(ret, []byte(".\r\n")...)
|
|
}
|
|
|
|
// footerLineSeparator is an internal function that generates a footer line separator string
|
|
func footerLineSeparator() string {
|
|
ret := ""
|
|
for i := 0; i < pageWidth; i++ {
|
|
ret += "_"
|
|
}
|
|
return ret
|
|
}
|