gopher

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2020 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultTimeout = 10 * time.Second

Variables

This section is empty.

Functions

func IsWellKnownDummyHostname

func IsWellKnownDummyHostname(s string) bool

Types

type BinaryResponse

type BinaryResponse struct {
	// contains filtered or unexported fields
}

func NewBinaryResponse

func NewBinaryResponse(u URL, rdr io.ReadCloser) *BinaryResponse

func (*BinaryResponse) Class

func (br *BinaryResponse) Class() ResponseClass

func (*BinaryResponse) Close

func (br *BinaryResponse) Close() error

func (*BinaryResponse) Read

func (br *BinaryResponse) Read(b []byte) (n int, err error)

func (*BinaryResponse) URL

func (br *BinaryResponse) URL() URL

type Cap

type Cap interface{}

type CapComment

type CapComment struct {
	Comment string
	Line    int
}

type CapKeyValue

type CapKeyValue struct {
	Key   string
	Value string
	Line  int
}

type Caps

type Caps struct {
	Version int
	Expiry  time.Duration
	Entries []Cap
}

type Client

type Client struct {
	Timeout     time.Duration
	BinaryTypes [256]bool
}

func (*Client) Binary

func (c *Client) Binary(ctx context.Context, u URL) (*BinaryResponse, error)

func (*Client) Dir

func (c *Client) Dir(ctx context.Context, u URL) (*DirResponse, error)

func (*Client) Fetch

func (c *Client) Fetch(ctx context.Context, u URL) (Response, error)
func (c *Client) interceptError(ctx context.Context, tcp *net.TCPConn) (rdr io.ReadCloser, rsErr *ErrorResponse, err error) {
    first := make([]byte, 2048)

    // XXX: this is difficult... we can only try to Read() once because subsequent calls
    // to Read() may block, which we can't allow because we have no way to know when
    // to unblock. Unfortunately, the server could be written to write bytes 1 at a
    // time (it probably won't, but if it does, we're stuffed), or to write the whole
    // response in one hit. The network could chop the reads up to the MTU size. All
    // sorts of stuff.
    //
    // So detecting the error can only be done with the result of the first call to Read.
    n, err := tcp.Read(first)
    if err != nil {
        tcp.Close()
        return nil, nil, err
    }

    first = first[:n]

    // Step 0: Empty file == error?

    // Step 1: Try to detect error responses that start with '--':
    // https://tools.ietf.org/html/draft-matavka-gopher-ii-02#section-9

    // Step 2: Try to detect error responses that are a single directory entry of type
    // '3', which may be preceded and/or followed by a list of 'i' lines.

    // Step 3: Iterate well known server responses for errors
    // - 3Happy helping ☃ here: Sorry, your selector does not start with / or contains '..'. That's illegal here.	Err	localhost	70
    // - An error occurred: Resource not found.
    // - File: '...' not found.
    // - Error: resource caps.txt does not exist on ...
    // - Error: 404 Not Found
    // - Error: File or directory not found!

    return tcp, nil, nil
}

func (*Client) Search

func (c *Client) Search(ctx context.Context, u URL) (*DirResponse, error)

func (*Client) Text

func (c *Client) Text(ctx context.Context, u URL) (*TextResponse, error)

func (*Client) UUEncoded

func (c *Client) UUEncoded(ctx context.Context, u URL) (*UUEncodedResponse, error)

type DirResponse

type DirResponse struct {
	// contains filtered or unexported fields
}

func NewDirResponse

func NewDirResponse(u URL, rdr io.ReadCloser) *DirResponse

func (*DirResponse) Class

func (br *DirResponse) Class() ResponseClass

func (*DirResponse) Close

func (br *DirResponse) Close() error

func (*DirResponse) Next

func (br *DirResponse) Next(dir *Dirent) bool

func (*DirResponse) URL

func (br *DirResponse) URL() URL

type Dirent

type Dirent struct {
	ItemType ItemType
	Display  string
	URL      URL
	Plus     bool

	Valid bool
	Error string
	Raw   string
}

type ItemType

type ItemType byte
const (
	File       ItemType = '0'
	Dir        ItemType = '1'
	CSOServer  ItemType = '2' // https://en.wikipedia.org/wiki/CCSO_Nameserver
	ItemError  ItemType = '3'
	BinHex     ItemType = '4' // Ancient pre OS X Mac format
	DOSArchive ItemType = '5' // Client must read until the TCP connection closes. Beware.
	UUEncoded  ItemType = '6'
	Search     ItemType = '7'
	Telnet     ItemType = '8' // Connect to given host at given port. The name to login as at this host is in the selector string.
	Binary     ItemType = '9' // Client must read until the TCP connection closes. Beware.

	// The information applies to a duplicated server. The information contained within is
	// a duplicate of the primary server. The primary server is defined as the last
	// DirEntity that is has a non-plus "Type" field. The client should use the
	// transaction as defined by the primary server Type field.
	Duplicate ItemType = '+'

	GIF   ItemType = 'g'
	Image ItemType = 'I' // Item is some kind of image file. Client gets to decide.

	// The information applies to a tn3270 based telnet session. Connect to given host at
	// given port. The name to login as at this host is in the selector string.
	TN3270 ItemType = 'T'

	// Non-canonical:
	Doc   = 'D'
	HTML  = 'h'
	Info  = 'i'
	Sound = 's'
)

func (ItemType) CanFetch

func (i ItemType) CanFetch() bool

func (ItemType) IsBinary

func (i ItemType) IsBinary() bool

func (ItemType) IsSearch

func (i ItemType) IsSearch() bool

func (ItemType) String

func (i ItemType) String() string

type Response

type Response interface {
	URL() URL
	Class() ResponseClass
	Close() error
}

type ResponseClass

type ResponseClass int
const (
	BinaryClass ResponseClass = 1
	DirClass    ResponseClass = 2
	TextClass   ResponseClass = 3
	ErrorClass  ResponseClass = 4
)

type TextResponse

type TextResponse struct {
	// contains filtered or unexported fields
}

func NewTextResponse

func NewTextResponse(u URL, rdr io.ReadCloser) *TextResponse

func (*TextResponse) Class

func (br *TextResponse) Class() ResponseClass

func (*TextResponse) Close

func (br *TextResponse) Close() error

func (*TextResponse) Read

func (br *TextResponse) Read(b []byte) (n int, err error)

func (*TextResponse) URL

func (br *TextResponse) URL() URL

type URL

type URL struct {
	Hostname string
	Port     int
	Root     bool
	ItemType ItemType
	Selector string
	Search   string
	Plus     string
}

func ParseURL

func ParseURL(s string) (gu URL, err error)

func (URL) Host

func (u URL) Host() string

func (URL) Parts

func (u URL) Parts() map[string]interface{}

func (URL) Query

func (u URL) Query() string

func (URL) String

func (u URL) String() string

type URLVar

type URLVar URL

func (*URLVar) Set

func (uv *URLVar) Set(s string) (err error)

func (URLVar) String

func (uv URLVar) String() string

func (URLVar) URL

func (uv URLVar) URL() URL

type UUEncodedResponse

type UUEncodedResponse struct {
	// contains filtered or unexported fields
}

func NewUUEncodedResponse

func NewUUEncodedResponse(u URL, rdr io.ReadCloser) *UUEncodedResponse

func (*UUEncodedResponse) Class

func (br *UUEncodedResponse) Class() ResponseClass

func (*UUEncodedResponse) Close

func (br *UUEncodedResponse) Close() error

func (*UUEncodedResponse) File

func (br *UUEncodedResponse) File() (string, bool)

func (*UUEncodedResponse) Mode

func (br *UUEncodedResponse) Mode() (os.FileMode, bool)

func (*UUEncodedResponse) Read

func (br *UUEncodedResponse) Read(b []byte) (n int, err error)

func (*UUEncodedResponse) URL

func (br *UUEncodedResponse) URL() URL

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL