diff options
Diffstat (limited to 'vendor/github.com')
25 files changed, 1141 insertions, 367 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/conn.go b/vendor/github.com/Rhymen/go-whatsapp/conn.go index 59445591..4b28cbe1 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/conn.go +++ b/vendor/github.com/Rhymen/go-whatsapp/conn.go @@ -116,31 +116,59 @@ Creates a new connection with a given timeout. The websocket connection to the W The goroutine for handling incoming messages is started */ func NewConn(timeout time.Duration) (*Conn, error) { - wac := &Conn{ - handler: make([]Handler, 0), - msgCount: 0, - msgTimeout: timeout, - Store: newStore(), - - longClientName: "github.com/rhymen/go-whatsapp", - shortClientName: "go-whatsapp", - clientVersion: "0.1.0", - } - return wac, wac.connect() + return NewConnWithOptions(&Options{ + Timeout: timeout, + }) } // NewConnWithProxy Create a new connect with a given timeout and a http proxy. func NewConnWithProxy(timeout time.Duration, proxy func(*http.Request) (*url.URL, error)) (*Conn, error) { + return NewConnWithOptions(&Options{ + Timeout: timeout, + Proxy: proxy, + }) +} + +// NewConnWithOptions Create a new connect with a given options. +type Options struct { + Proxy func(*http.Request) (*url.URL, error) + Timeout time.Duration + Handler []Handler + ShortClientName string + LongClientName string + ClientVersion string + Store *Store +} +func NewConnWithOptions(opt *Options) (*Conn, error) { + if opt == nil { + return nil, ErrOptionsNotProvided + } wac := &Conn{ handler: make([]Handler, 0), msgCount: 0, - msgTimeout: timeout, + msgTimeout: opt.Timeout, Store: newStore(), - - longClientName: "github.com/rhymen/go-whatsapp", + longClientName: "github.com/Rhymen/go-whatsapp", shortClientName: "go-whatsapp", clientVersion: "0.1.0", - Proxy: proxy, + } + if opt.Handler != nil { + wac.handler = opt.Handler + } + if opt.Store != nil { + wac.Store = opt.Store + } + if opt.Proxy != nil { + wac.Proxy = opt.Proxy + } + if len(opt.ShortClientName) != 0 { + wac.shortClientName = opt.ShortClientName + } + if len(opt.LongClientName) != 0 { + wac.longClientName = opt.LongClientName + } + if len(opt.ClientVersion) != 0 { + wac.clientVersion = opt.ClientVersion } return wac, wac.connect() } @@ -249,10 +277,26 @@ func (wac *Conn) keepAlive(minIntervalMs int, maxIntervalMs int) { } } +// IsConnected returns whether the server connection is established or not +func (wac *Conn) IsConnected() bool { + return wac.connected +} + +// GetConnected returns whether the server connection is established or not +// +// Deprecated: function name is not go idiomatic, use IsConnected instead func (wac *Conn) GetConnected() bool { - return wac.connected + return wac.connected +} + +//IsLoggedIn returns whether the you are logged in or not +func (wac *Conn) IsLoggedIn() bool { + return wac.loggedIn } +// GetLoggedIn returns whether the you are logged in or not +// +// Deprecated: function name is not go idiomatic, use IsLoggedIn instead. func (wac *Conn) GetLoggedIn() bool { - return wac.loggedIn + return wac.loggedIn } diff --git a/vendor/github.com/Rhymen/go-whatsapp/errors.go b/vendor/github.com/Rhymen/go-whatsapp/errors.go index be78ea0f..022f977a 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/errors.go +++ b/vendor/github.com/Rhymen/go-whatsapp/errors.go @@ -22,6 +22,8 @@ var ( ErrMediaDownloadFailedWith404 = errors.New("download failed with status code 404") ErrMediaDownloadFailedWith410 = errors.New("download failed with status code 410") ErrInvalidWebsocket = errors.New("invalid websocket") + ErrMessageTypeNotImplemented = errors.New("message type not implemented") + ErrOptionsNotProvided = errors.New("new conn options not provided") ) type ErrConnectionFailed struct { diff --git a/vendor/github.com/Rhymen/go-whatsapp/go.sum b/vendor/github.com/Rhymen/go-whatsapp/go.sum index b724cb47..ee786406 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/go.sum +++ b/vendor/github.com/Rhymen/go-whatsapp/go.sum @@ -32,5 +32,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= diff --git a/vendor/github.com/Rhymen/go-whatsapp/media.go b/vendor/github.com/Rhymen/go-whatsapp/media.go index 225eac8e..0fcacd2e 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/media.go +++ b/vendor/github.com/Rhymen/go-whatsapp/media.go @@ -38,7 +38,7 @@ func Download(url string, mediaKey []byte, appInfo MediaType, fileLength int) ([ return nil, err } if len(data) != fileLength { - return nil, fmt.Errorf("file length does not match") + return nil, fmt.Errorf("file length does not match. Expected: %v, got: %v", fileLength, len(data)) } return data, nil } @@ -93,21 +93,21 @@ func downloadMedia(url string) (file []byte, mac []byte, err error) { return data[:n-10], data[n-10 : n], nil } - -type MediaConn struct { - Status int `json:"status"` - MediaConn struct { - Auth string `json:"auth"` - TTL int `json:"ttl"` - Hosts []struct { - Hostname string `json:"hostname"` - IPs []interface{} `json:"ips"` - } `json:"hosts"` - } `json:"media_conn"` +type MediaConn struct { + Status int `json:"status"` + MediaConn struct { + Auth string `json:"auth"` + TTL int `json:"ttl"` + Hosts []struct { + Hostname string `json:"hostname"` + IPs []struct { + IP4 string `json:"ip4"` + IP6 string `json:"ip6"` + } `json:"ips"` + } `json:"hosts"` + } `json:"media_conn"` } - - func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { queryReq := []interface{}{"query", "mediaConn"} ch, err := wac.writeJson(queryReq) @@ -131,7 +131,7 @@ func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { var host string for _, h := range resp.MediaConn.Hosts { - if h.Hostname!="" { + if h.Hostname != "" { host = h.Hostname break } @@ -143,10 +143,10 @@ func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { } var mediaTypeMap = map[MediaType]string{ - MediaImage: "/mms/image", - MediaVideo: "/mms/video", + MediaImage: "/mms/image", + MediaVideo: "/mms/video", MediaDocument: "/mms/document", - MediaAudio: "/mms/audio", + MediaAudio: "/mms/audio", } func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) { diff --git a/vendor/github.com/Rhymen/go-whatsapp/message.go b/vendor/github.com/Rhymen/go-whatsapp/message.go index 15797cb4..34fc02af 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/message.go +++ b/vendor/github.com/Rhymen/go-whatsapp/message.go @@ -238,7 +238,7 @@ func getMessageInfo(msg *proto.WebMessageInfo) MessageInfo { return MessageInfo{ Id: msg.GetKey().GetId(), RemoteJid: msg.GetKey().GetRemoteJid(), - SenderJid: msg.GetKey().GetParticipant(), + SenderJid: msg.GetParticipant(), FromMe: msg.GetKey().GetFromMe(), Timestamp: msg.GetMessageTimestamp(), Status: MessageStatus(msg.GetStatus()), @@ -838,19 +838,16 @@ func ParseProtoMessage(msg *proto.WebMessageInfo) interface{} { default: //cannot match message - + return ErrMessageTypeNotImplemented } - - return nil } - /* BatteryMessage represents a battery level and charging state. */ type BatteryMessage struct { - Plugged bool - Powersave bool + Plugged bool + Powersave bool Percentage int } @@ -859,8 +856,8 @@ func getBatteryMessage(msg map[string]string) BatteryMessage { powersave, _ := strconv.ParseBool(msg["powersave"]) percentage, _ := strconv.Atoi(msg["value"]) batteryMessage := BatteryMessage{ - Plugged: plugged, - Powersave: powersave, + Plugged: plugged, + Powersave: powersave, Percentage: percentage, } @@ -869,7 +866,7 @@ func getBatteryMessage(msg map[string]string) BatteryMessage { func getNewContact(msg map[string]string) Contact { contact := Contact{ - Jid: msg["jid"], + Jid: msg["jid"], Notify: msg["notify"], } diff --git a/vendor/github.com/Rhymen/go-whatsapp/read.go b/vendor/github.com/Rhymen/go-whatsapp/read.go index c35f7f0e..81e16619 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/read.go +++ b/vendor/github.com/Rhymen/go-whatsapp/read.go @@ -62,6 +62,10 @@ func (wac *Conn) processReadData(msgType int, msg []byte) error { data[0] = "!" } + if len(data) == 2 && len(data[1]) == 0 { + return nil + } + if len(data) != 2 || len(data[1]) == 0 { return ErrInvalidWsData } diff --git a/vendor/github.com/gomarkdown/markdown/README.md b/vendor/github.com/gomarkdown/markdown/README.md index 5488280c..095db307 100644 --- a/vendor/github.com/gomarkdown/markdown/README.md +++ b/vendor/github.com/gomarkdown/markdown/README.md @@ -6,11 +6,7 @@ Package `github.com/gomarkdown/markdown` is a very fast Go library for parsing [ It's fast and supports common extensions. -## Installation - - go get -u github.com/gomarkdown/markdown - -API Docs: +## API Docs: - https://godoc.org/github.com/gomarkdown/markdown : top level package - https://godoc.org/github.com/gomarkdown/markdown/ast : defines abstract syntax tree of parsed markdown document diff --git a/vendor/github.com/gomarkdown/markdown/ast/node.go b/vendor/github.com/gomarkdown/markdown/ast/node.go index e6fcba9a..9d2422af 100644 --- a/vendor/github.com/gomarkdown/markdown/ast/node.go +++ b/vendor/github.com/gomarkdown/markdown/ast/node.go @@ -250,11 +250,12 @@ type Del struct { type Link struct { Container - Destination []byte // Destination is what goes into a href - Title []byte // Title is the tooltip thing that goes in a title attribute - NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote - Footnote Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. - DeferredID []byte // If a deferred link this holds the original ID. + Destination []byte // Destination is what goes into a href + Title []byte // Title is the tooltip thing that goes in a title attribute + NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote + Footnote Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. + DeferredID []byte // If a deferred link this holds the original ID. + AdditionalAttributes []string // Defines additional attributes to use during rendering. } // CrossReference is a reference node. diff --git a/vendor/github.com/gomarkdown/markdown/html/callouts.go b/vendor/github.com/gomarkdown/markdown/html/callouts.go deleted file mode 100644 index e377af22..00000000 --- a/vendor/github.com/gomarkdown/markdown/html/callouts.go +++ /dev/null @@ -1,42 +0,0 @@ -package html - -import ( - "bytes" - "io" - - "github.com/gomarkdown/markdown/ast" - "github.com/gomarkdown/markdown/parser" -) - -// EscapeHTMLCallouts writes html-escaped d to w. It escapes &, <, > and " characters, *but* -// expands callouts <<N>> with the callout HTML, i.e. by calling r.callout() with a newly created -// ast.Callout node. -func (r *Renderer) EscapeHTMLCallouts(w io.Writer, d []byte) { - ld := len(d) -Parse: - for i := 0; i < ld; i++ { - for _, comment := range r.opts.Comments { - if !bytes.HasPrefix(d[i:], comment) { - break - } - - lc := len(comment) - if i+lc < ld { - if id, consumed := parser.IsCallout(d[i+lc:]); consumed > 0 { - // We have seen a callout - callout := &ast.Callout{ID: id} - r.callout(w, callout) - i += consumed + lc - 1 - continue Parse - } - } - } - - escSeq := Escaper[d[i]] - if escSeq != nil { - w.Write(escSeq) - } else { - w.Write([]byte{d[i]}) - } - } -} diff --git a/vendor/github.com/gomarkdown/markdown/html/esc.go b/vendor/github.com/gomarkdown/markdown/html/esc.go deleted file mode 100644 index 89ec9a27..00000000 --- a/vendor/github.com/gomarkdown/markdown/html/esc.go +++ /dev/null @@ -1,50 +0,0 @@ -package html - -import ( - "html" - "io" -) - -var Escaper = [256][]byte{ - '&': []byte("&"), - '<': []byte("<"), - '>': []byte(">"), - '"': []byte("""), -} - -// EscapeHTML writes html-escaped d to w. It escapes &, <, > and " characters. -func EscapeHTML(w io.Writer, d []byte) { - var start, end int - n := len(d) - for end < n { - escSeq := Escaper[d[end]] - if escSeq != nil { - w.Write(d[start:end]) - w.Write(escSeq) - start = end + 1 - } - end++ - } - if start < n && end <= n { - w.Write(d[start:end]) - } -} - -func escLink(w io.Writer, text []byte) { - unesc := html.UnescapeString(string(text)) - EscapeHTML(w, []byte(unesc)) -} - -// Escape writes the text to w, but skips the escape character. -func Escape(w io.Writer, text []byte) { - esc := false - for i := 0; i < len(text); i++ { - if text[i] == '\\' { - esc = !esc - } - if esc && text[i] == '\\' { - continue - } - w.Write([]byte{text[i]}) - } -} diff --git a/vendor/github.com/gomarkdown/markdown/html/renderer.go b/vendor/github.com/gomarkdown/markdown/html/renderer.go index 01e0deec..6c56ac12 100644 --- a/vendor/github.com/gomarkdown/markdown/html/renderer.go +++ b/vendor/github.com/gomarkdown/markdown/html/renderer.go @@ -3,6 +3,7 @@ package html import ( "bytes" "fmt" + "html" "io" "regexp" "sort" @@ -10,6 +11,7 @@ import ( "strings" "github.com/gomarkdown/markdown/ast" + "github.com/gomarkdown/markdown/parser" ) // Flags control optional behavior of HTML renderer. @@ -125,13 +127,60 @@ type Renderer struct { headingIDs map[string]int lastOutputLen int - disableTags int + + // if > 0, will strip html tags in Out and Outs + DisableTags int sr *SPRenderer documentMatter ast.DocumentMatters // keep track of front/main/back matter. } +// Escaper defines how to escape HTML special characters +var Escaper = [256][]byte{ + '&': []byte("&"), + '<': []byte("<"), + '>': []byte(">"), + '"': []byte("""), +} + +// EscapeHTML writes html-escaped d to w. It escapes &, <, > and " characters. +func EscapeHTML(w io.Writer, d []byte) { + var start, end int + n := len(d) + for end < n { + escSeq := Escaper[d[end]] + if escSeq != nil { + w.Write(d[start:end]) + w.Write(escSeq) + start = end + 1 + } + end++ + } + if start < n && end <= n { + w.Write(d[start:end]) + } +} + +func escLink(w io.Writer, text []byte) { + unesc := html.UnescapeString(string(text)) + EscapeHTML(w, []byte(unesc)) +} + +// Escape writes the text to w, but skips the escape character. +func Escape(w io.Writer, text []byte) { + esc := false + for i := 0; i < len(text); i++ { + if text[i] == '\\' { + esc = !esc + } + if esc && text[i] == '\\' { + continue + } + w.Write([]byte{text[i]}) + } +} + // NewRenderer creates and configures an Renderer object, which // satisfies the Renderer interface. func NewRenderer(opts RendererOptions) *Renderer { @@ -384,25 +433,28 @@ func skipParagraphTags(para *ast.Paragraph) bool { return tightOrTerm } -func (r *Renderer) out(w io.Writer, d []byte) { +// Out is a helper to write data to writer +func (r *Renderer) Out(w io.Writer, d []byte) { r.lastOutputLen = len(d) - if r.disableTags > 0 { + if r.DisableTags > 0 { d = htmlTagRe.ReplaceAll(d, []byte{}) } w.Write(d) } -func (r *Renderer) outs(w io.Writer, s string) { +// Outs is a helper to write data to writer +func (r *Renderer) Outs(w io.Writer, s string) { r.lastOutputLen = len(s) - if r.disableTags > 0 { + if r.DisableTags > 0 { s = htmlTagRe.ReplaceAllString(s, "") } io.WriteString(w, s) } -func (r *Renderer) cr(w io.Writer) { +// CR writes a new line +func (r *Renderer) CR(w io.Writer) { if r.lastOutputLen > 0 { - r.outs(w, "\n") + r.Outs(w, "\n") } } @@ -426,11 +478,12 @@ func headingCloseTagFromLevel(level int) string { } func (r *Renderer) outHRTag(w io.Writer, attrs []string) { - hr := tagWithAttributes("<hr", attrs) - r.outOneOf(w, r.opts.Flags&UseXHTML == 0, hr, "<hr />") + hr := TagWithAttributes("<hr", attrs) + r.OutOneOf(w, r.opts.Flags&UseXHTML == 0, hr, "<hr />") } -func (r *Renderer) text(w io.Writer, text *ast.Text) { +// Text writes ast.Text node +func (r *Renderer) Text(w io.Writer, text *ast.Text) { if r.opts.Flags&Smartypants != 0 { var tmp bytes.Buffer EscapeHTML(&tmp, text.Literal) @@ -445,41 +498,46 @@ func (r *Renderer) text(w io.Writer, text *ast.Text) { } } -func (r *Renderer) hardBreak(w io.Writer, node *ast.Hardbreak) { - r.outOneOf(w, r.opts.Flags&UseXHTML == 0, "<br>", "<br />") - r.cr(w) +// HardBreak writes ast.Hardbreak node +func (r *Renderer) HardBreak(w io.Writer, node *ast.Hardbreak) { + r.OutOneOf(w, r.opts.Flags&UseXHTML == 0, "<br>", "<br />") + r.CR(w) } -func (r *Renderer) nonBlockingSpace(w io.Writer, node *ast.NonBlockingSpace) { - r.outs(w, " ") +// NonBlockingSpace writes ast.NonBlockingSpace node +func (r *Renderer) NonBlockingSpace(w io.Writer, node *ast.NonBlockingSpace) { + r.Outs(w, " ") } -func (r *Renderer) outOneOf(w io.Writer, outFirst bool, first string, second string) { +// OutOneOf writes first or second depending on outFirst +func (r *Renderer) OutOneOf(w io.Writer, outFirst bool, first string, second string) { if outFirst { - r.outs(w, first) + r.Outs(w, first) } else { - r.outs(w, second) + r.Outs(w, second) } } -func (r *Renderer) outOneOfCr(w io.Writer, outFirst bool, first string, second string) { +// OutOneOfCr writes CR + first or second + CR depending on outFirst +func (r *Renderer) OutOneOfCr(w io.Writer, outFirst bool, first string, second string) { if outFirst { - r.cr(w) - r.outs(w, first) + r.CR(w) + r.Outs(w, first) } else { - r.outs(w, second) - r.cr(w) + r.Outs(w, second) + r.CR(w) } } -func (r *Renderer) htmlSpan(w io.Writer, span *ast.HTMLSpan) { +// HTMLSpan writes ast.HTMLSpan node +func (r *Renderer) HTMLSpan(w io.Writer, span *ast.HTMLSpan) { if r.opts.Flags&SkipHTML == 0 { - r.out(w, span.Literal) + r.Out(w, span.Literal) } } func (r *Renderer) linkEnter(w io.Writer, link *ast.Link) { - var attrs []string + attrs := link.AdditionalAttributes dest := link.Destination dest = r.addAbsPrefix(dest) var hrefBuf bytes.Buffer @@ -488,7 +546,7 @@ func (r *Renderer) linkEnter(w io.Writer, link *ast.Link) { hrefBuf.WriteByte('"') attrs = append(attrs, hrefBuf.String()) if link.NoteID != 0 { - r.outs(w, footnoteRef(r.opts.FootnoteAnchorPrefix, link)) + r.Outs(w, footnoteRef(r.opts.FootnoteAnchorPrefix, link)) return } @@ -505,14 +563,15 @@ func (r *Renderer) linkEnter(w io.Writer, link *ast.Link) { func (r *Renderer) linkExit(w io.Writer, link *ast.Link) { if link.NoteID == 0 { - r.outs(w, "</a>") + r.Outs(w, "</a>") } } -func (r *Renderer) link(w io.Writer, link *ast.Link, entering bool) { +// Link writes ast.Link node +func (r *Renderer) Link(w io.Writer, link *ast.Link, entering bool) { // mark it but don't link it if it is not a safe link: no smartypants if needSkipLink(r.opts.Flags, link.Destination) { - r.outOneOf(w, entering, "<tt>", "</tt>") + r.OutOneOf(w, entering, "<tt>", "</tt>") return } @@ -526,26 +585,35 @@ func (r *Renderer) link(w io.Writer, link *ast.Link, entering bool) { func (r *Renderer) imageEnter(w io.Writer, image *ast.Image) { dest := image.Destination dest = r.addAbsPrefix(dest) - if r.disableTags == 0 { + if r.DisableTags == 0 { //if options.safe && potentiallyUnsafe(dest) { //out(w, `<img src="" alt="`) //} else { - r.outs(w, `<img src="`) + r.Outs(w, `<img src="`) escLink(w, dest) - r.outs(w, `" alt="`) + r.Outs(w, `" alt="`) //} } - r.disableTags++ + r.DisableTags++ } func (r *Renderer) imageExit(w io.Writer, image *ast.Image) { - r.disableTags-- - if r.disableTags == 0 { + r.DisableTags-- + if r.DisableTags == 0 { if image.Title != nil { - r.outs(w, `" title="`) + r.Outs(w, `" title="`) EscapeHTML(w, image.Title) } - r.outs(w, `" />`) + r.Outs(w, `" />`) + } +} + +// Image writes ast.Image node +func (r *Renderer) Image(w io.Writer, node *ast.Image, entering bool) { + if entering { + r.imageEnter(w, node) + } else { + r.imageExit(w, node) } } @@ -556,33 +624,34 @@ func (r *Renderer) paragraphEnter(w io.Writer, para *ast.Paragraph) { if prev != nil { switch prev.(type) { case *ast.HTMLBlock, *ast.List, *ast.Paragraph, *ast.Heading, *ast.CaptionFigure, *ast.CodeBlock, *ast.BlockQuote, *ast.Aside, *ast.HorizontalRule: - r.cr(w) + r.CR(w) } } if prev == nil { _, isParentBlockQuote := para.Parent.(*ast.BlockQuote) if isParentBlockQuote { - r.cr(w) + r.CR(w) } _, isParentAside := para.Parent.(*ast.Aside) if isParentAside { - r.cr(w) + r.CR(w) } } - tag := tagWithAttributes("<p", BlockAttrs(para)) - r.outs(w, tag) + tag := TagWithAttributes("<p", BlockAttrs(para)) + r.Outs(w, tag) } func (r *Renderer) paragraphExit(w io.Writer, para *ast.Paragraph) { - r.outs(w, "</p>") + r.Outs(w, "</p>") if !(isListItem(para.Parent) && ast.GetNextNode(para) == nil) { - r.cr(w) + r.CR(w) } } -func (r *Renderer) paragraph(w io.Writer, para *ast.Paragraph, entering bool) { +// Paragraph writes ast.Paragraph node +func (r *Renderer) Paragraph(w io.Writer, para *ast.Paragraph, entering bool) { if skipParagraphTags(para) { return } @@ -592,27 +661,22 @@ func (r *Renderer) paragraph(w io.Writer, para *ast.Paragraph, entering bool) { r.paragraphExit(w, para) } } -func (r *Renderer) image(w io.Writer, node *ast.Image, entering bool) { - if entering { - r.imageEnter(w, node) - } else { - r.imageExit(w, node) - } -} -func (r *Renderer) code(w io.Writer, node *ast.Code) { - r.outs(w, "<code>") +// Code writes ast.Code node +func (r *Renderer) Code(w io.Writer, node *ast.Code) { + r.Outs(w, "<code>") EscapeHTML(w, node.Literal) - r.outs(w, "</code>") + r.Outs(w, "</code>") } -func (r *Renderer) htmlBlock(w io.Writer, node *ast.HTMLBlock) { +// HTMLBlock write ast.HTMLBlock node +func (r *Renderer) HTMLBlock(w io.Writer, node *ast.HTMLBlock) { if r.opts.Flags&SkipHTML != 0 { return } - r.cr(w) - r.out(w, node.Literal) - r.cr(w) + r.CR(w) + r.Out(w, node.Literal) + r.CR(w) } func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) { @@ -644,18 +708,19 @@ func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) { attrs = append(attrs, attrID) } attrs = append(attrs, BlockAttrs(nodeData)...) - r.cr(w) + r.CR(w) r.outTag(w, headingOpenTagFromLevel(nodeData.Level), attrs) } func (r *Renderer) headingExit(w io.Writer, heading *ast.Heading) { - r.outs(w, headingCloseTagFromLevel(heading.Level)) + r.Outs(w, headingCloseTagFromLevel(heading.Level)) if !(isListItem(heading.Parent) && ast.GetNextNode(heading) == nil) { - r.cr(w) + r.CR(w) } } -func (r *Renderer) heading(w io.Writer, node *ast.Heading, entering bool) { +// Heading writes ast.Heading node +func (r *Renderer) Heading(w io.Writer, node *ast.Heading, entering bool) { if entering { r.headingEnter(w, node) } else { @@ -663,10 +728,11 @@ func (r *Renderer) heading(w io.Writer, node *ast.Heading, entering bool) { } } -func (r *Renderer) horizontalRule(w io.Writer, node *ast.HorizontalRule) { - r.cr(w) +// HorizontalRule writes ast.HorizontalRule node +func (r *Renderer) HorizontalRule(w io.Writer, node *ast.HorizontalRule) { + r.CR(w) r.outHRTag(w, BlockAttrs(node)) - r.cr(w) + r.CR(w) } func (r *Renderer) listEnter(w io.Writer, nodeData *ast.List) { @@ -674,17 +740,17 @@ func (r *Renderer) listEnter(w io.Writer, nodeData *ast.List) { var attrs []string if nodeData.IsFootnotesList { - r.outs(w, "\n<div class=\"footnotes\">\n\n") + r.Outs(w, "\n<div class=\"footnotes\">\n\n") if r.opts.Flags&FootnoteNoHRTag == 0 { r.outHRTag(w, nil) - r.cr(w) + r.CR(w) } } - r.cr(w) + r.CR(w) if isListItem(nodeData.Parent) { grand := nodeData.Parent.GetParent() if isListTight(grand) { - r.cr(w) + r.CR(w) } } @@ -700,7 +766,7 @@ func (r *Renderer) listEnter(w io.Writer, nodeData *ast.List) { } attrs = append(attrs, BlockAttrs(nodeData)...) r.outTag(w, openTag, attrs) - r.cr(w) + r.CR(w) } func (r *Renderer) listExit(w io.Writer, list *ast.List) { @@ -711,7 +777,7 @@ func (r *Renderer) listExit(w io.Writer, list *ast.List) { if list.ListFlags&ast.ListTypeDefinition != 0 { closeTag = "</dl>" } - r.outs(w, closeTag) + r.Outs(w, closeTag) //cr(w) //if node.parent.Type != Item { @@ -721,18 +787,19 @@ func (r *Renderer) listExit(w io.Writer, list *ast.List) { switch parent.(type) { case *ast.ListItem: if ast.GetNextNode(list) != nil { - r.cr(w) + r.CR(w) } case *ast.Document, *ast.BlockQuote, *ast.Aside: - r.cr(w) + r.CR(w) } if list.IsFootnotesList { - r.outs(w, "\n</div>\n") + r.Outs(w, "\n</div>\n") } } -func (r *Renderer) list(w io.Writer, list *ast.List, entering bool) { +// List writes ast.List node +func (r *Renderer) List(w io.Writer, list *ast.List, entering bool) { if entering { r.listEnter(w, list) } else { @@ -742,11 +809,11 @@ func (r *Renderer) list(w io.Writer, list *ast.List, entering bool) { func (r *Renderer) listItemEnter(w io.Writer, listItem *ast.ListItem) { if listItemOpenCR(listItem) { - r.cr(w) + r.CR(w) } if listItem.RefLink != nil { slug := slugify(listItem.RefLink) - r.outs(w, footnoteItem(r.opts.FootnoteAnchorPrefix, slug)) + r.Outs(w, footnoteItem(r.opts.FootnoteAnchorPrefix, slug)) return } @@ -757,7 +824,7 @@ func (r *Renderer) listItemEnter(w io.Writer, listItem *ast.ListItem) { if listItem.ListFlags&ast.ListTypeTerm != 0 { openTag = "<dt>" } - r.outs(w, openTag) + r.Outs(w, openTag) } func (r *Renderer) listItemExit(w io.Writer, listItem *ast.ListItem) { @@ -766,7 +833,7 @@ func (r *Renderer) listItemExit(w io.Writer, listItem *ast.ListItem) { prefix := r.opts.FootnoteAnchorPrefix link := r.opts.FootnoteReturnLinkContents s := footnoteReturnLink(prefix, link, slug) - r.outs(w, s) + r.Outs(w, s) } closeTag := "</li>" @@ -776,11 +843,12 @@ func (r *Renderer) listItemExit(w io.Writer, listItem *ast.ListItem) { if listItem.ListFlags&ast.ListTypeTerm != 0 { closeTag = "</dt>" } - r.outs(w, closeTag) - r.cr(w) + r.Outs(w, closeTag) + r.CR(w) } -func (r *Renderer) listItem(w io.Writer, listItem *ast.ListItem, entering bool) { +// ListItem writes ast.ListItem node +func (r *Renderer) ListItem(w io.Writer, listItem *ast.ListItem, entering bool) { if entering { r.listItemEnter(w, listItem) } else { @@ -788,38 +856,74 @@ func (r *Renderer) listItem(w io.Writer, listItem *ast.ListItem, entering bool) } } -func (r *Renderer) codeBlock(w io.Writer, codeBlock *ast.CodeBlock) { +// EscapeHTMLCallouts writes html-escaped d to w. It escapes &, <, > and " characters, *but* +// expands callouts <<N>> with the callout HTML, i.e. by calling r.callout() with a newly created +// ast.Callout node. +func (r *Renderer) EscapeHTMLCallouts(w io.Writer, d []byte) { + ld := len(d) +Parse: + for i := 0; i < ld; i++ { + for _, comment := range r.opts.Comments { + if !bytes.HasPrefix(d[i:], comment) { + break + } + + lc := len(comment) + if i+lc < ld { + if id, consumed := parser.IsCallout(d[i+lc:]); consumed > 0 { + // We have seen a callout + callout := &ast.Callout{ID: id} + r.Callout(w, callout) + i += consumed + lc - 1 + continue Parse + } + } + } + + escSeq := Escaper[d[i]] + if escSeq != nil { + w.Write(escSeq) + } else { + w.Write([]byte{d[i]}) + } + } +} + +// CodeBlock writes ast.CodeBlock node +func (r *Renderer) CodeBlock(w io.Writer, codeBlock *ast.CodeBlock) { var attrs []string // TODO(miek): this can add multiple class= attribute, they should be coalesced into one. // This is probably true for some other elements as well attrs = appendLanguageAttr(attrs, codeBlock.Info) attrs = append(attrs, BlockAttrs(codeBlock)...) - r.cr(w) + r.CR(w) - r.outs(w, "<pre>") - code := tagWithAttributes("<code", attrs) - r.outs(w, code) + r.Outs(w, "<pre>") + code := TagWithAttributes("<code", attrs) + r.Outs(w, code) if r.opts.Comments != nil { r.EscapeHTMLCallouts(w, codeBlock.Literal) } else { EscapeHTML(w, codeBlock.Literal) } - r.outs(w, "</code>") - r.outs(w, "</pre>") + r.Outs(w, "</code>") + r.Outs(w, "</pre>") if !isListItem(codeBlock.Parent) { - r.cr(w) + r.CR(w) } } -func (r *Renderer) caption(w io.Writer, caption *ast.Caption, entering bool) { +// Caption writes ast.Caption node +func (r *Renderer) Caption(w io.Writer, caption *ast.Caption, entering bool) { if entering { - r.outs(w, "<figcaption>") + r.Outs(w, "<figcaption>") return } - r.outs(w, "</figcaption>") + r.Outs(w, "</figcaption>") } -func (r *Renderer) captionFigure(w io.Writer, figure *ast.CaptionFigure, entering bool) { +// CaptionFigure writes ast.CaptionFigure node +func (r *Renderer) CaptionFigure(w io.Writer, figure *ast.CaptionFigure, entering bool) { // TODO(miek): copy more generic ways of mmark over to here. fig := "<figure" if figure.HeadingID != "" { @@ -827,13 +931,14 @@ func (r *Renderer) captionFigure(w io.Writer, figure *ast.CaptionFigure, enterin } else { fig += ">" } - r.outOneOf(w, entering, fig, "\n</figure>\n") + r.OutOneOf(w, entering, fig, "\n</figure>\n") } -func (r *Renderer) tableCell(w io.Writer, tableCell *ast.TableCell, entering bool) { +// TableCell writes ast.TableCell node +func (r *Renderer) TableCell(w io.Writer, tableCell *ast.TableCell, entering bool) { if !entering { - r.outOneOf(w, tableCell.IsHeader, "</th>", "</td>") - r.cr(w) + r.OutOneOf(w, tableCell.IsHeader, "</th>", "</td>") + r.CR(w) return } @@ -848,44 +953,47 @@ func (r *Renderer) tableCell(w io.Writer, tableCell *ast.TableCell, entering boo attrs = append(attrs, fmt.Sprintf(`align="%s"`, align)) } if ast.GetPrevNode(tableCell) == nil { - r.cr(w) + r.CR(w) } r.outTag(w, openTag, attrs) } -func (r *Renderer) tableBody(w io.Writer, node *ast.TableBody, entering bool) { +// TableBody writes ast.TableBody node +func (r *Renderer) TableBody(w io.Writer, node *ast.TableBody, entering bool) { if entering { - r.cr(w) - r.outs(w, "<tbody>") + r.CR(w) + r.Outs(w, "<tbody>") // XXX: this is to adhere to a rather silly test. Should fix test. if ast.GetFirstChild(node) == nil { - r.cr(w) + r.CR(w) } } else { - r.outs(w, "</tbody>") - r.cr(w) + r.Outs(w, "</tbody>") + r.CR(w) } } -func (r *Renderer) matter(w io.Writer, node *ast.DocumentMatter, entering bool) { +// DocumentMatter writes ast.DocumentMatter +func (r *Renderer) DocumentMatter(w io.Writer, node *ast.DocumentMatter, entering bool) { if !entering { return } if r.documentMatter != ast.DocumentMatterNone { - r.outs(w, "</section>\n") + r.Outs(w, "</section>\n") } switch node.Matter { case ast.DocumentMatterFront: - r.outs(w, `<section data-matter="front">`) + r.Outs(w, `<section data-matter="front">`) case ast.DocumentMatterMain: - r.outs(w, `<section data-matter="main">`) + r.Outs(w, `<section data-matter="main">`) case ast.DocumentMatterBack: - r.outs(w, `<section data-matter="back">`) + r.Outs(w, `<section data-matter="back">`) } r.documentMatter = node.Matter } -func (r *Renderer) citation(w io.Writer, node *ast.Citation) { +// Citation writes ast.Citation node +func (r *Renderer) Citation(w io.Writer, node *ast.Citation) { for i, c := range node.Destination { attr := []string{`class="none"`} switch node.Type[i] { @@ -897,23 +1005,25 @@ func (r *Renderer) citation(w io.Writer, node *ast.Citation) { attr[0] = `class="suppressed"` } r.outTag(w, "<cite", attr) - r.outs(w, fmt.Sprintf(`<a href="#%s">`+r.opts.CitationFormatString+`</a>`, c, c)) - r.outs(w, "</cite>") + r.Outs(w, fmt.Sprintf(`<a href="#%s">`+r.opts.CitationFormatString+`</a>`, c, c)) + r.Outs(w, "</cite>") } } -func (r *Renderer) callout(w io.Writer, node *ast.Callout) { +// Callout writes ast.Callout node +func (r *Renderer) Callout(w io.Writer, node *ast.Callout) { attr := []string{`class="callout"`} r.outTag(w, "<span", attr) - r.out(w, node.ID) - r.outs(w, "</span>") + r.Out(w, node.ID) + r.Outs(w, "</span>") } -func (r *Renderer) index(w io.Writer, node *ast.Index) { +// Index writes ast.Index node +func (r *Renderer) Index(w io.Writer, node *ast.Index) { // there is no in-text representation. attr := []string{`class="index"`, fmt.Sprintf(`id="%s"`, node.ID)} r.outTag(w, "<span", attr) - r.outs(w, "</span>") + r.Outs(w, "</span>") } // RenderNode renders a markdown node to HTML @@ -926,102 +1036,102 @@ func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.Wal } switch node := node.(type) { case *ast.Text: - r.text(w, node) + r.Text(w, node) case *ast.Softbreak: - r.cr(w) + r.CR(w) // TODO: make it configurable via out(renderer.softbreak) case *ast.Hardbreak: - r.hardBreak(w, node) + r.HardBreak(w, node) case *ast.NonBlockingSpace: - r.nonBlockingSpace(w, node) + r.NonBlockingSpace(w, node) case *ast.Emph: - r.outOneOf(w, entering, "<em>", "</em>") + r.OutOneOf(w, entering, "<em>", "</em>") case *ast.Strong: - r.outOneOf(w, entering, "<strong>", "</strong>") + r.OutOneOf(w, entering, "<strong>", "</strong>") case *ast.Del: - r.outOneOf(w, entering, "<del>", "</del>") + r.OutOneOf(w, entering, "<del>", "</del>") case *ast.BlockQuote: - tag := tagWithAttributes("<blockquote", BlockAttrs(node)) - r.outOneOfCr(w, entering, tag, "</blockquote>") + tag := TagWithAttributes("<blockquote", BlockAttrs(node)) + r.OutOneOfCr(w, entering, tag, "</blockquote>") case *ast.Aside: - tag := tagWithAttributes("<aside", BlockAttrs(node)) - r.outOneOfCr(w, entering, tag, "</aside>") + tag := TagWithAttributes("<aside", BlockAttrs(node)) + r.OutOneOfCr(w, entering, tag, "</aside>") case *ast.Link: - r.link(w, node, entering) + r.Link(w, node, entering) case *ast.CrossReference: link := &ast.Link{Destination: append([]byte("#"), node.Destination...)} - r.link(w, link, entering) + r.Link(w, link, entering) case *ast.Citation: - r.citation(w, node) + r.Citation(w, node) case *ast.Image: if r.opts.Flags&SkipImages != 0 { return ast.SkipChildren } - r.image(w, node, entering) + r.Image(w, node, entering) case *ast.Code: - r.code(w, node) + r.Code(w, node) case *ast.CodeBlock: - r.codeBlock(w, node) + r.CodeBlock(w, node) case *ast.Caption: - r.caption(w, node, entering) + r.Caption(w, node, entering) case *ast.CaptionFigure: - r.captionFigure(w, node, entering) + r.CaptionFigure(w, node, entering) case *ast.Document: // do nothing case *ast.Paragraph: - r.paragraph(w, node, entering) + r.Paragraph(w, node, entering) case *ast.HTMLSpan: - r.htmlSpan(w, node) + r.HTMLSpan(w, node) case *ast.HTMLBlock: - r.htmlBlock(w, node) + r.HTMLBlock(w, node) case *ast.Heading: - r.heading(w, node, entering) + r.Heading(w, node, entering) case *ast.HorizontalRule: - r.horizontalRule(w, node) + r.HorizontalRule(w, node) case *ast.List: - r.list(w, node, entering) + r.List(w, node, entering) case *ast.ListItem: - r.listItem(w, node, entering) + r.ListItem(w, node, entering) case *ast.Table: - tag := tagWithAttributes("<table", BlockAttrs(node)) - r.outOneOfCr(w, entering, tag, "</table>") + tag := TagWithAttributes("<table", BlockAttrs(node)) + r.OutOneOfCr(w, entering, tag, "</table>") case *ast.TableCell: - r.tableCell(w, node, entering) + r.TableCell(w, node, entering) case *ast.TableHeader: - r.outOneOfCr(w, entering, "<thead>", "</thead>") + r.OutOneOfCr(w, entering, "<thead>", "</thead>") case *ast.TableBody: - r.tableBody(w, node, entering) + r.TableBody(w, node, entering) case *ast.TableRow: - r.outOneOfCr(w, entering, "<tr>", "</tr>") + r.OutOneOfCr(w, entering, "<tr>", "</tr>") case *ast.TableFooter: - r.outOneOfCr(w, entering, "<tfoot>", "</tfoot>") + r.OutOneOfCr(w, entering, "<tfoot>", "</tfoot>") case *ast.Math: - r.outOneOf(w, true, `<span class="math inline">\(`, `\)</span>`) + r.OutOneOf(w, true, `<span class="math inline">\(`, `\)</span>`) EscapeHTML(w, node.Literal) - r.outOneOf(w, false, `<span class="math inline">\(`, `\)</span>`) + r.OutOneOf(w, false, `<span class="math inline">\(`, `\)</span>`) case *ast.MathBlock: - r.outOneOf(w, entering, `<p><span class="math display">\[`, `\]</span></p>`) + r.OutOneOf(w, entering, `<p><span class="math display">\[`, `\]</span></p>`) if entering { EscapeHTML(w, node.Literal) } case *ast.DocumentMatter: - r.matter(w, node, entering) + r.DocumentMatter(w, node, entering) case *ast.Callout: - r.callout(w, node) + r.Callout(w, node) case *ast.Index: - r.index(w, node) + r.Index(w, node) case *ast.Subscript: - r.outOneOf(w, true, "<sub>", "</sub>") + r.OutOneOf(w, true, "<sub>", "</sub>") if entering { Escape(w, node.Literal) } - r.outOneOf(w, false, "<sub>", "</sub>") + r.OutOneOf(w, false, "<sub>", "</sub>") case *ast.Superscript: - r.outOneOf(w, true, "<sup>", "</sup>") + r.OutOneOf(w, true, "<sup>", "</sup>") if entering { Escape(w, node.Literal) } - r.outOneOf(w, false, "<sup>", "</sup>") + r.OutOneOf(w, false, "<sup>", "</sup>") case *ast.Footnotes: // nothing by default; just output the list. default: @@ -1041,7 +1151,7 @@ func (r *Renderer) RenderHeader(w io.Writer, ast ast.Node) { // RenderFooter writes HTML document footer. func (r *Renderer) RenderFooter(w io.Writer, _ ast.Node) { if r.documentMatter != ast.DocumentMatterNone { - r.outs(w, "</section>\n") + r.Outs(w, "</section>\n") } if r.opts.Flags&CompletePage == 0 { @@ -1315,7 +1425,8 @@ func BlockAttrs(node ast.Node) []string { return s } -func tagWithAttributes(name string, attrs []string) string { +// TagWithAttributes creates a HTML tag with a given name and attributes +func TagWithAttributes(name string, attrs []string) string { s := name if len(attrs) > 0 { s += " " + strings.Join(attrs, " ") diff --git a/vendor/github.com/gomarkdown/markdown/parser/block.go b/vendor/github.com/gomarkdown/markdown/parser/block.go index a0b80991..5ef55e98 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/block.go +++ b/vendor/github.com/gomarkdown/markdown/parser/block.go @@ -1074,10 +1074,14 @@ func isBackslashEscaped(data []byte, i int) bool { func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlags, table ast.Node) { i := 0 colCount := 1 + headerIsUnderline := true for i = 0; i < len(data) && data[i] != '\n'; i++ { if data[i] == '|' && !isBackslashEscaped(data, i) { colCount++ } + if data[i] != '-' && data[i] != ' ' && data[i] != ':' && data[i] != '|' { + headerIsUnderline = false + } } // doesn't look like a table header @@ -1097,10 +1101,18 @@ func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlag colCount-- } + // if the header looks like a underline, then we omit the header + // and parse the first line again as underline + if headerIsUnderline { + header = nil + i = 0 + } else { + i++ // move past newline + } + columns = make([]ast.CellAlignFlags, colCount) // move on to the header underline - i++ if i >= len(data) { return } @@ -1175,8 +1187,10 @@ func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlag table = &ast.Table{} p.addBlock(table) - p.addBlock(&ast.TableHeader{}) - p.tableRow(header, columns, true) + if header != nil { + p.addBlock(&ast.TableHeader{}) + p.tableRow(header, columns, true) + } size = skipCharN(data, i, '\n', 1) return } diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go index 6a79593c..d05c6c9d 100644 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "regexp" ) type SidebarCategoryType string @@ -109,3 +110,15 @@ func (o OrderedSidebarCategories) ToJson() []byte { return b } } + +var categoryIdPattern = regexp.MustCompile("(favorites|channels|direct_messages)_[a-z0-9]{26}_[a-z0-9]{26}") + +func IsValidCategoryId(s string) bool { + // Category IDs can either be regular IDs + if IsValidId(s) { + return true + } + + // Or default categories can follow the pattern {type}_{userID}_{teamID} + return categoryIdPattern.MatchString(s) +} diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/config.go b/vendor/github.com/mattermost/mattermost-server/v5/model/config.go index f50bbf29..42863ead 100644 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/config.go +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/config.go @@ -342,6 +342,9 @@ type ServiceSettings struct { EnableAPIChannelDeletion *bool EnableLocalMode *bool LocalModeSocketLocation *string + EnableAWSMetering *bool + ThreadAutoFollow *bool `access:"experimental"` + ManagedResourcePaths *string `access:"environment,write_restrictable,cloud_restrictable"` } func (s *ServiceSettings) SetDefaults(isUpdate bool) { @@ -755,6 +758,18 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) { if s.LocalModeSocketLocation == nil { s.LocalModeSocketLocation = NewString(LOCAL_MODE_SOCKET_PATH) } + + if s.EnableAWSMetering == nil { + s.EnableAWSMetering = NewBool(false) + } + + if s.ThreadAutoFollow == nil { + s.ThreadAutoFollow = NewBool(true) + } + + if s.ManagedResourcePaths == nil { + s.ManagedResourcePaths = NewString("") + } } type ClusterSettings struct { diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go b/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go index 4b71f5a8..aded5be9 100644 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go @@ -36,22 +36,23 @@ type GetFileInfosOptions struct { } type FileInfo struct { - Id string `json:"id"` - CreatorId string `json:"user_id"` - PostId string `json:"post_id,omitempty"` - CreateAt int64 `json:"create_at"` - UpdateAt int64 `json:"update_at"` - DeleteAt int64 `json:"delete_at"` - Path string `json:"-"` // not sent back to the client - ThumbnailPath string `json:"-"` // not sent back to the client - PreviewPath string `json:"-"` // not sent back to the client - Name string `json:"name"` - Extension string `json:"extension"` - Size int64 `json:"size"` - MimeType string `json:"mime_type"` - Width int `json:"width,omitempty"` - Height int `json:"height,omitempty"` - HasPreviewImage bool `json:"has_preview_image,omitempty"` + Id string `json:"id"` + CreatorId string `json:"user_id"` + PostId string `json:"post_id,omitempty"` + CreateAt int64 `json:"create_at"` + UpdateAt int64 `json:"update_at"` + DeleteAt int64 `json:"delete_at"` + Path string `json:"-"` // not sent back to the client + ThumbnailPath string `json:"-"` // not sent back to the client + PreviewPath string `json:"-"` // not sent back to the client + Name string `json:"name"` + Extension string `json:"extension"` + Size int64 `json:"size"` + MimeType string `json:"mime_type"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + HasPreviewImage bool `json:"has_preview_image,omitempty"` + MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization } func (fi *FileInfo) ToJson() string { diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go b/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go new file mode 100644 index 00000000..969a599e --- /dev/null +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package model + +import ( + "encoding/json" +) + +type Thread struct { + PostId string `json:"id"` + ChannelId string `json:"channel_id"` + ReplyCount int64 `json:"reply_count"` + LastReplyAt int64 `json:"last_reply_at"` + Participants StringArray `json:"participants"` +} + +func (o *Thread) ToJson() string { + b, _ := json.Marshal(o) + return string(b) +} + +func (o *Thread) Etag() string { + return Etag(o.PostId, o.LastReplyAt) +} + +type ThreadMembership struct { + PostId string `json:"post_id"` + UserId string `json:"user_id"` + Following bool `json:"following"` + LastViewed int64 `json:"last_view_at"` + LastUpdated int64 `json:"last_update_at"` +} + +func (o *ThreadMembership) ToJson() string { + b, _ := json.Marshal(o) + return string(b) +} diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go b/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go index 2ab71090..9a7ab229 100644 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go @@ -36,6 +36,26 @@ type StringInterface map[string]interface{} type StringMap map[string]string type StringArray []string +func (sa StringArray) Remove(input string) StringArray { + for index := range sa { + if sa[index] == input { + ret := make(StringArray, 0, len(sa)-1) + ret = append(ret, sa[:index]...) + return append(ret, sa[index+1:]...) + } + } + return sa +} + +func (sa StringArray) Contains(input string) bool { + for index := range sa { + if sa[index] == input { + return true + } + } + + return false +} func (sa StringArray) Equals(input StringArray) bool { if len(sa) != len(input) { diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/version.go b/vendor/github.com/mattermost/mattermost-server/v5/model/version.go index 11e0427a..aba587f7 100644 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/version.go +++ b/vendor/github.com/mattermost/mattermost-server/v5/model/version.go @@ -13,6 +13,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "5.29.0", "5.28.0", "5.27.0", "5.26.0", diff --git a/vendor/github.com/mattn/godown/godown.go b/vendor/github.com/mattn/godown/godown.go index 5f73743f..5aae9690 100644 --- a/vendor/github.com/mattn/godown/godown.go +++ b/vendor/github.com/mattn/godown/godown.go @@ -346,6 +346,22 @@ func walk(node *html.Node, w io.Writer, nest int, option *Option) { fmt.Fprint(w, "\n\n") } default: + if option == nil || option.CustomRules == nil { + walk(c, w, nest, option) + break + } + + foundCustom := false + for _, cr := range option.CustomRules { + if tag, customWalk := cr.Rule(walk); strings.ToLower(c.Data) == tag { + customWalk(c, w, nest, option) + foundCustom = true + } + } + + if foundCustom { + break + } walk(c, w, nest, option) } default: @@ -354,11 +370,27 @@ func walk(node *html.Node, w io.Writer, nest int, option *Option) { } } +// WalkFunc type is an signature for functions traversing HTML nodes +type WalkFunc func(node *html.Node, w io.Writer, nest int, option *Option) + +// CustomRule is an interface to define custom conversion rules +// +// Rule method accepts `next WalkFunc` as an argument, which `customRule` should call +// to let walk function continue parsing the content inside the HTML tag. +// It returns a tagName to indicate what HTML element this `customRule` handles and the `customRule` +// function itself, where conversion logic should reside. +// +// See example TestRule implementation in godown_test.go +type CustomRule interface { + Rule(next WalkFunc) (tagName string, customRule WalkFunc) +} + // Option is optional information for Convert. type Option struct { - GuessLang func(string) (string, error) - Script bool - Style bool + GuessLang func(string) (string, error) + Script bool + Style bool + CustomRules []CustomRule } // Convert convert HTML to Markdown. Read HTML from r and write to w. diff --git a/vendor/github.com/missdeer/golib/LICENSE b/vendor/github.com/missdeer/golib/LICENSE index 0d9b5ada..8000a6fa 100644 --- a/vendor/github.com/missdeer/golib/LICENSE +++ b/vendor/github.com/missdeer/golib/LICENSE @@ -1,21 +1,504 @@ -MIT License - -Copyright (c) 2017 DForD Software - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/vendor/github.com/shazow/rateio/limiter.go b/vendor/github.com/shazow/rateio/limiter.go index db5ae76c..a18ce3c1 100644 --- a/vendor/github.com/shazow/rateio/limiter.go +++ b/vendor/github.com/shazow/rateio/limiter.go @@ -7,7 +7,7 @@ import ( const minInt = -int(^uint(0)>>1) - 1 -// The error returned when the read rate exceeds our specification. +// ErrRateExceeded is the error returned when the read rate exceeds our specification. var ErrRateExceeded = errors.New("Read rate exceeded.") // Limiter is an interface for a rate limiter. @@ -27,7 +27,7 @@ type simpleLimiter struct { } // NewSimpleLimiter creates a Limiter that restricts a given number of bytes per frequency. -func NewSimpleLimiter(amount int, frequency time.Duration) Limiter { +func NewSimpleLimiter(amount int, frequency time.Duration) *simpleLimiter { return &simpleLimiter{ Amount: amount, Frequency: frequency, @@ -38,7 +38,7 @@ func NewSimpleLimiter(amount int, frequency time.Duration) Limiter { // SimpleLimiter but adds a grace period at the start of the rate // limiting where it allows unlimited bytes to be read during that // period. -func NewGracefulLimiter(amount int, frequency time.Duration, grace time.Duration) Limiter { +func NewGracefulLimiter(amount int, frequency time.Duration, grace time.Duration) *simpleLimiter { return &simpleLimiter{ Amount: amount, Frequency: frequency, @@ -60,3 +60,12 @@ func (limit *simpleLimiter) Count(n int) error { } return nil } + +// Delay returns a channel that can be used to block until next window +func (limit *simpleLimiter) Delay() <-chan time.Time { + waitTill := time.Now() + if limit.numRead >= limit.Amount { + waitTill = waitTill.Add(limit.Frequency) + } + return time.NewTimer(time.Until(waitTill)).C +} diff --git a/vendor/github.com/shazow/ssh-chat/sshd/auth.go b/vendor/github.com/shazow/ssh-chat/sshd/auth.go index afa7271a..a1404135 100644 --- a/vendor/github.com/shazow/ssh-chat/sshd/auth.go +++ b/vendor/github.com/shazow/ssh-chat/sshd/auth.go @@ -19,6 +19,7 @@ type Auth interface { } // MakeAuth makes an ssh.ServerConfig which performs authentication against an Auth implementation. +// TODO: Switch to using ssh.AuthMethod instead? func MakeAuth(auth Auth) *ssh.ServerConfig { config := ssh.ServerConfig{ NoClientAuth: false, diff --git a/vendor/github.com/shazow/ssh-chat/sshd/pty.go b/vendor/github.com/shazow/ssh-chat/sshd/pty.go index 4443fd33..d3ed9ca8 100644 --- a/vendor/github.com/shazow/ssh-chat/sshd/pty.go +++ b/vendor/github.com/shazow/ssh-chat/sshd/pty.go @@ -6,8 +6,8 @@ import "encoding/binary" // parsePtyRequest parses the payload of the pty-req message and extracts the // dimensions of the terminal. See RFC 4254, section 6.2. -func parsePtyRequest(s []byte) (width, height int, ok bool) { - _, s, ok = parseString(s) +func parsePtyRequest(s []byte) (term string, width, height int, ok bool) { + term, s, ok = parseString(s) if !ok { return } diff --git a/vendor/github.com/shazow/ssh-chat/sshd/terminal.go b/vendor/github.com/shazow/ssh-chat/sshd/terminal.go index 472b5c15..e8d99016 100644 --- a/vendor/github.com/shazow/ssh-chat/sshd/terminal.go +++ b/vendor/github.com/shazow/ssh-chat/sshd/terminal.go @@ -55,6 +55,29 @@ func (c sshConn) Name() string { return c.User() } +// EnvVar is an environment variable key-value pair +type EnvVar struct { + Key string + Value string +} + +func (v EnvVar) String() string { + return v.Key + "=" + v.Value +} + +// Env is a wrapper type around []EnvVar with some helper methods +type Env []EnvVar + +// Get returns the latest value for a given key, or empty string if not found +func (e Env) Get(key string) string { + for i := len(e) - 1; i >= 0; i-- { + if e[i].Key == key { + return e[i].Value + } + } + return "" +} + // Terminal extends ssh/terminal to include a close method type Terminal struct { terminal.Terminal @@ -63,9 +86,14 @@ type Terminal struct { done chan struct{} closeOnce sync.Once + + mu sync.Mutex + env []EnvVar + term string } // Make new terminal from a session channel +// TODO: For v2, make a separate `Serve(ctx context.Context) error` method to activate the Terminal func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) { if ch.ChannelType() != "session" { return nil, ErrNotSessionChannel @@ -75,14 +103,15 @@ func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) { return nil, err } term := Terminal{ - Terminal: *terminal.NewTerminal(channel, "Connecting..."), + Terminal: *terminal.NewTerminal(channel, ""), Conn: sshConn{conn}, Channel: channel, done: make(chan struct{}), } - go term.listen(requests) + ready := make(chan struct{}) + go term.listen(requests, ready) go func() { // Keep-Alive Ticker @@ -103,7 +132,18 @@ func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) { } }() - return &term, nil + // We need to wait for term.ready to acquire a shell before we return, this + // gives the SSH session a chance to populate the env vars and other state. + // TODO: Make the timeout configurable + // TODO: Use context.Context for abort/timeout in the future, will need to change the API. + select { + case <-ready: // shell acquired + return &term, nil + case <-term.done: + return nil, errors.New("terminal aborted") + case <-time.NewTimer(time.Minute).C: + return nil, errors.New("timed out starting terminal") + } } // NewSession Finds a session channel and make a Terminal from it @@ -133,8 +173,9 @@ func (t *Terminal) Close() error { return err } -// Negotiate terminal type and settings -func (t *Terminal) listen(requests <-chan *ssh.Request) { +// listen negotiates the terminal type and state +// ready is closed when the terminal is ready. +func (t *Terminal) listen(requests <-chan *ssh.Request, ready chan<- struct{}) { hasShell := false for req := range requests { @@ -146,13 +187,19 @@ func (t *Terminal) listen(requests <-chan *ssh.Request) { if !hasShell { ok = true hasShell = true + close(ready) } case "pty-req": - width, height, ok = parsePtyRequest(req.Payload) + var term string + term, width, height, ok = parsePtyRequest(req.Payload) if ok { // TODO: Hardcode width to 100000? err := t.SetSize(width, height) ok = err == nil + // Save the term: + t.mu.Lock() + t.term = term + t.mu.Unlock() } case "window-change": width, height, ok = parseWinchRequest(req.Payload) @@ -161,6 +208,14 @@ func (t *Terminal) listen(requests <-chan *ssh.Request) { err := t.SetSize(width, height) ok = err == nil } + case "env": + var v EnvVar + if err := ssh.Unmarshal(req.Payload, &v); err == nil { + t.mu.Lock() + t.env = append(t.env, v) + t.mu.Unlock() + ok = true + } } if req.WantReply { @@ -168,3 +223,24 @@ func (t *Terminal) listen(requests <-chan *ssh.Request) { } } } + +// Env returns a list of environment key-values that have been set. They are +// returned in the order that they have been set, there is no deduplication or +// other pre-processing applied. +func (t *Terminal) Env() Env { + t.mu.Lock() + defer t.mu.Unlock() + return Env(t.env) +} + +// Term returns the terminal string value as set by the pty. +// If there was no pty request, it falls back to the TERM value passed in as an +// Env variable. +func (t *Terminal) Term() string { + t.mu.Lock() + defer t.mu.Unlock() + if t.term != "" { + return t.term + } + return Env(t.env).Get("TERM") +} diff --git a/vendor/github.com/shazow/ssh-chat/sshd/terminal/terminal.go b/vendor/github.com/shazow/ssh-chat/sshd/terminal/terminal.go index d6650bb1..ec04e8f1 100644 --- a/vendor/github.com/shazow/ssh-chat/sshd/terminal/terminal.go +++ b/vendor/github.com/shazow/ssh-chat/sshd/terminal/terminal.go @@ -10,6 +10,8 @@ import ( "strconv" "sync" "unicode/utf8" + + "golang.org/x/text/width" ) // EscapeCodes contains escape sequences that can be written to the terminal in @@ -262,7 +264,7 @@ func (t *Terminal) moveCursorToPos(pos int) { return } - x := visualLength(t.prompt) + pos + x := visualLength(t.prompt) + visualLength(t.line[:pos]) y := x / t.termWidth x = x % t.termWidth @@ -351,6 +353,7 @@ func (t *Terminal) setLine(newLine []rune, newPos int) { for i := len(newLine); i < len(t.line); i++ { t.writeLine(space) } + t.line = newLine t.moveCursorToPos(newPos) } t.line = newLine @@ -462,6 +465,10 @@ func visualLength(runes []rune) int { inEscapeSeq = true default: length++ + kind := width.LookupRune(r).Kind() + if kind == width.EastAsianFullwidth || kind == width.EastAsianWide { + length++ + } } } |