This commit is contained in:
Aine
2022-01-11 19:58:35 +02:00
commit eac249819d
86 changed files with 16954 additions and 0 deletions

55
Makefile Normal file
View File

@@ -0,0 +1,55 @@
BUILDFLAGS = -buildmode=pie
### CI vars
CI_LOGIN_COMMAND = @echo "Not a CI, skip login"
CI_REGISTRY_IMAGE ?= registry.gitlab.com/etke.cc/honoroit
CI_COMMIT_TAG ?= latest
# for main branch it must be set explicitly
ifeq ($(CI_COMMIT_TAG), main)
CI_COMMIT_TAG = latest
endif
# login command
ifdef CI_JOB_TOKEN
CI_LOGIN_COMMAND = @docker login -u gitlab-ci-token -p $(CI_JOB_TOKEN) $(CI_REGISTRY)
endif
# update go dependencies
update:
go get ./cmd
go mod tidy
go mod vendor
mock:
-@rm -rf mocks
@mockery --all
# run linter
lint:
golangci-lint run ./...
# run linter and fix issues if possible
lintfix:
golangci-lint run --fix ./...
# run unit tests
test:
@go test ${BUILDFLAGS} -coverprofile=cover.out ./...
@go tool cover -func=cover.out
-@rm -f cover.out
# run honoroit, note: make doesn't understand exit code 130 and sets it == 1
run:
@go run ${BUILDFLAGS} ./cmd || exit 0
# build honoroit
build:
go build ${BUILDFLAGS} -v -o honoroit -ldflags "-X main.version=${CI_COMMIT_TAG}" ./cmd
# CI: docker login
login:
@echo "trying to login to docker registry..."
$(CI_LOGIN_COMMAND)
# docker build
docker:
docker buildx create --use
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 --push -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG} .

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
# emm: Export Matrix Messages
A CLI tool that joins the room and exports last N messages to the file you specified.
## TODO
* setup the repo properly
* add docs
## Usage
```bash
emm -hs hs.url -u user -p pass -r "#room:hs.url" -t contrib/hugo-post-template.md -o /tmp/%s.md
```

53
cmd/cmd.go Normal file
View File

@@ -0,0 +1,53 @@
package main
import (
"gitlab.com/etke.cc/emm/export"
"gitlab.com/etke.cc/emm/flags"
"gitlab.com/etke.cc/emm/matrix"
"maunium.net/go/mautrix/id"
)
var cfg *flags.Config
func main() {
var err error
cfg, err = flags.Parse()
if err != nil {
panic(err)
}
resolve()
err = matrix.Init(*cfg.HS, *cfg.Login, *cfg.Password, cfg.RoomID, cfg.RoomAlias)
if err != nil {
panic(err)
}
messages, err := matrix.Messages(*cfg.Limit)
if err != nil {
panic(err)
}
err = export.Run(*cfg.Template, *cfg.Output, messages)
if err != nil {
panic(err)
}
}
func resolve() {
// Resolve homeserver
hs, err := matrix.ResolveServer(*cfg.HS)
if err != nil {
panic(err)
}
cfg.HS = &hs
// Resolve room type
alias, err := matrix.IsRoom(*cfg.Room)
if err != nil {
panic(err)
}
if alias {
cfg.RoomAlias = id.RoomAlias(*cfg.Room)
} else {
cfg.RoomID = id.RoomID(*cfg.Room)
}
}

View File

@@ -0,0 +1,9 @@
---
id: '{{ .ID }}'
date: '{{ .CreatedAt }}'
title: '{{ .CreatedAt }}'
author: '{{ .Author }}'
draft: false
---
{{ .Text }}

41
export/export.go Normal file
View File

@@ -0,0 +1,41 @@
package export
import (
"text/template"
"gitlab.com/etke.cc/emm/matrix"
)
// DefaultTemplate text
const DefaultTemplate = `
id={{ .ID }}
author={{ .Author }}
text={{ .Text }}
html={{ .HTML }}
created_at={{ .CreatedAt }}
`
// Run export
func Run(templatePath string, output string, messages []*matrix.Message) error {
tpl, err := createTemplate(templatePath)
if err != nil {
return err
}
for _, message := range messages {
err = save(tpl, output, message)
if err != nil {
return err
}
}
return nil
}
func save(tpl *template.Template, path string, message *matrix.Message) error {
file, err := getOutput(path, message.ID)
if err != nil {
return err
}
return tpl.Execute(file, message)
}

37
export/output.go Normal file
View File

@@ -0,0 +1,37 @@
package export
import (
"fmt"
"os"
"strings"
"maunium.net/go/mautrix/id"
)
var outputFileSingle *os.File
func getOutput(output string, eventID id.EventID) (*os.File, error) {
if isMulti(output) {
return getOutputMulti(fmt.Sprintf(output, eventID))
}
return getOutputSingle(output)
}
// isMulti check if output is a single file
func isMulti(output string) bool {
return strings.Contains(output, "%s")
}
func getOutputSingle(output string) (*os.File, error) {
var err error
if outputFileSingle == nil {
outputFileSingle, err = os.OpenFile(output, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
}
return outputFileSingle, err
}
func getOutputMulti(output string) (*os.File, error) {
return os.OpenFile(output, os.O_WRONLY|os.O_CREATE, 0644)
}

28
export/template.go Normal file
View File

@@ -0,0 +1,28 @@
package export
import (
"os"
"text/template"
)
func createTemplate(templatePath string) (*template.Template, error) {
var err error
templateContent := DefaultTemplate
if templatePath != "" {
templateContent, err = loadTemplate(templatePath)
if err != nil {
return nil, err
}
}
return template.New("emm").Parse(templateContent)
}
func loadTemplate(path string) (string, error) {
content, err := os.ReadFile(path)
if err != nil {
return "", err
}
return string(content), nil
}

75
flags/flags.go Normal file
View File

@@ -0,0 +1,75 @@
// Package flags manages command line arguments and flags
package flags
import (
"errors"
"flag"
"maunium.net/go/mautrix/id"
)
// Config from the command line args and flags
type Config struct {
// HS is matrix homeserver (supports delegation)
HS *string
// Login is matrix user login
Login *string
// Password is matrix user password
Password *string
// Room id or alias (raw)
Room *string
// Room ID
RoomID id.RoomID
// RoomAlias
RoomAlias id.RoomAlias
// Limit of messages
Limit *int
// Template file
Template *string
// Output file name. If filename contains %s it will be replaced with event ID (in case of one file per message)
Output *string
}
func (cfg *Config) validate() error {
if cfg.HS == nil || *cfg.HS == "" {
return errors.New("-hs is not set. You must specify homeserver URL")
}
if cfg.Login == nil || *cfg.Login == "" {
return errors.New("-u is not set. You must specify username/login of the matrix user")
}
if cfg.Password == nil || *cfg.Password == "" {
return errors.New("-p is not set. You must specify password of the matrix user")
}
if cfg.Room == nil || *cfg.Room == "" {
return errors.New("-r is not set. You must specify room id or alias")
}
if cfg.Output == nil || *cfg.Output == "" {
return errors.New("-o is not set. You must specify output filename")
}
if cfg.Limit == nil || *cfg.Limit < 0 {
limit := 0
cfg.Limit = &limit
}
if cfg.Template == nil {
empty := ""
cfg.Template = &empty
}
return nil
}
// Parse command line arguments and flags
func Parse() (*Config, error) {
cfg := &Config{
HS: flag.String("hs", "", "Homeserver URL (supports delegation)"),
Login: flag.String("u", "", "Username/Login of the matrix user"),
Password: flag.String("p", "", "Password of the matrix user"),
Room: flag.String("r", "", "Room ID or alias"),
Limit: flag.Int("l", 0, "Messages limit"),
Template: flag.String("t", "", "Template file. Default is JSON message struct"),
Output: flag.String("o", "", "Output filename. If it contains %s, it will be replaced with event ID (one message per file)"),
}
flag.Parse()
return cfg, cfg.validate()
}

11
go.mod Normal file
View File

@@ -0,0 +1,11 @@
module gitlab.com/etke.cc/emm
go 1.17
require maunium.net/go/mautrix v0.10.9
require (
github.com/btcsuite/btcutil v1.0.2 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
)

67
go.sum Normal file
View File

@@ -0,0 +1,67 @@
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/maulogger/v2 v2.3.2/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
maunium.net/go/mautrix v0.10.9 h1:Xb2lBpjSoMazsSlvsDEqJnuHZDJpYpxwza2N0w60UV0=
maunium.net/go/mautrix v0.10.9/go.mod h1:4XljZZGZiIlpfbQ+Tt2ykjapskJ8a7Z2i9y/+YaceF8=

40
matrix/client.go Normal file
View File

@@ -0,0 +1,40 @@
package matrix
import (
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/id"
)
var client *mautrix.Client
var room id.RoomID
// Init matrix client
func Init(hs string, login string, password string, roomID id.RoomID, alias id.RoomAlias) error {
var err error
client, err = mautrix.NewClient(hs, "", "")
if err != nil {
return err
}
_, err = client.Login(&mautrix.ReqLogin{
Type: "m.login.password",
Identifier: mautrix.UserIdentifier{
Type: mautrix.IdentifierTypeUser,
User: login,
},
Password: password,
StoreCredentials: true,
})
if err != nil {
return err
}
if roomID == "" {
roomID, err = resolveAlias(alias)
if err != nil {
return err
}
}
room = roomID
return nil
}

70
matrix/messages.go Normal file
View File

@@ -0,0 +1,70 @@
package matrix
import (
"time"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
// Message struct
type Message struct {
// ID is a matrix event id of the message
ID id.EventID
// Author is a matrix id of the sender
Author id.UserID
// Text is the message body in plaintext/markdown format
Text string
// HTML is the message body in html format
HTML string
// CreatedAt is a timestamp
CreatedAt time.Time
}
// Messages of the room
// Note on limit - the output slice may be less size than limit you sent in the following cases:
// * room contains less messages than limit
// * some room messages don't contain body/formatted body
func Messages(limit int) ([]*Message, error) {
var messages []*Message
filter := &mautrix.FilterPart{
Types: []event.Type{event.EventMessage},
NotTypes: []event.Type{event.EventRedaction, event.EventReaction, event.StateMember},
}
chunks, err := client.Messages(room, "", "", 'b', filter, limit)
if err != nil {
return nil, err
}
for _, chunk := range chunks.Chunk {
message := parseMessage(chunk)
if message == nil {
continue
}
messages = append(messages, message)
}
return messages, nil
}
func parseMessage(evt *event.Event) *Message {
err := evt.Content.ParseRaw(event.EventMessage)
if err != nil {
return nil
}
content := evt.Content.AsMessage()
if content.Body == "" && content.FormattedBody == "" {
return nil
}
return &Message{
ID: evt.ID,
Author: evt.Sender,
Text: content.Body,
HTML: content.FormattedBody,
CreatedAt: time.UnixMilli(evt.Timestamp),
}
}

48
matrix/resolve.go Normal file
View File

@@ -0,0 +1,48 @@
package matrix
import (
"errors"
"strings"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/id"
)
// ResolveServer resolves actual homeserver URL from possible delegated host
func ResolveServer(homeserver string) (string, error) {
discover, err := mautrix.DiscoverClientAPI(homeserver)
if err != nil {
return "", err
}
return discover.Homeserver.BaseURL, nil
}
// IsRoom checks if room is valid room alias or room ID. True = alias, False = room ID
func IsRoom(room string) (bool, error) {
if room == "" {
return false, errors.New("room is not set")
}
if strings.LastIndex(room, ":") == -1 {
return false, errors.New("not a valid room id or alias")
}
if strings.HasPrefix(room, "#") {
return true, nil
}
if strings.HasPrefix(room, "!") {
return false, nil
}
return false, errors.New("not a valid room id or alias")
}
func resolveAlias(alias id.RoomAlias) (id.RoomID, error) {
resp, err := client.ResolveAlias(alias)
if err != nil {
return "", err
}
return resp.RoomID, err
}

16
vendor/github.com/btcsuite/btcutil/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2013-2017 The btcsuite developers
Copyright (c) 2016-2017 The Lightning Network Developers
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

34
vendor/github.com/btcsuite/btcutil/base58/README.md generated vendored Normal file
View File

@@ -0,0 +1,34 @@
base58
==========
[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil)
[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcutil/base58)
Package base58 provides an API for encoding and decoding to and from the
modified base58 encoding. It also provides an API to do Base58Check encoding,
as described [here](https://en.bitcoin.it/wiki/Base58Check_encoding).
A comprehensive suite of tests is provided to ensure proper functionality.
## Installation and Updating
```bash
$ go get -u github.com/btcsuite/btcutil/base58
```
## Examples
* [Decode Example](http://godoc.org/github.com/btcsuite/btcutil/base58#example-Decode)
Demonstrates how to decode modified base58 encoded data.
* [Encode Example](http://godoc.org/github.com/btcsuite/btcutil/base58#example-Encode)
Demonstrates how to encode data using the modified base58 encoding scheme.
* [CheckDecode Example](http://godoc.org/github.com/btcsuite/btcutil/base58#example-CheckDecode)
Demonstrates how to decode Base58Check encoded data.
* [CheckEncode Example](http://godoc.org/github.com/btcsuite/btcutil/base58#example-CheckEncode)
Demonstrates how to encode data using the Base58Check encoding scheme.
## License
Package base58 is licensed under the [copyfree](http://copyfree.org) ISC
License.

49
vendor/github.com/btcsuite/btcutil/base58/alphabet.go generated vendored Normal file
View File

@@ -0,0 +1,49 @@
// Copyright (c) 2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
// AUTOGENERATED by genalphabet.go; do not edit.
package base58
const (
// alphabet is the modified base58 alphabet used by Bitcoin.
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
alphabetIdx0 = '1'
)
var b58 = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 255, 255, 255, 255, 255, 255,
255, 9, 10, 11, 12, 13, 14, 15,
16, 255, 17, 18, 19, 20, 21, 255,
22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 255, 255, 255, 255, 255,
255, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 255, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
}

75
vendor/github.com/btcsuite/btcutil/base58/base58.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
// Copyright (c) 2013-2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package base58
import (
"math/big"
)
//go:generate go run genalphabet.go
var bigRadix = big.NewInt(58)
var bigZero = big.NewInt(0)
// Decode decodes a modified base58 string to a byte slice.
func Decode(b string) []byte {
answer := big.NewInt(0)
j := big.NewInt(1)
scratch := new(big.Int)
for i := len(b) - 1; i >= 0; i-- {
tmp := b58[b[i]]
if tmp == 255 {
return []byte("")
}
scratch.SetInt64(int64(tmp))
scratch.Mul(j, scratch)
answer.Add(answer, scratch)
j.Mul(j, bigRadix)
}
tmpval := answer.Bytes()
var numZeros int
for numZeros = 0; numZeros < len(b); numZeros++ {
if b[numZeros] != alphabetIdx0 {
break
}
}
flen := numZeros + len(tmpval)
val := make([]byte, flen)
copy(val[numZeros:], tmpval)
return val
}
// Encode encodes a byte slice to a modified base58 string.
func Encode(b []byte) string {
x := new(big.Int)
x.SetBytes(b)
answer := make([]byte, 0, len(b)*136/100)
for x.Cmp(bigZero) > 0 {
mod := new(big.Int)
x.DivMod(x, bigRadix, mod)
answer = append(answer, alphabet[mod.Int64()])
}
// leading zero bytes
for _, i := range b {
if i != 0 {
break
}
answer = append(answer, alphabetIdx0)
}
// reverse
alen := len(answer)
for i := 0; i < alen/2; i++ {
answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i]
}
return string(answer)
}

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2013-2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package base58
import (
"crypto/sha256"
"errors"
)
// ErrChecksum indicates that the checksum of a check-encoded string does not verify against
// the checksum.
var ErrChecksum = errors.New("checksum error")
// ErrInvalidFormat indicates that the check-encoded string has an invalid format.
var ErrInvalidFormat = errors.New("invalid format: version and/or checksum bytes missing")
// checksum: first four bytes of sha256^2
func checksum(input []byte) (cksum [4]byte) {
h := sha256.Sum256(input)
h2 := sha256.Sum256(h[:])
copy(cksum[:], h2[:4])
return
}
// CheckEncode prepends a version byte and appends a four byte checksum.
func CheckEncode(input []byte, version byte) string {
b := make([]byte, 0, 1+len(input)+4)
b = append(b, version)
b = append(b, input[:]...)
cksum := checksum(b)
b = append(b, cksum[:]...)
return Encode(b)
}
// CheckDecode decodes a string that was encoded with CheckEncode and verifies the checksum.
func CheckDecode(input string) (result []byte, version byte, err error) {
decoded := Decode(input)
if len(decoded) < 5 {
return nil, 0, ErrInvalidFormat
}
version = decoded[0]
var cksum [4]byte
copy(cksum[:], decoded[len(decoded)-4:])
if checksum(decoded[:len(decoded)-4]) != cksum {
return nil, 0, ErrChecksum
}
payload := decoded[1 : len(decoded)-4]
result = append(result, payload...)
return
}

View File

@@ -0,0 +1,17 @@
#!/bin/sh
# This script uses gocov to generate a test coverage report.
# The gocov tool my be obtained with the following command:
# go get github.com/axw/gocov/gocov
#
# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH.
# Check for gocov.
type gocov >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo >&2 "This script requires the gocov tool."
echo >&2 "You may obtain it with the following command:"
echo >&2 "go get github.com/axw/gocov/gocov"
exit 1
fi
gocov test | gocov report

29
vendor/github.com/btcsuite/btcutil/base58/doc.go generated vendored Normal file
View File

@@ -0,0 +1,29 @@
// Copyright (c) 2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
/*
Package base58 provides an API for working with modified base58 and Base58Check
encodings.
Modified Base58 Encoding
Standard base58 encoding is similar to standard base64 encoding except, as the
name implies, it uses a 58 character alphabet which results in an alphanumeric
string and allows some characters which are problematic for humans to be
excluded. Due to this, there can be various base58 alphabets.
The modified base58 alphabet used by Bitcoin, and hence this package, omits the
0, O, I, and l characters that look the same in many fonts and are therefore
hard to humans to distinguish.
Base58Check Encoding Scheme
The Base58Check encoding scheme is primarily used for Bitcoin addresses at the
time of this writing, however it can be used to generically encode arbitrary
byte arrays into human-readable strings along with a version byte that can be
used to differentiate the same payload. For Bitcoin addresses, the extra
version is used to differentiate the network of otherwise identical public keys
which helps prevent using an address intended for one network on another.
*/
package base58

3
vendor/golang.org/x/crypto/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at https://tip.golang.org/AUTHORS.

3
vendor/golang.org/x/crypto/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at https://tip.golang.org/CONTRIBUTORS.

27
vendor/golang.org/x/crypto/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/crypto/PATENTS generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

93
vendor/golang.org/x/crypto/hkdf/hkdf.go generated vendored Normal file
View File

@@ -0,0 +1,93 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation
// Function (HKDF) as defined in RFC 5869.
//
// HKDF is a cryptographic key derivation function (KDF) with the goal of
// expanding limited input keying material into one or more cryptographically
// strong secret keys.
package hkdf // import "golang.org/x/crypto/hkdf"
import (
"crypto/hmac"
"errors"
"hash"
"io"
)
// Extract generates a pseudorandom key for use with Expand from an input secret
// and an optional independent salt.
//
// Only use this function if you need to reuse the extracted key with multiple
// Expand invocations and different context values. Most common scenarios,
// including the generation of multiple keys, should use New instead.
func Extract(hash func() hash.Hash, secret, salt []byte) []byte {
if salt == nil {
salt = make([]byte, hash().Size())
}
extractor := hmac.New(hash, salt)
extractor.Write(secret)
return extractor.Sum(nil)
}
type hkdf struct {
expander hash.Hash
size int
info []byte
counter byte
prev []byte
buf []byte
}
func (f *hkdf) Read(p []byte) (int, error) {
// Check whether enough data can be generated
need := len(p)
remains := len(f.buf) + int(255-f.counter+1)*f.size
if remains < need {
return 0, errors.New("hkdf: entropy limit reached")
}
// Read any leftover from the buffer
n := copy(p, f.buf)
p = p[n:]
// Fill the rest of the buffer
for len(p) > 0 {
f.expander.Reset()
f.expander.Write(f.prev)
f.expander.Write(f.info)
f.expander.Write([]byte{f.counter})
f.prev = f.expander.Sum(f.prev[:0])
f.counter++
// Copy the new batch into p
f.buf = f.prev
n = copy(p, f.buf)
p = p[n:]
}
// Save leftovers for next run
f.buf = f.buf[n:]
return need, nil
}
// Expand returns a Reader, from which keys can be read, using the given
// pseudorandom key and optional context info, skipping the extraction step.
//
// The pseudorandomKey should have been generated by Extract, or be a uniformly
// random or pseudorandom cryptographically strong key. See RFC 5869, Section
// 3.3. Most common scenarios will want to use New instead.
func Expand(hash func() hash.Hash, pseudorandomKey, info []byte) io.Reader {
expander := hmac.New(hash, pseudorandomKey)
return &hkdf{expander, expander.Size(), info, 1, nil, nil}
}
// New returns a Reader, from which keys can be read, using the given hash,
// secret, salt and context info. Salt and info can be nil.
func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
prk := Extract(hash, secret, salt)
return Expand(hash, prk, info)
}

77
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go generated vendored Normal file
View File

@@ -0,0 +1,77 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
2898 / PKCS #5 v2.0.
A key derivation function is useful when encrypting data based on a password
or any other not-fully-random data. It uses a pseudorandom function to derive
a secure encryption key based on the password.
While v2.0 of the standard defines only one pseudorandom function to use,
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
choose, you can pass the `New` functions from the different SHA packages to
pbkdf2.Key.
*/
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
import (
"crypto/hmac"
"hash"
)
// Key derives a key from the password, salt and iteration count, returning a
// []byte of length keylen that can be used as cryptographic key. The key is
// derived based on the method described as PBKDF2 with the HMAC variant using
// the supplied hash function.
//
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
// doing:
//
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
//
// Remember to get a good random salt. At least 8 bytes is recommended by the
// RFC.
//
// Using a higher iteration count will increase the cost of an exhaustive
// search but will also make derivation proportionally slower.
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
prf := hmac.New(h, password)
hashLen := prf.Size()
numBlocks := (keyLen + hashLen - 1) / hashLen
var buf [4]byte
dk := make([]byte, 0, numBlocks*hashLen)
U := make([]byte, hashLen)
for block := 1; block <= numBlocks; block++ {
// N.B.: || means concatenation, ^ means XOR
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
// U_1 = PRF(password, salt || uint(i))
prf.Reset()
prf.Write(salt)
buf[0] = byte(block >> 24)
buf[1] = byte(block >> 16)
buf[2] = byte(block >> 8)
buf[3] = byte(block)
prf.Write(buf[:4])
dk = prf.Sum(dk)
T := dk[len(dk)-hashLen:]
copy(U, T)
// U_n = PRF(password, U_(n-1))
for n := 2; n <= iter; n++ {
prf.Reset()
prf.Write(U)
U = U[:0]
U = prf.Sum(U)
for x := range U {
T[x] ^= U[x]
}
}
}
return dk[:keyLen]
}

3
vendor/golang.org/x/net/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

3
vendor/golang.org/x/net/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

27
vendor/golang.org/x/net/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/net/PATENTS generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

78
vendor/golang.org/x/net/html/atom/atom.go generated vendored Normal file
View File

@@ -0,0 +1,78 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package atom provides integer codes (also known as atoms) for a fixed set of
// frequently occurring HTML strings: tag names and attribute keys such as "p"
// and "id".
//
// Sharing an atom's name between all elements with the same tag can result in
// fewer string allocations when tokenizing and parsing HTML. Integer
// comparisons are also generally faster than string comparisons.
//
// The value of an atom's particular code is not guaranteed to stay the same
// between versions of this package. Neither is any ordering guaranteed:
// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
// be dense. The only guarantees are that e.g. looking up "div" will yield
// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
package atom // import "golang.org/x/net/html/atom"
// Atom is an integer code for a string. The zero value maps to "".
type Atom uint32
// String returns the atom's name.
func (a Atom) String() string {
start := uint32(a >> 8)
n := uint32(a & 0xff)
if start+n > uint32(len(atomText)) {
return ""
}
return atomText[start : start+n]
}
func (a Atom) string() string {
return atomText[a>>8 : a>>8+a&0xff]
}
// fnv computes the FNV hash with an arbitrary starting value h.
func fnv(h uint32, s []byte) uint32 {
for i := range s {
h ^= uint32(s[i])
h *= 16777619
}
return h
}
func match(s string, t []byte) bool {
for i, c := range t {
if s[i] != c {
return false
}
}
return true
}
// Lookup returns the atom whose name is s. It returns zero if there is no
// such atom. The lookup is case sensitive.
func Lookup(s []byte) Atom {
if len(s) == 0 || len(s) > maxAtomLen {
return 0
}
h := fnv(hash0, s)
if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
return a
}
if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
return a
}
return 0
}
// String returns a string whose contents are equal to s. In that sense, it is
// equivalent to string(s) but may be more efficient.
func String(s []byte) string {
if a := Lookup(s); a != 0 {
return a.String()
}
return string(s)
}

783
vendor/golang.org/x/net/html/atom/table.go generated vendored Normal file
View File

@@ -0,0 +1,783 @@
// Code generated by go generate gen.go; DO NOT EDIT.
//go:generate go run gen.go
package atom
const (
A Atom = 0x1
Abbr Atom = 0x4
Accept Atom = 0x1a06
AcceptCharset Atom = 0x1a0e
Accesskey Atom = 0x2c09
Acronym Atom = 0xaa07
Action Atom = 0x27206
Address Atom = 0x6f307
Align Atom = 0xb105
Allowfullscreen Atom = 0x2080f
Allowpaymentrequest Atom = 0xc113
Allowusermedia Atom = 0xdd0e
Alt Atom = 0xf303
Annotation Atom = 0x1c90a
AnnotationXml Atom = 0x1c90e
Applet Atom = 0x31906
Area Atom = 0x35604
Article Atom = 0x3fc07
As Atom = 0x3c02
Aside Atom = 0x10705
Async Atom = 0xff05
Audio Atom = 0x11505
Autocomplete Atom = 0x2780c
Autofocus Atom = 0x12109
Autoplay Atom = 0x13c08
B Atom = 0x101
Base Atom = 0x3b04
Basefont Atom = 0x3b08
Bdi Atom = 0xba03
Bdo Atom = 0x14b03
Bgsound Atom = 0x15e07
Big Atom = 0x17003
Blink Atom = 0x17305
Blockquote Atom = 0x1870a
Body Atom = 0x2804
Br Atom = 0x202
Button Atom = 0x19106
Canvas Atom = 0x10306
Caption Atom = 0x23107
Center Atom = 0x22006
Challenge Atom = 0x29b09
Charset Atom = 0x2107
Checked Atom = 0x47907
Cite Atom = 0x19c04
Class Atom = 0x56405
Code Atom = 0x5c504
Col Atom = 0x1ab03
Colgroup Atom = 0x1ab08
Color Atom = 0x1bf05
Cols Atom = 0x1c404
Colspan Atom = 0x1c407
Command Atom = 0x1d707
Content Atom = 0x58b07
Contenteditable Atom = 0x58b0f
Contextmenu Atom = 0x3800b
Controls Atom = 0x1de08
Coords Atom = 0x1ea06
Crossorigin Atom = 0x1fb0b
Data Atom = 0x4a504
Datalist Atom = 0x4a508
Datetime Atom = 0x2b808
Dd Atom = 0x2d702
Default Atom = 0x10a07
Defer Atom = 0x5c705
Del Atom = 0x45203
Desc Atom = 0x56104
Details Atom = 0x7207
Dfn Atom = 0x8703
Dialog Atom = 0xbb06
Dir Atom = 0x9303
Dirname Atom = 0x9307
Disabled Atom = 0x16408
Div Atom = 0x16b03
Dl Atom = 0x5e602
Download Atom = 0x46308
Draggable Atom = 0x17a09
Dropzone Atom = 0x40508
Dt Atom = 0x64b02
Em Atom = 0x6e02
Embed Atom = 0x6e05
Enctype Atom = 0x28d07
Face Atom = 0x21e04
Fieldset Atom = 0x22608
Figcaption Atom = 0x22e0a
Figure Atom = 0x24806
Font Atom = 0x3f04
Footer Atom = 0xf606
For Atom = 0x25403
ForeignObject Atom = 0x2540d
Foreignobject Atom = 0x2610d
Form Atom = 0x26e04
Formaction Atom = 0x26e0a
Formenctype Atom = 0x2890b
Formmethod Atom = 0x2a40a
Formnovalidate Atom = 0x2ae0e
Formtarget Atom = 0x2c00a
Frame Atom = 0x8b05
Frameset Atom = 0x8b08
H1 Atom = 0x15c02
H2 Atom = 0x2de02
H3 Atom = 0x30d02
H4 Atom = 0x34502
H5 Atom = 0x34f02
H6 Atom = 0x64d02
Head Atom = 0x33104
Header Atom = 0x33106
Headers Atom = 0x33107
Height Atom = 0x5206
Hgroup Atom = 0x2ca06
Hidden Atom = 0x2d506
High Atom = 0x2db04
Hr Atom = 0x15702
Href Atom = 0x2e004
Hreflang Atom = 0x2e008
Html Atom = 0x5604
HttpEquiv Atom = 0x2e80a
I Atom = 0x601
Icon Atom = 0x58a04
Id Atom = 0x10902
Iframe Atom = 0x2fc06
Image Atom = 0x30205
Img Atom = 0x30703
Input Atom = 0x44b05
Inputmode Atom = 0x44b09
Ins Atom = 0x20403
Integrity Atom = 0x23f09
Is Atom = 0x16502
Isindex Atom = 0x30f07
Ismap Atom = 0x31605
Itemid Atom = 0x38b06
Itemprop Atom = 0x19d08
Itemref Atom = 0x3cd07
Itemscope Atom = 0x67109
Itemtype Atom = 0x31f08
Kbd Atom = 0xb903
Keygen Atom = 0x3206
Keytype Atom = 0xd607
Kind Atom = 0x17704
Label Atom = 0x5905
Lang Atom = 0x2e404
Legend Atom = 0x18106
Li Atom = 0xb202
Link Atom = 0x17404
List Atom = 0x4a904
Listing Atom = 0x4a907
Loop Atom = 0x5d04
Low Atom = 0xc303
Main Atom = 0x1004
Malignmark Atom = 0xb00a
Manifest Atom = 0x6d708
Map Atom = 0x31803
Mark Atom = 0xb604
Marquee Atom = 0x32707
Math Atom = 0x32e04
Max Atom = 0x33d03
Maxlength Atom = 0x33d09
Media Atom = 0xe605
Mediagroup Atom = 0xe60a
Menu Atom = 0x38704
Menuitem Atom = 0x38708
Meta Atom = 0x4b804
Meter Atom = 0x9805
Method Atom = 0x2a806
Mglyph Atom = 0x30806
Mi Atom = 0x34702
Min Atom = 0x34703
Minlength Atom = 0x34709
Mn Atom = 0x2b102
Mo Atom = 0xa402
Ms Atom = 0x67402
Mtext Atom = 0x35105
Multiple Atom = 0x35f08
Muted Atom = 0x36705
Name Atom = 0x9604
Nav Atom = 0x1303
Nobr Atom = 0x3704
Noembed Atom = 0x6c07
Noframes Atom = 0x8908
Nomodule Atom = 0xa208
Nonce Atom = 0x1a605
Noscript Atom = 0x21608
Novalidate Atom = 0x2b20a
Object Atom = 0x26806
Ol Atom = 0x13702
Onabort Atom = 0x19507
Onafterprint Atom = 0x2360c
Onautocomplete Atom = 0x2760e
Onautocompleteerror Atom = 0x27613
Onauxclick Atom = 0x61f0a
Onbeforeprint Atom = 0x69e0d
Onbeforeunload Atom = 0x6e70e
Onblur Atom = 0x56d06
Oncancel Atom = 0x11908
Oncanplay Atom = 0x14d09
Oncanplaythrough Atom = 0x14d10
Onchange Atom = 0x41b08
Onclick Atom = 0x2f507
Onclose Atom = 0x36c07
Oncontextmenu Atom = 0x37e0d
Oncopy Atom = 0x39106
Oncuechange Atom = 0x3970b
Oncut Atom = 0x3a205
Ondblclick Atom = 0x3a70a
Ondrag Atom = 0x3b106
Ondragend Atom = 0x3b109
Ondragenter Atom = 0x3ba0b
Ondragexit Atom = 0x3c50a
Ondragleave Atom = 0x3df0b
Ondragover Atom = 0x3ea0a
Ondragstart Atom = 0x3f40b
Ondrop Atom = 0x40306
Ondurationchange Atom = 0x41310
Onemptied Atom = 0x40a09
Onended Atom = 0x42307
Onerror Atom = 0x42a07
Onfocus Atom = 0x43107
Onhashchange Atom = 0x43d0c
Oninput Atom = 0x44907
Oninvalid Atom = 0x45509
Onkeydown Atom = 0x45e09
Onkeypress Atom = 0x46b0a
Onkeyup Atom = 0x48007
Onlanguagechange Atom = 0x48d10
Onload Atom = 0x49d06
Onloadeddata Atom = 0x49d0c
Onloadedmetadata Atom = 0x4b010
Onloadend Atom = 0x4c609
Onloadstart Atom = 0x4cf0b
Onmessage Atom = 0x4da09
Onmessageerror Atom = 0x4da0e
Onmousedown Atom = 0x4e80b
Onmouseenter Atom = 0x4f30c
Onmouseleave Atom = 0x4ff0c
Onmousemove Atom = 0x50b0b
Onmouseout Atom = 0x5160a
Onmouseover Atom = 0x5230b
Onmouseup Atom = 0x52e09
Onmousewheel Atom = 0x53c0c
Onoffline Atom = 0x54809
Ononline Atom = 0x55108
Onpagehide Atom = 0x5590a
Onpageshow Atom = 0x5730a
Onpaste Atom = 0x57f07
Onpause Atom = 0x59a07
Onplay Atom = 0x5a406
Onplaying Atom = 0x5a409
Onpopstate Atom = 0x5ad0a
Onprogress Atom = 0x5b70a
Onratechange Atom = 0x5cc0c
Onrejectionhandled Atom = 0x5d812
Onreset Atom = 0x5ea07
Onresize Atom = 0x5f108
Onscroll Atom = 0x60008
Onsecuritypolicyviolation Atom = 0x60819
Onseeked Atom = 0x62908
Onseeking Atom = 0x63109
Onselect Atom = 0x63a08
Onshow Atom = 0x64406
Onsort Atom = 0x64f06
Onstalled Atom = 0x65909
Onstorage Atom = 0x66209
Onsubmit Atom = 0x66b08
Onsuspend Atom = 0x67b09
Ontimeupdate Atom = 0x400c
Ontoggle Atom = 0x68408
Onunhandledrejection Atom = 0x68c14
Onunload Atom = 0x6ab08
Onvolumechange Atom = 0x6b30e
Onwaiting Atom = 0x6c109
Onwheel Atom = 0x6ca07
Open Atom = 0x1a304
Optgroup Atom = 0x5f08
Optimum Atom = 0x6d107
Option Atom = 0x6e306
Output Atom = 0x51d06
P Atom = 0xc01
Param Atom = 0xc05
Pattern Atom = 0x6607
Picture Atom = 0x7b07
Ping Atom = 0xef04
Placeholder Atom = 0x1310b
Plaintext Atom = 0x1b209
Playsinline Atom = 0x1400b
Poster Atom = 0x2cf06
Pre Atom = 0x47003
Preload Atom = 0x48607
Progress Atom = 0x5b908
Prompt Atom = 0x53606
Public Atom = 0x58606
Q Atom = 0xcf01
Radiogroup Atom = 0x30a
Rb Atom = 0x3a02
Readonly Atom = 0x35708
Referrerpolicy Atom = 0x3d10e
Rel Atom = 0x48703
Required Atom = 0x24c08
Reversed Atom = 0x8008
Rows Atom = 0x9c04
Rowspan Atom = 0x9c07
Rp Atom = 0x23c02
Rt Atom = 0x19a02
Rtc Atom = 0x19a03
Ruby Atom = 0xfb04
S Atom = 0x2501
Samp Atom = 0x7804
Sandbox Atom = 0x12907
Scope Atom = 0x67505
Scoped Atom = 0x67506
Script Atom = 0x21806
Seamless Atom = 0x37108
Section Atom = 0x56807
Select Atom = 0x63c06
Selected Atom = 0x63c08
Shape Atom = 0x1e505
Size Atom = 0x5f504
Sizes Atom = 0x5f505
Slot Atom = 0x1ef04
Small Atom = 0x20605
Sortable Atom = 0x65108
Sorted Atom = 0x33706
Source Atom = 0x37806
Spacer Atom = 0x43706
Span Atom = 0x9f04
Spellcheck Atom = 0x4740a
Src Atom = 0x5c003
Srcdoc Atom = 0x5c006
Srclang Atom = 0x5f907
Srcset Atom = 0x6f906
Start Atom = 0x3fa05
Step Atom = 0x58304
Strike Atom = 0xd206
Strong Atom = 0x6dd06
Style Atom = 0x6ff05
Sub Atom = 0x66d03
Summary Atom = 0x70407
Sup Atom = 0x70b03
Svg Atom = 0x70e03
System Atom = 0x71106
Tabindex Atom = 0x4be08
Table Atom = 0x59505
Target Atom = 0x2c406
Tbody Atom = 0x2705
Td Atom = 0x9202
Template Atom = 0x71408
Textarea Atom = 0x35208
Tfoot Atom = 0xf505
Th Atom = 0x15602
Thead Atom = 0x33005
Time Atom = 0x4204
Title Atom = 0x11005
Tr Atom = 0xcc02
Track Atom = 0x1ba05
Translate Atom = 0x1f209
Tt Atom = 0x6802
Type Atom = 0xd904
Typemustmatch Atom = 0x2900d
U Atom = 0xb01
Ul Atom = 0xa702
Updateviacache Atom = 0x460e
Usemap Atom = 0x59e06
Value Atom = 0x1505
Var Atom = 0x16d03
Video Atom = 0x2f105
Wbr Atom = 0x57c03
Width Atom = 0x64905
Workertype Atom = 0x71c0a
Wrap Atom = 0x72604
Xmp Atom = 0x12f03
)
const hash0 = 0x81cdf10e
const maxAtomLen = 25
var table = [1 << 9]Atom{
0x1: 0xe60a, // mediagroup
0x2: 0x2e404, // lang
0x4: 0x2c09, // accesskey
0x5: 0x8b08, // frameset
0x7: 0x63a08, // onselect
0x8: 0x71106, // system
0xa: 0x64905, // width
0xc: 0x2890b, // formenctype
0xd: 0x13702, // ol
0xe: 0x3970b, // oncuechange
0x10: 0x14b03, // bdo
0x11: 0x11505, // audio
0x12: 0x17a09, // draggable
0x14: 0x2f105, // video
0x15: 0x2b102, // mn
0x16: 0x38704, // menu
0x17: 0x2cf06, // poster
0x19: 0xf606, // footer
0x1a: 0x2a806, // method
0x1b: 0x2b808, // datetime
0x1c: 0x19507, // onabort
0x1d: 0x460e, // updateviacache
0x1e: 0xff05, // async
0x1f: 0x49d06, // onload
0x21: 0x11908, // oncancel
0x22: 0x62908, // onseeked
0x23: 0x30205, // image
0x24: 0x5d812, // onrejectionhandled
0x26: 0x17404, // link
0x27: 0x51d06, // output
0x28: 0x33104, // head
0x29: 0x4ff0c, // onmouseleave
0x2a: 0x57f07, // onpaste
0x2b: 0x5a409, // onplaying
0x2c: 0x1c407, // colspan
0x2f: 0x1bf05, // color
0x30: 0x5f504, // size
0x31: 0x2e80a, // http-equiv
0x33: 0x601, // i
0x34: 0x5590a, // onpagehide
0x35: 0x68c14, // onunhandledrejection
0x37: 0x42a07, // onerror
0x3a: 0x3b08, // basefont
0x3f: 0x1303, // nav
0x40: 0x17704, // kind
0x41: 0x35708, // readonly
0x42: 0x30806, // mglyph
0x44: 0xb202, // li
0x46: 0x2d506, // hidden
0x47: 0x70e03, // svg
0x48: 0x58304, // step
0x49: 0x23f09, // integrity
0x4a: 0x58606, // public
0x4c: 0x1ab03, // col
0x4d: 0x1870a, // blockquote
0x4e: 0x34f02, // h5
0x50: 0x5b908, // progress
0x51: 0x5f505, // sizes
0x52: 0x34502, // h4
0x56: 0x33005, // thead
0x57: 0xd607, // keytype
0x58: 0x5b70a, // onprogress
0x59: 0x44b09, // inputmode
0x5a: 0x3b109, // ondragend
0x5d: 0x3a205, // oncut
0x5e: 0x43706, // spacer
0x5f: 0x1ab08, // colgroup
0x62: 0x16502, // is
0x65: 0x3c02, // as
0x66: 0x54809, // onoffline
0x67: 0x33706, // sorted
0x69: 0x48d10, // onlanguagechange
0x6c: 0x43d0c, // onhashchange
0x6d: 0x9604, // name
0x6e: 0xf505, // tfoot
0x6f: 0x56104, // desc
0x70: 0x33d03, // max
0x72: 0x1ea06, // coords
0x73: 0x30d02, // h3
0x74: 0x6e70e, // onbeforeunload
0x75: 0x9c04, // rows
0x76: 0x63c06, // select
0x77: 0x9805, // meter
0x78: 0x38b06, // itemid
0x79: 0x53c0c, // onmousewheel
0x7a: 0x5c006, // srcdoc
0x7d: 0x1ba05, // track
0x7f: 0x31f08, // itemtype
0x82: 0xa402, // mo
0x83: 0x41b08, // onchange
0x84: 0x33107, // headers
0x85: 0x5cc0c, // onratechange
0x86: 0x60819, // onsecuritypolicyviolation
0x88: 0x4a508, // datalist
0x89: 0x4e80b, // onmousedown
0x8a: 0x1ef04, // slot
0x8b: 0x4b010, // onloadedmetadata
0x8c: 0x1a06, // accept
0x8d: 0x26806, // object
0x91: 0x6b30e, // onvolumechange
0x92: 0x2107, // charset
0x93: 0x27613, // onautocompleteerror
0x94: 0xc113, // allowpaymentrequest
0x95: 0x2804, // body
0x96: 0x10a07, // default
0x97: 0x63c08, // selected
0x98: 0x21e04, // face
0x99: 0x1e505, // shape
0x9b: 0x68408, // ontoggle
0x9e: 0x64b02, // dt
0x9f: 0xb604, // mark
0xa1: 0xb01, // u
0xa4: 0x6ab08, // onunload
0xa5: 0x5d04, // loop
0xa6: 0x16408, // disabled
0xaa: 0x42307, // onended
0xab: 0xb00a, // malignmark
0xad: 0x67b09, // onsuspend
0xae: 0x35105, // mtext
0xaf: 0x64f06, // onsort
0xb0: 0x19d08, // itemprop
0xb3: 0x67109, // itemscope
0xb4: 0x17305, // blink
0xb6: 0x3b106, // ondrag
0xb7: 0xa702, // ul
0xb8: 0x26e04, // form
0xb9: 0x12907, // sandbox
0xba: 0x8b05, // frame
0xbb: 0x1505, // value
0xbc: 0x66209, // onstorage
0xbf: 0xaa07, // acronym
0xc0: 0x19a02, // rt
0xc2: 0x202, // br
0xc3: 0x22608, // fieldset
0xc4: 0x2900d, // typemustmatch
0xc5: 0xa208, // nomodule
0xc6: 0x6c07, // noembed
0xc7: 0x69e0d, // onbeforeprint
0xc8: 0x19106, // button
0xc9: 0x2f507, // onclick
0xca: 0x70407, // summary
0xcd: 0xfb04, // ruby
0xce: 0x56405, // class
0xcf: 0x3f40b, // ondragstart
0xd0: 0x23107, // caption
0xd4: 0xdd0e, // allowusermedia
0xd5: 0x4cf0b, // onloadstart
0xd9: 0x16b03, // div
0xda: 0x4a904, // list
0xdb: 0x32e04, // math
0xdc: 0x44b05, // input
0xdf: 0x3ea0a, // ondragover
0xe0: 0x2de02, // h2
0xe2: 0x1b209, // plaintext
0xe4: 0x4f30c, // onmouseenter
0xe7: 0x47907, // checked
0xe8: 0x47003, // pre
0xea: 0x35f08, // multiple
0xeb: 0xba03, // bdi
0xec: 0x33d09, // maxlength
0xed: 0xcf01, // q
0xee: 0x61f0a, // onauxclick
0xf0: 0x57c03, // wbr
0xf2: 0x3b04, // base
0xf3: 0x6e306, // option
0xf5: 0x41310, // ondurationchange
0xf7: 0x8908, // noframes
0xf9: 0x40508, // dropzone
0xfb: 0x67505, // scope
0xfc: 0x8008, // reversed
0xfd: 0x3ba0b, // ondragenter
0xfe: 0x3fa05, // start
0xff: 0x12f03, // xmp
0x100: 0x5f907, // srclang
0x101: 0x30703, // img
0x104: 0x101, // b
0x105: 0x25403, // for
0x106: 0x10705, // aside
0x107: 0x44907, // oninput
0x108: 0x35604, // area
0x109: 0x2a40a, // formmethod
0x10a: 0x72604, // wrap
0x10c: 0x23c02, // rp
0x10d: 0x46b0a, // onkeypress
0x10e: 0x6802, // tt
0x110: 0x34702, // mi
0x111: 0x36705, // muted
0x112: 0xf303, // alt
0x113: 0x5c504, // code
0x114: 0x6e02, // em
0x115: 0x3c50a, // ondragexit
0x117: 0x9f04, // span
0x119: 0x6d708, // manifest
0x11a: 0x38708, // menuitem
0x11b: 0x58b07, // content
0x11d: 0x6c109, // onwaiting
0x11f: 0x4c609, // onloadend
0x121: 0x37e0d, // oncontextmenu
0x123: 0x56d06, // onblur
0x124: 0x3fc07, // article
0x125: 0x9303, // dir
0x126: 0xef04, // ping
0x127: 0x24c08, // required
0x128: 0x45509, // oninvalid
0x129: 0xb105, // align
0x12b: 0x58a04, // icon
0x12c: 0x64d02, // h6
0x12d: 0x1c404, // cols
0x12e: 0x22e0a, // figcaption
0x12f: 0x45e09, // onkeydown
0x130: 0x66b08, // onsubmit
0x131: 0x14d09, // oncanplay
0x132: 0x70b03, // sup
0x133: 0xc01, // p
0x135: 0x40a09, // onemptied
0x136: 0x39106, // oncopy
0x137: 0x19c04, // cite
0x138: 0x3a70a, // ondblclick
0x13a: 0x50b0b, // onmousemove
0x13c: 0x66d03, // sub
0x13d: 0x48703, // rel
0x13e: 0x5f08, // optgroup
0x142: 0x9c07, // rowspan
0x143: 0x37806, // source
0x144: 0x21608, // noscript
0x145: 0x1a304, // open
0x146: 0x20403, // ins
0x147: 0x2540d, // foreignObject
0x148: 0x5ad0a, // onpopstate
0x14a: 0x28d07, // enctype
0x14b: 0x2760e, // onautocomplete
0x14c: 0x35208, // textarea
0x14e: 0x2780c, // autocomplete
0x14f: 0x15702, // hr
0x150: 0x1de08, // controls
0x151: 0x10902, // id
0x153: 0x2360c, // onafterprint
0x155: 0x2610d, // foreignobject
0x156: 0x32707, // marquee
0x157: 0x59a07, // onpause
0x158: 0x5e602, // dl
0x159: 0x5206, // height
0x15a: 0x34703, // min
0x15b: 0x9307, // dirname
0x15c: 0x1f209, // translate
0x15d: 0x5604, // html
0x15e: 0x34709, // minlength
0x15f: 0x48607, // preload
0x160: 0x71408, // template
0x161: 0x3df0b, // ondragleave
0x162: 0x3a02, // rb
0x164: 0x5c003, // src
0x165: 0x6dd06, // strong
0x167: 0x7804, // samp
0x168: 0x6f307, // address
0x169: 0x55108, // ononline
0x16b: 0x1310b, // placeholder
0x16c: 0x2c406, // target
0x16d: 0x20605, // small
0x16e: 0x6ca07, // onwheel
0x16f: 0x1c90a, // annotation
0x170: 0x4740a, // spellcheck
0x171: 0x7207, // details
0x172: 0x10306, // canvas
0x173: 0x12109, // autofocus
0x174: 0xc05, // param
0x176: 0x46308, // download
0x177: 0x45203, // del
0x178: 0x36c07, // onclose
0x179: 0xb903, // kbd
0x17a: 0x31906, // applet
0x17b: 0x2e004, // href
0x17c: 0x5f108, // onresize
0x17e: 0x49d0c, // onloadeddata
0x180: 0xcc02, // tr
0x181: 0x2c00a, // formtarget
0x182: 0x11005, // title
0x183: 0x6ff05, // style
0x184: 0xd206, // strike
0x185: 0x59e06, // usemap
0x186: 0x2fc06, // iframe
0x187: 0x1004, // main
0x189: 0x7b07, // picture
0x18c: 0x31605, // ismap
0x18e: 0x4a504, // data
0x18f: 0x5905, // label
0x191: 0x3d10e, // referrerpolicy
0x192: 0x15602, // th
0x194: 0x53606, // prompt
0x195: 0x56807, // section
0x197: 0x6d107, // optimum
0x198: 0x2db04, // high
0x199: 0x15c02, // h1
0x19a: 0x65909, // onstalled
0x19b: 0x16d03, // var
0x19c: 0x4204, // time
0x19e: 0x67402, // ms
0x19f: 0x33106, // header
0x1a0: 0x4da09, // onmessage
0x1a1: 0x1a605, // nonce
0x1a2: 0x26e0a, // formaction
0x1a3: 0x22006, // center
0x1a4: 0x3704, // nobr
0x1a5: 0x59505, // table
0x1a6: 0x4a907, // listing
0x1a7: 0x18106, // legend
0x1a9: 0x29b09, // challenge
0x1aa: 0x24806, // figure
0x1ab: 0xe605, // media
0x1ae: 0xd904, // type
0x1af: 0x3f04, // font
0x1b0: 0x4da0e, // onmessageerror
0x1b1: 0x37108, // seamless
0x1b2: 0x8703, // dfn
0x1b3: 0x5c705, // defer
0x1b4: 0xc303, // low
0x1b5: 0x19a03, // rtc
0x1b6: 0x5230b, // onmouseover
0x1b7: 0x2b20a, // novalidate
0x1b8: 0x71c0a, // workertype
0x1ba: 0x3cd07, // itemref
0x1bd: 0x1, // a
0x1be: 0x31803, // map
0x1bf: 0x400c, // ontimeupdate
0x1c0: 0x15e07, // bgsound
0x1c1: 0x3206, // keygen
0x1c2: 0x2705, // tbody
0x1c5: 0x64406, // onshow
0x1c7: 0x2501, // s
0x1c8: 0x6607, // pattern
0x1cc: 0x14d10, // oncanplaythrough
0x1ce: 0x2d702, // dd
0x1cf: 0x6f906, // srcset
0x1d0: 0x17003, // big
0x1d2: 0x65108, // sortable
0x1d3: 0x48007, // onkeyup
0x1d5: 0x5a406, // onplay
0x1d7: 0x4b804, // meta
0x1d8: 0x40306, // ondrop
0x1da: 0x60008, // onscroll
0x1db: 0x1fb0b, // crossorigin
0x1dc: 0x5730a, // onpageshow
0x1dd: 0x4, // abbr
0x1de: 0x9202, // td
0x1df: 0x58b0f, // contenteditable
0x1e0: 0x27206, // action
0x1e1: 0x1400b, // playsinline
0x1e2: 0x43107, // onfocus
0x1e3: 0x2e008, // hreflang
0x1e5: 0x5160a, // onmouseout
0x1e6: 0x5ea07, // onreset
0x1e7: 0x13c08, // autoplay
0x1e8: 0x63109, // onseeking
0x1ea: 0x67506, // scoped
0x1ec: 0x30a, // radiogroup
0x1ee: 0x3800b, // contextmenu
0x1ef: 0x52e09, // onmouseup
0x1f1: 0x2ca06, // hgroup
0x1f2: 0x2080f, // allowfullscreen
0x1f3: 0x4be08, // tabindex
0x1f6: 0x30f07, // isindex
0x1f7: 0x1a0e, // accept-charset
0x1f8: 0x2ae0e, // formnovalidate
0x1fb: 0x1c90e, // annotation-xml
0x1fc: 0x6e05, // embed
0x1fd: 0x21806, // script
0x1fe: 0xbb06, // dialog
0x1ff: 0x1d707, // command
}
const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" +
"asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" +
"sampictureversedfnoframesetdirnameterowspanomoduleacronymali" +
"gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" +
"ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" +
"dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" +
"bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" +
"penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" +
"ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" +
"ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" +
"ignObjectforeignobjectformactionautocompleteerrorformenctype" +
"mustmatchallengeformmethodformnovalidatetimeformtargethgroup" +
"osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" +
"ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" +
"inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" +
"extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" +
"enterondragexitemreferrerpolicyondragleaveondragoverondragst" +
"articleondropzonemptiedondurationchangeonendedonerroronfocus" +
"paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" +
"spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" +
"onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" +
"usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" +
"seoveronmouseupromptonmousewheelonofflineononlineonpagehides" +
"classectionbluronpageshowbronpastepublicontenteditableonpaus" +
"emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" +
"jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" +
"violationauxclickonseekedonseekingonselectedonshowidth6onsor" +
"tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" +
"handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" +
"wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" +
"arysupsvgsystemplateworkertypewrap"

111
vendor/golang.org/x/net/html/const.go generated vendored Normal file
View File

@@ -0,0 +1,111 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
// Section 12.2.4.2 of the HTML5 specification says "The following elements
// have varying levels of special parsing rules".
// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
var isSpecialElementMap = map[string]bool{
"address": true,
"applet": true,
"area": true,
"article": true,
"aside": true,
"base": true,
"basefont": true,
"bgsound": true,
"blockquote": true,
"body": true,
"br": true,
"button": true,
"caption": true,
"center": true,
"col": true,
"colgroup": true,
"dd": true,
"details": true,
"dir": true,
"div": true,
"dl": true,
"dt": true,
"embed": true,
"fieldset": true,
"figcaption": true,
"figure": true,
"footer": true,
"form": true,
"frame": true,
"frameset": true,
"h1": true,
"h2": true,
"h3": true,
"h4": true,
"h5": true,
"h6": true,
"head": true,
"header": true,
"hgroup": true,
"hr": true,
"html": true,
"iframe": true,
"img": true,
"input": true,
"keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility.
"li": true,
"link": true,
"listing": true,
"main": true,
"marquee": true,
"menu": true,
"meta": true,
"nav": true,
"noembed": true,
"noframes": true,
"noscript": true,
"object": true,
"ol": true,
"p": true,
"param": true,
"plaintext": true,
"pre": true,
"script": true,
"section": true,
"select": true,
"source": true,
"style": true,
"summary": true,
"table": true,
"tbody": true,
"td": true,
"template": true,
"textarea": true,
"tfoot": true,
"th": true,
"thead": true,
"title": true,
"tr": true,
"track": true,
"ul": true,
"wbr": true,
"xmp": true,
}
func isSpecialElement(element *Node) bool {
switch element.Namespace {
case "", "html":
return isSpecialElementMap[element.Data]
case "math":
switch element.Data {
case "mi", "mo", "mn", "ms", "mtext", "annotation-xml":
return true
}
case "svg":
switch element.Data {
case "foreignObject", "desc", "title":
return true
}
}
return false
}

106
vendor/golang.org/x/net/html/doc.go generated vendored Normal file
View File

@@ -0,0 +1,106 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package html implements an HTML5-compliant tokenizer and parser.
Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
caller's responsibility to ensure that r provides UTF-8 encoded HTML.
z := html.NewTokenizer(r)
Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
which parses the next token and returns its type, or an error:
for {
tt := z.Next()
if tt == html.ErrorToken {
// ...
return ...
}
// Process the current token.
}
There are two APIs for retrieving the current token. The high-level API is to
call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
allow optionally calling Raw after Next but before Token, Text, TagName, or
TagAttr. In EBNF notation, the valid call sequence per token is:
Next {Raw} [ Token | Text | TagName {TagAttr} ]
Token returns an independent data structure that completely describes a token.
Entities (such as "&lt;") are unescaped, tag names and attribute keys are
lower-cased, and attributes are collected into a []Attribute. For example:
for {
if z.Next() == html.ErrorToken {
// Returning io.EOF indicates success.
return z.Err()
}
emitToken(z.Token())
}
The low-level API performs fewer allocations and copies, but the contents of
the []byte values returned by Text, TagName and TagAttr may change on the next
call to Next. For example, to extract an HTML page's anchor text:
depth := 0
for {
tt := z.Next()
switch tt {
case html.ErrorToken:
return z.Err()
case html.TextToken:
if depth > 0 {
// emitBytes should copy the []byte it receives,
// if it doesn't process it immediately.
emitBytes(z.Text())
}
case html.StartTagToken, html.EndTagToken:
tn, _ := z.TagName()
if len(tn) == 1 && tn[0] == 'a' {
if tt == html.StartTagToken {
depth++
} else {
depth--
}
}
}
}
Parsing is done by calling Parse with an io.Reader, which returns the root of
the parse tree (the document element) as a *Node. It is the caller's
responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
example, to process each anchor node in depth-first order:
doc, err := html.Parse(r)
if err != nil {
// ...
}
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a" {
// Do something with n...
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
The relevant specifications include:
https://html.spec.whatwg.org/multipage/syntax.html and
https://html.spec.whatwg.org/multipage/syntax.html#tokenization
*/
package html // import "golang.org/x/net/html"
// The tokenization algorithm implemented by this package is not a line-by-line
// transliteration of the relatively verbose state-machine in the WHATWG
// specification. A more direct approach is used instead, where the program
// counter implies the state, such as whether it is tokenizing a tag or a text
// node. Specification compliance is verified by checking expected and actual
// outputs over a test suite rather than aiming for algorithmic fidelity.
// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
// TODO(nigeltao): How does parsing interact with a JavaScript engine?

156
vendor/golang.org/x/net/html/doctype.go generated vendored Normal file
View File

@@ -0,0 +1,156 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
import (
"strings"
)
// parseDoctype parses the data from a DoctypeToken into a name,
// public identifier, and system identifier. It returns a Node whose Type
// is DoctypeNode, whose Data is the name, and which has attributes
// named "system" and "public" for the two identifiers if they were present.
// quirks is whether the document should be parsed in "quirks mode".
func parseDoctype(s string) (n *Node, quirks bool) {
n = &Node{Type: DoctypeNode}
// Find the name.
space := strings.IndexAny(s, whitespace)
if space == -1 {
space = len(s)
}
n.Data = s[:space]
// The comparison to "html" is case-sensitive.
if n.Data != "html" {
quirks = true
}
n.Data = strings.ToLower(n.Data)
s = strings.TrimLeft(s[space:], whitespace)
if len(s) < 6 {
// It can't start with "PUBLIC" or "SYSTEM".
// Ignore the rest of the string.
return n, quirks || s != ""
}
key := strings.ToLower(s[:6])
s = s[6:]
for key == "public" || key == "system" {
s = strings.TrimLeft(s, whitespace)
if s == "" {
break
}
quote := s[0]
if quote != '"' && quote != '\'' {
break
}
s = s[1:]
q := strings.IndexRune(s, rune(quote))
var id string
if q == -1 {
id = s
s = ""
} else {
id = s[:q]
s = s[q+1:]
}
n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
if key == "public" {
key = "system"
} else {
key = ""
}
}
if key != "" || s != "" {
quirks = true
} else if len(n.Attr) > 0 {
if n.Attr[0].Key == "public" {
public := strings.ToLower(n.Attr[0].Val)
switch public {
case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
quirks = true
default:
for _, q := range quirkyIDs {
if strings.HasPrefix(public, q) {
quirks = true
break
}
}
}
// The following two public IDs only cause quirks mode if there is no system ID.
if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
quirks = true
}
}
if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
quirks = true
}
}
return n, quirks
}
// quirkyIDs is a list of public doctype identifiers that cause a document
// to be interpreted in quirks mode. The identifiers should be in lower case.
var quirkyIDs = []string{
"+//silmaril//dtd html pro v0r11 19970101//",
"-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
"-//as//dtd html 3.0 aswedit + extensions//",
"-//ietf//dtd html 2.0 level 1//",
"-//ietf//dtd html 2.0 level 2//",
"-//ietf//dtd html 2.0 strict level 1//",
"-//ietf//dtd html 2.0 strict level 2//",
"-//ietf//dtd html 2.0 strict//",
"-//ietf//dtd html 2.0//",
"-//ietf//dtd html 2.1e//",
"-//ietf//dtd html 3.0//",
"-//ietf//dtd html 3.2 final//",
"-//ietf//dtd html 3.2//",
"-//ietf//dtd html 3//",
"-//ietf//dtd html level 0//",
"-//ietf//dtd html level 1//",
"-//ietf//dtd html level 2//",
"-//ietf//dtd html level 3//",
"-//ietf//dtd html strict level 0//",
"-//ietf//dtd html strict level 1//",
"-//ietf//dtd html strict level 2//",
"-//ietf//dtd html strict level 3//",
"-//ietf//dtd html strict//",
"-//ietf//dtd html//",
"-//metrius//dtd metrius presentational//",
"-//microsoft//dtd internet explorer 2.0 html strict//",
"-//microsoft//dtd internet explorer 2.0 html//",
"-//microsoft//dtd internet explorer 2.0 tables//",
"-//microsoft//dtd internet explorer 3.0 html strict//",
"-//microsoft//dtd internet explorer 3.0 html//",
"-//microsoft//dtd internet explorer 3.0 tables//",
"-//netscape comm. corp.//dtd html//",
"-//netscape comm. corp.//dtd strict html//",
"-//o'reilly and associates//dtd html 2.0//",
"-//o'reilly and associates//dtd html extended 1.0//",
"-//o'reilly and associates//dtd html extended relaxed 1.0//",
"-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
"-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
"-//spyglass//dtd html 2.0 extended//",
"-//sq//dtd html 2.0 hotmetal + extensions//",
"-//sun microsystems corp.//dtd hotjava html//",
"-//sun microsystems corp.//dtd hotjava strict html//",
"-//w3c//dtd html 3 1995-03-24//",
"-//w3c//dtd html 3.2 draft//",
"-//w3c//dtd html 3.2 final//",
"-//w3c//dtd html 3.2//",
"-//w3c//dtd html 3.2s draft//",
"-//w3c//dtd html 4.0 frameset//",
"-//w3c//dtd html 4.0 transitional//",
"-//w3c//dtd html experimental 19960712//",
"-//w3c//dtd html experimental 970421//",
"-//w3c//dtd w3 html//",
"-//w3o//dtd w3 html 3.0//",
"-//webtechs//dtd mozilla html 2.0//",
"-//webtechs//dtd mozilla html//",
}

2253
vendor/golang.org/x/net/html/entity.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

258
vendor/golang.org/x/net/html/escape.go generated vendored Normal file
View File

@@ -0,0 +1,258 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
import (
"bytes"
"strings"
"unicode/utf8"
)
// These replacements permit compatibility with old numeric entities that
// assumed Windows-1252 encoding.
// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
var replacementTable = [...]rune{
'\u20AC', // First entry is what 0x80 should be replaced with.
'\u0081',
'\u201A',
'\u0192',
'\u201E',
'\u2026',
'\u2020',
'\u2021',
'\u02C6',
'\u2030',
'\u0160',
'\u2039',
'\u0152',
'\u008D',
'\u017D',
'\u008F',
'\u0090',
'\u2018',
'\u2019',
'\u201C',
'\u201D',
'\u2022',
'\u2013',
'\u2014',
'\u02DC',
'\u2122',
'\u0161',
'\u203A',
'\u0153',
'\u009D',
'\u017E',
'\u0178', // Last entry is 0x9F.
// 0x00->'\uFFFD' is handled programmatically.
// 0x0D->'\u000D' is a no-op.
}
// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
// Precondition: b[src] == '&' && dst <= src.
// attribute should be true if parsing an attribute value.
func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
// i starts at 1 because we already know that s[0] == '&'.
i, s := 1, b[src:]
if len(s) <= 1 {
b[dst] = b[src]
return dst + 1, src + 1
}
if s[i] == '#' {
if len(s) <= 3 { // We need to have at least "&#.".
b[dst] = b[src]
return dst + 1, src + 1
}
i++
c := s[i]
hex := false
if c == 'x' || c == 'X' {
hex = true
i++
}
x := '\x00'
for i < len(s) {
c = s[i]
i++
if hex {
if '0' <= c && c <= '9' {
x = 16*x + rune(c) - '0'
continue
} else if 'a' <= c && c <= 'f' {
x = 16*x + rune(c) - 'a' + 10
continue
} else if 'A' <= c && c <= 'F' {
x = 16*x + rune(c) - 'A' + 10
continue
}
} else if '0' <= c && c <= '9' {
x = 10*x + rune(c) - '0'
continue
}
if c != ';' {
i--
}
break
}
if i <= 3 { // No characters matched.
b[dst] = b[src]
return dst + 1, src + 1
}
if 0x80 <= x && x <= 0x9F {
// Replace characters from Windows-1252 with UTF-8 equivalents.
x = replacementTable[x-0x80]
} else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
// Replace invalid characters with the replacement character.
x = '\uFFFD'
}
return dst + utf8.EncodeRune(b[dst:], x), src + i
}
// Consume the maximum number of characters possible, with the
// consumed characters matching one of the named references.
for i < len(s) {
c := s[i]
i++
// Lower-cased characters are more common in entities, so we check for them first.
if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
continue
}
if c != ';' {
i--
}
break
}
entityName := string(s[1:i])
if entityName == "" {
// No-op.
} else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
// No-op.
} else if x := entity[entityName]; x != 0 {
return dst + utf8.EncodeRune(b[dst:], x), src + i
} else if x := entity2[entityName]; x[0] != 0 {
dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
} else if !attribute {
maxLen := len(entityName) - 1
if maxLen > longestEntityWithoutSemicolon {
maxLen = longestEntityWithoutSemicolon
}
for j := maxLen; j > 1; j-- {
if x := entity[entityName[:j]]; x != 0 {
return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
}
}
}
dst1, src1 = dst+i, src+i
copy(b[dst:dst1], b[src:src1])
return dst1, src1
}
// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
// attribute should be true if parsing an attribute value.
func unescape(b []byte, attribute bool) []byte {
for i, c := range b {
if c == '&' {
dst, src := unescapeEntity(b, i, i, attribute)
for src < len(b) {
c := b[src]
if c == '&' {
dst, src = unescapeEntity(b, dst, src, attribute)
} else {
b[dst] = c
dst, src = dst+1, src+1
}
}
return b[0:dst]
}
}
return b
}
// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
func lower(b []byte) []byte {
for i, c := range b {
if 'A' <= c && c <= 'Z' {
b[i] = c + 'a' - 'A'
}
}
return b
}
const escapedChars = "&'<>\"\r"
func escape(w writer, s string) error {
i := strings.IndexAny(s, escapedChars)
for i != -1 {
if _, err := w.WriteString(s[:i]); err != nil {
return err
}
var esc string
switch s[i] {
case '&':
esc = "&amp;"
case '\'':
// "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
esc = "&#39;"
case '<':
esc = "&lt;"
case '>':
esc = "&gt;"
case '"':
// "&#34;" is shorter than "&quot;".
esc = "&#34;"
case '\r':
esc = "&#13;"
default:
panic("unrecognized escape character")
}
s = s[i+1:]
if _, err := w.WriteString(esc); err != nil {
return err
}
i = strings.IndexAny(s, escapedChars)
}
_, err := w.WriteString(s)
return err
}
// EscapeString escapes special characters like "<" to become "&lt;". It
// escapes only five such characters: <, >, &, ' and ".
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
// always true.
func EscapeString(s string) string {
if strings.IndexAny(s, escapedChars) == -1 {
return s
}
var buf bytes.Buffer
escape(&buf, s)
return buf.String()
}
// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
// larger range of entities than EscapeString escapes. For example, "&aacute;"
// unescapes to "á", as does "&#225;" and "&xE1;".
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
// always true.
func UnescapeString(s string) string {
for _, c := range s {
if c == '&' {
return string(unescape([]byte(s), false))
}
}
return s
}

222
vendor/golang.org/x/net/html/foreign.go generated vendored Normal file
View File

@@ -0,0 +1,222 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
import (
"strings"
)
func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
for i := range aa {
if newName, ok := nameMap[aa[i].Key]; ok {
aa[i].Key = newName
}
}
}
func adjustForeignAttributes(aa []Attribute) {
for i, a := range aa {
if a.Key == "" || a.Key[0] != 'x' {
continue
}
switch a.Key {
case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
"xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
j := strings.Index(a.Key, ":")
aa[i].Namespace = a.Key[:j]
aa[i].Key = a.Key[j+1:]
}
}
}
func htmlIntegrationPoint(n *Node) bool {
if n.Type != ElementNode {
return false
}
switch n.Namespace {
case "math":
if n.Data == "annotation-xml" {
for _, a := range n.Attr {
if a.Key == "encoding" {
val := strings.ToLower(a.Val)
if val == "text/html" || val == "application/xhtml+xml" {
return true
}
}
}
}
case "svg":
switch n.Data {
case "desc", "foreignObject", "title":
return true
}
}
return false
}
func mathMLTextIntegrationPoint(n *Node) bool {
if n.Namespace != "math" {
return false
}
switch n.Data {
case "mi", "mo", "mn", "ms", "mtext":
return true
}
return false
}
// Section 12.2.6.5.
var breakout = map[string]bool{
"b": true,
"big": true,
"blockquote": true,
"body": true,
"br": true,
"center": true,
"code": true,
"dd": true,
"div": true,
"dl": true,
"dt": true,
"em": true,
"embed": true,
"h1": true,
"h2": true,
"h3": true,
"h4": true,
"h5": true,
"h6": true,
"head": true,
"hr": true,
"i": true,
"img": true,
"li": true,
"listing": true,
"menu": true,
"meta": true,
"nobr": true,
"ol": true,
"p": true,
"pre": true,
"ruby": true,
"s": true,
"small": true,
"span": true,
"strong": true,
"strike": true,
"sub": true,
"sup": true,
"table": true,
"tt": true,
"u": true,
"ul": true,
"var": true,
}
// Section 12.2.6.5.
var svgTagNameAdjustments = map[string]string{
"altglyph": "altGlyph",
"altglyphdef": "altGlyphDef",
"altglyphitem": "altGlyphItem",
"animatecolor": "animateColor",
"animatemotion": "animateMotion",
"animatetransform": "animateTransform",
"clippath": "clipPath",
"feblend": "feBlend",
"fecolormatrix": "feColorMatrix",
"fecomponenttransfer": "feComponentTransfer",
"fecomposite": "feComposite",
"feconvolvematrix": "feConvolveMatrix",
"fediffuselighting": "feDiffuseLighting",
"fedisplacementmap": "feDisplacementMap",
"fedistantlight": "feDistantLight",
"feflood": "feFlood",
"fefunca": "feFuncA",
"fefuncb": "feFuncB",
"fefuncg": "feFuncG",
"fefuncr": "feFuncR",
"fegaussianblur": "feGaussianBlur",
"feimage": "feImage",
"femerge": "feMerge",
"femergenode": "feMergeNode",
"femorphology": "feMorphology",
"feoffset": "feOffset",
"fepointlight": "fePointLight",
"fespecularlighting": "feSpecularLighting",
"fespotlight": "feSpotLight",
"fetile": "feTile",
"feturbulence": "feTurbulence",
"foreignobject": "foreignObject",
"glyphref": "glyphRef",
"lineargradient": "linearGradient",
"radialgradient": "radialGradient",
"textpath": "textPath",
}
// Section 12.2.6.1
var mathMLAttributeAdjustments = map[string]string{
"definitionurl": "definitionURL",
}
var svgAttributeAdjustments = map[string]string{
"attributename": "attributeName",
"attributetype": "attributeType",
"basefrequency": "baseFrequency",
"baseprofile": "baseProfile",
"calcmode": "calcMode",
"clippathunits": "clipPathUnits",
"diffuseconstant": "diffuseConstant",
"edgemode": "edgeMode",
"filterunits": "filterUnits",
"glyphref": "glyphRef",
"gradienttransform": "gradientTransform",
"gradientunits": "gradientUnits",
"kernelmatrix": "kernelMatrix",
"kernelunitlength": "kernelUnitLength",
"keypoints": "keyPoints",
"keysplines": "keySplines",
"keytimes": "keyTimes",
"lengthadjust": "lengthAdjust",
"limitingconeangle": "limitingConeAngle",
"markerheight": "markerHeight",
"markerunits": "markerUnits",
"markerwidth": "markerWidth",
"maskcontentunits": "maskContentUnits",
"maskunits": "maskUnits",
"numoctaves": "numOctaves",
"pathlength": "pathLength",
"patterncontentunits": "patternContentUnits",
"patterntransform": "patternTransform",
"patternunits": "patternUnits",
"pointsatx": "pointsAtX",
"pointsaty": "pointsAtY",
"pointsatz": "pointsAtZ",
"preservealpha": "preserveAlpha",
"preserveaspectratio": "preserveAspectRatio",
"primitiveunits": "primitiveUnits",
"refx": "refX",
"refy": "refY",
"repeatcount": "repeatCount",
"repeatdur": "repeatDur",
"requiredextensions": "requiredExtensions",
"requiredfeatures": "requiredFeatures",
"specularconstant": "specularConstant",
"specularexponent": "specularExponent",
"spreadmethod": "spreadMethod",
"startoffset": "startOffset",
"stddeviation": "stdDeviation",
"stitchtiles": "stitchTiles",
"surfacescale": "surfaceScale",
"systemlanguage": "systemLanguage",
"tablevalues": "tableValues",
"targetx": "targetX",
"targety": "targetY",
"textlength": "textLength",
"viewbox": "viewBox",
"viewtarget": "viewTarget",
"xchannelselector": "xChannelSelector",
"ychannelselector": "yChannelSelector",
"zoomandpan": "zoomAndPan",
}

225
vendor/golang.org/x/net/html/node.go generated vendored Normal file
View File

@@ -0,0 +1,225 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
import (
"golang.org/x/net/html/atom"
)
// A NodeType is the type of a Node.
type NodeType uint32
const (
ErrorNode NodeType = iota
TextNode
DocumentNode
ElementNode
CommentNode
DoctypeNode
// RawNode nodes are not returned by the parser, but can be part of the
// Node tree passed to func Render to insert raw HTML (without escaping).
// If so, this package makes no guarantee that the rendered HTML is secure
// (from e.g. Cross Site Scripting attacks) or well-formed.
RawNode
scopeMarkerNode
)
// Section 12.2.4.3 says "The markers are inserted when entering applet,
// object, marquee, template, td, th, and caption elements, and are used
// to prevent formatting from "leaking" into applet, object, marquee,
// template, td, th, and caption elements".
var scopeMarker = Node{Type: scopeMarkerNode}
// A Node consists of a NodeType and some Data (tag name for element nodes,
// content for text) and are part of a tree of Nodes. Element nodes may also
// have a Namespace and contain a slice of Attributes. Data is unescaped, so
// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
// is the atom for Data, or zero if Data is not a known tag name.
//
// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
// "svg" is short for "http://www.w3.org/2000/svg".
type Node struct {
Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
Type NodeType
DataAtom atom.Atom
Data string
Namespace string
Attr []Attribute
}
// InsertBefore inserts newChild as a child of n, immediately before oldChild
// in the sequence of n's children. oldChild may be nil, in which case newChild
// is appended to the end of n's children.
//
// It will panic if newChild already has a parent or siblings.
func (n *Node) InsertBefore(newChild, oldChild *Node) {
if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
panic("html: InsertBefore called for an attached child Node")
}
var prev, next *Node
if oldChild != nil {
prev, next = oldChild.PrevSibling, oldChild
} else {
prev = n.LastChild
}
if prev != nil {
prev.NextSibling = newChild
} else {
n.FirstChild = newChild
}
if next != nil {
next.PrevSibling = newChild
} else {
n.LastChild = newChild
}
newChild.Parent = n
newChild.PrevSibling = prev
newChild.NextSibling = next
}
// AppendChild adds a node c as a child of n.
//
// It will panic if c already has a parent or siblings.
func (n *Node) AppendChild(c *Node) {
if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
panic("html: AppendChild called for an attached child Node")
}
last := n.LastChild
if last != nil {
last.NextSibling = c
} else {
n.FirstChild = c
}
n.LastChild = c
c.Parent = n
c.PrevSibling = last
}
// RemoveChild removes a node c that is a child of n. Afterwards, c will have
// no parent and no siblings.
//
// It will panic if c's parent is not n.
func (n *Node) RemoveChild(c *Node) {
if c.Parent != n {
panic("html: RemoveChild called for a non-child Node")
}
if n.FirstChild == c {
n.FirstChild = c.NextSibling
}
if c.NextSibling != nil {
c.NextSibling.PrevSibling = c.PrevSibling
}
if n.LastChild == c {
n.LastChild = c.PrevSibling
}
if c.PrevSibling != nil {
c.PrevSibling.NextSibling = c.NextSibling
}
c.Parent = nil
c.PrevSibling = nil
c.NextSibling = nil
}
// reparentChildren reparents all of src's child nodes to dst.
func reparentChildren(dst, src *Node) {
for {
child := src.FirstChild
if child == nil {
break
}
src.RemoveChild(child)
dst.AppendChild(child)
}
}
// clone returns a new node with the same type, data and attributes.
// The clone has no parent, no siblings and no children.
func (n *Node) clone() *Node {
m := &Node{
Type: n.Type,
DataAtom: n.DataAtom,
Data: n.Data,
Attr: make([]Attribute, len(n.Attr)),
}
copy(m.Attr, n.Attr)
return m
}
// nodeStack is a stack of nodes.
type nodeStack []*Node
// pop pops the stack. It will panic if s is empty.
func (s *nodeStack) pop() *Node {
i := len(*s)
n := (*s)[i-1]
*s = (*s)[:i-1]
return n
}
// top returns the most recently pushed node, or nil if s is empty.
func (s *nodeStack) top() *Node {
if i := len(*s); i > 0 {
return (*s)[i-1]
}
return nil
}
// index returns the index of the top-most occurrence of n in the stack, or -1
// if n is not present.
func (s *nodeStack) index(n *Node) int {
for i := len(*s) - 1; i >= 0; i-- {
if (*s)[i] == n {
return i
}
}
return -1
}
// contains returns whether a is within s.
func (s *nodeStack) contains(a atom.Atom) bool {
for _, n := range *s {
if n.DataAtom == a && n.Namespace == "" {
return true
}
}
return false
}
// insert inserts a node at the given index.
func (s *nodeStack) insert(i int, n *Node) {
(*s) = append(*s, nil)
copy((*s)[i+1:], (*s)[i:])
(*s)[i] = n
}
// remove removes a node from the stack. It is a no-op if n is not present.
func (s *nodeStack) remove(n *Node) {
i := s.index(n)
if i == -1 {
return
}
copy((*s)[i:], (*s)[i+1:])
j := len(*s) - 1
(*s)[j] = nil
*s = (*s)[:j]
}
type insertionModeStack []insertionMode
func (s *insertionModeStack) pop() (im insertionMode) {
i := len(*s)
im = (*s)[i-1]
*s = (*s)[:i-1]
return im
}
func (s *insertionModeStack) top() insertionMode {
if i := len(*s); i > 0 {
return (*s)[i-1]
}
return nil
}

2460
vendor/golang.org/x/net/html/parse.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

273
vendor/golang.org/x/net/html/render.go generated vendored Normal file
View File

@@ -0,0 +1,273 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
import (
"bufio"
"errors"
"fmt"
"io"
"strings"
)
type writer interface {
io.Writer
io.ByteWriter
WriteString(string) (int, error)
}
// Render renders the parse tree n to the given writer.
//
// Rendering is done on a 'best effort' basis: calling Parse on the output of
// Render will always result in something similar to the original tree, but it
// is not necessarily an exact clone unless the original tree was 'well-formed'.
// 'Well-formed' is not easily specified; the HTML5 specification is
// complicated.
//
// Calling Parse on arbitrary input typically results in a 'well-formed' parse
// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
// For example, in a 'well-formed' parse tree, no <a> element is a child of
// another <a> element: parsing "<a><a>" results in two sibling elements.
// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
// children; the <a> is reparented to the <table>'s parent. However, calling
// Parse on "<a><table><a>" does not return an error, but the result has an <a>
// element with an <a> child, and is therefore not 'well-formed'.
//
// Programmatically constructed trees are typically also 'well-formed', but it
// is possible to construct a tree that looks innocuous but, when rendered and
// re-parsed, results in a different tree. A simple example is that a solitary
// text node would become a tree containing <html>, <head> and <body> elements.
// Another example is that the programmatic equivalent of "a<head>b</head>c"
// becomes "<html><head><head/><body>abc</body></html>".
func Render(w io.Writer, n *Node) error {
if x, ok := w.(writer); ok {
return render(x, n)
}
buf := bufio.NewWriter(w)
if err := render(buf, n); err != nil {
return err
}
return buf.Flush()
}
// plaintextAbort is returned from render1 when a <plaintext> element
// has been rendered. No more end tags should be rendered after that.
var plaintextAbort = errors.New("html: internal error (plaintext abort)")
func render(w writer, n *Node) error {
err := render1(w, n)
if err == plaintextAbort {
err = nil
}
return err
}
func render1(w writer, n *Node) error {
// Render non-element nodes; these are the easy cases.
switch n.Type {
case ErrorNode:
return errors.New("html: cannot render an ErrorNode node")
case TextNode:
return escape(w, n.Data)
case DocumentNode:
for c := n.FirstChild; c != nil; c = c.NextSibling {
if err := render1(w, c); err != nil {
return err
}
}
return nil
case ElementNode:
// No-op.
case CommentNode:
if _, err := w.WriteString("<!--"); err != nil {
return err
}
if _, err := w.WriteString(n.Data); err != nil {
return err
}
if _, err := w.WriteString("-->"); err != nil {
return err
}
return nil
case DoctypeNode:
if _, err := w.WriteString("<!DOCTYPE "); err != nil {
return err
}
if _, err := w.WriteString(n.Data); err != nil {
return err
}
if n.Attr != nil {
var p, s string
for _, a := range n.Attr {
switch a.Key {
case "public":
p = a.Val
case "system":
s = a.Val
}
}
if p != "" {
if _, err := w.WriteString(" PUBLIC "); err != nil {
return err
}
if err := writeQuoted(w, p); err != nil {
return err
}
if s != "" {
if err := w.WriteByte(' '); err != nil {
return err
}
if err := writeQuoted(w, s); err != nil {
return err
}
}
} else if s != "" {
if _, err := w.WriteString(" SYSTEM "); err != nil {
return err
}
if err := writeQuoted(w, s); err != nil {
return err
}
}
}
return w.WriteByte('>')
case RawNode:
_, err := w.WriteString(n.Data)
return err
default:
return errors.New("html: unknown node type")
}
// Render the <xxx> opening tag.
if err := w.WriteByte('<'); err != nil {
return err
}
if _, err := w.WriteString(n.Data); err != nil {
return err
}
for _, a := range n.Attr {
if err := w.WriteByte(' '); err != nil {
return err
}
if a.Namespace != "" {
if _, err := w.WriteString(a.Namespace); err != nil {
return err
}
if err := w.WriteByte(':'); err != nil {
return err
}
}
if _, err := w.WriteString(a.Key); err != nil {
return err
}
if _, err := w.WriteString(`="`); err != nil {
return err
}
if err := escape(w, a.Val); err != nil {
return err
}
if err := w.WriteByte('"'); err != nil {
return err
}
}
if voidElements[n.Data] {
if n.FirstChild != nil {
return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
}
_, err := w.WriteString("/>")
return err
}
if err := w.WriteByte('>'); err != nil {
return err
}
// Add initial newline where there is danger of a newline beging ignored.
if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
switch n.Data {
case "pre", "listing", "textarea":
if err := w.WriteByte('\n'); err != nil {
return err
}
}
}
// Render any child nodes.
switch n.Data {
case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
for c := n.FirstChild; c != nil; c = c.NextSibling {
if c.Type == TextNode {
if _, err := w.WriteString(c.Data); err != nil {
return err
}
} else {
if err := render1(w, c); err != nil {
return err
}
}
}
if n.Data == "plaintext" {
// Don't render anything else. <plaintext> must be the
// last element in the file, with no closing tag.
return plaintextAbort
}
default:
for c := n.FirstChild; c != nil; c = c.NextSibling {
if err := render1(w, c); err != nil {
return err
}
}
}
// Render the </xxx> closing tag.
if _, err := w.WriteString("</"); err != nil {
return err
}
if _, err := w.WriteString(n.Data); err != nil {
return err
}
return w.WriteByte('>')
}
// writeQuoted writes s to w surrounded by quotes. Normally it will use double
// quotes, but if s contains a double quote, it will use single quotes.
// It is used for writing the identifiers in a doctype declaration.
// In valid HTML, they can't contain both types of quotes.
func writeQuoted(w writer, s string) error {
var q byte = '"'
if strings.Contains(s, `"`) {
q = '\''
}
if err := w.WriteByte(q); err != nil {
return err
}
if _, err := w.WriteString(s); err != nil {
return err
}
if err := w.WriteByte(q); err != nil {
return err
}
return nil
}
// Section 12.1.2, "Elements", gives this list of void elements. Void elements
// are those that can't have any contents.
var voidElements = map[string]bool{
"area": true,
"base": true,
"br": true,
"col": true,
"embed": true,
"hr": true,
"img": true,
"input": true,
"keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility.
"link": true,
"meta": true,
"param": true,
"source": true,
"track": true,
"wbr": true,
}

1224
vendor/golang.org/x/net/html/token.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

12
vendor/maunium.net/go/mautrix/.editorconfig generated vendored Normal file
View File

@@ -0,0 +1,12 @@
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{yaml,yml}]
indent_style = space

2
vendor/maunium.net/go/mautrix/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea/
.vscode/

374
vendor/maunium.net/go/mautrix/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,374 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

24
vendor/maunium.net/go/mautrix/README.md generated vendored Normal file
View File

@@ -0,0 +1,24 @@
# mautrix-go
[![GoDoc](https://godoc.org/maunium.net/go/mautrix?status.svg)](https://godoc.org/maunium.net/go/mautrix)
A Golang Matrix framework. Used by [gomuks](https://matrix.org/docs/projects/client/gomuks),
[go-neb](https://github.com/matrix-org/go-neb), [mautrix-whatsapp](https://github.com/tulir/mautrix-whatsapp)
and others.
Matrix room: [`#maunium:maunium.net`](https://matrix.to/#/#maunium:maunium.net)
This project is based on [matrix-org/gomatrix](https://github.com/matrix-org/gomatrix).
The original project is licensed under [Apache 2.0](https://github.com/matrix-org/gomatrix/blob/master/LICENSE).
In addition to the basic client API features the original project has, this framework also has:
* Appservice support (Intent API like mautrix-python, room state storage, etc)
* End-to-end encryption support (incl. interactive SAS verification)
* Structs for parsing event content
* Helpers for parsing and generating Matrix HTML
* Helpers for handling push rules
This project contains modules that are licensed under Apache 2.0:
* [maunium.net/go/mautrix/crypto/canonicaljson](crypto/canonicaljson)
* [maunium.net/go/mautrix/crypto/olm](crypto/olm)

1596
vendor/maunium.net/go/mautrix/client.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,171 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package attachment
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha256"
"encoding/base64"
"errors"
"hash"
"io"
"maunium.net/go/mautrix/crypto/utils"
)
var (
HashMismatch = errors.New("mismatching SHA-256 digest")
UnsupportedVersion = errors.New("unsupported Matrix file encryption version")
UnsupportedAlgorithm = errors.New("unsupported JWK encryption algorithm")
InvalidKey = errors.New("failed to decode key")
InvalidInitVector = errors.New("failed to decode initialization vector")
ReaderClosed = errors.New("encrypting reader was already closed")
)
var (
keyBase64Length = base64.RawURLEncoding.EncodedLen(utils.AESCTRKeyLength)
ivBase64Length = base64.RawStdEncoding.EncodedLen(utils.AESCTRIVLength)
hashBase64Length = base64.RawStdEncoding.EncodedLen(utils.SHAHashLength)
)
type JSONWebKey struct {
Key string `json:"k"`
Algorithm string `json:"alg"`
Extractable bool `json:"ext"`
KeyType string `json:"kty"`
KeyOps []string `json:"key_ops"`
}
type EncryptedFileHashes struct {
SHA256 string `json:"sha256"`
}
type decodedKeys struct {
key [utils.AESCTRKeyLength]byte
iv [utils.AESCTRIVLength]byte
}
type EncryptedFile struct {
Key JSONWebKey `json:"key"`
InitVector string `json:"iv"`
Hashes EncryptedFileHashes `json:"hashes"`
Version string `json:"v"`
decoded *decodedKeys `json:"-"`
}
func NewEncryptedFile() *EncryptedFile {
key, iv := utils.GenAttachmentA256CTR()
return &EncryptedFile{
Key: JSONWebKey{
Key: base64.RawURLEncoding.EncodeToString(key[:]),
Algorithm: "A256CTR",
Extractable: true,
KeyType: "oct",
KeyOps: []string{"encrypt", "decrypt"},
},
InitVector: base64.RawStdEncoding.EncodeToString(iv[:]),
Version: "v2",
decoded: &decodedKeys{key, iv},
}
}
func (ef *EncryptedFile) decodeKeys() error {
if ef.decoded != nil {
return nil
} else if len(ef.Key.Key) != keyBase64Length {
return InvalidKey
} else if len(ef.InitVector) != ivBase64Length {
return InvalidInitVector
}
ef.decoded = &decodedKeys{}
_, err := base64.RawURLEncoding.Decode(ef.decoded.key[:], []byte(ef.Key.Key))
if err != nil {
return InvalidKey
}
_, err = base64.RawStdEncoding.Decode(ef.decoded.iv[:], []byte(ef.InitVector))
if err != nil {
return InvalidInitVector
}
return nil
}
func (ef *EncryptedFile) Encrypt(plaintext []byte) []byte {
ef.decodeKeys()
ciphertext := utils.XorA256CTR(plaintext, ef.decoded.key, ef.decoded.iv)
checksum := sha256.Sum256(ciphertext)
ef.Hashes.SHA256 = base64.RawStdEncoding.EncodeToString(checksum[:])
return ciphertext
}
// encryptingReader is a variation of cipher.StreamReader that also hashes the content.
type encryptingReader struct {
stream cipher.Stream
hash hash.Hash
source io.Reader
file *EncryptedFile
closed bool
}
func (r *encryptingReader) Read(dst []byte) (n int, err error) {
if r.closed {
return 0, ReaderClosed
}
n, err = r.source.Read(dst)
r.stream.XORKeyStream(dst[:n], dst[:n])
r.hash.Write(dst[:n])
return
}
func (r *encryptingReader) Close() (err error) {
closer, ok := r.source.(io.ReadCloser)
if ok {
err = closer.Close()
}
r.file.Hashes.SHA256 = base64.RawStdEncoding.EncodeToString(r.hash.Sum(nil))
r.closed = true
return
}
func (ef *EncryptedFile) EncryptStream(reader io.Reader) io.ReadCloser {
ef.decodeKeys()
block, _ := aes.NewCipher(ef.decoded.key[:])
return &encryptingReader{
stream: cipher.NewCTR(block, ef.decoded.iv[:]),
hash: sha256.New(),
source: reader,
file: ef,
}
}
func (ef *EncryptedFile) checkHash(ciphertext []byte) bool {
if len(ef.Hashes.SHA256) != hashBase64Length {
return false
}
var checksum [utils.SHAHashLength]byte
_, err := base64.RawStdEncoding.Decode(checksum[:], []byte(ef.Hashes.SHA256))
if err != nil {
return false
}
return checksum == sha256.Sum256(ciphertext)
}
func (ef *EncryptedFile) Decrypt(ciphertext []byte) ([]byte, error) {
if ef.Version != "v2" {
return nil, UnsupportedVersion
} else if ef.Key.Algorithm != "A256CTR" {
return nil, UnsupportedAlgorithm
} else if !ef.checkHash(ciphertext) {
return nil, HashMismatch
} else if err := ef.decodeKeys(); err != nil {
return nil, err
} else {
return utils.XorA256CTR(ciphertext, ef.decoded.key, ef.decoded.iv), nil
}
}

133
vendor/maunium.net/go/mautrix/crypto/utils/utils.go generated vendored Normal file
View File

@@ -0,0 +1,133 @@
// Copyright (c) 2020 Nikos Filippakis
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package utils
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"math/rand"
"strings"
"github.com/btcsuite/btcutil/base58"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/pbkdf2"
)
const (
// AESCTRKeyLength is the length of the AES256-CTR key used.
AESCTRKeyLength = 32
// AESCTRIVLength is the length of the AES256-CTR IV used.
AESCTRIVLength = 16
// HMACKeyLength is the length of the HMAC key used.
HMACKeyLength = 32
// SHAHashLength is the length of the SHA hash used.
SHAHashLength = 32
)
// XorA256CTR encrypts the input with the keystream generated by the AES256-CTR algorithm with the given arguments.
func XorA256CTR(source []byte, key [AESCTRKeyLength]byte, iv [AESCTRIVLength]byte) []byte {
block, _ := aes.NewCipher(key[:])
result := make([]byte, len(source))
cipher.NewCTR(block, iv[:]).XORKeyStream(result, source)
return result
}
// GenAttachmentA256CTR generates a new random AES256-CTR key and IV suitable for encrypting attachments.
func GenAttachmentA256CTR() (key [AESCTRKeyLength]byte, iv [AESCTRIVLength]byte) {
_, err := rand.Read(key[:])
if err != nil {
panic(err)
}
// The last 8 bytes of the IV act as the counter in AES-CTR, which means they're left empty here
_, err = rand.Read(iv[:8])
if err != nil {
panic(err)
}
return
}
// GenA256CTRIV generates a random IV for AES256-CTR with the last bit set to zero.
func GenA256CTRIV() (iv [AESCTRIVLength]byte) {
_, err := rand.Read(iv[:])
if err != nil {
panic(err)
}
iv[8] &= 0x7F
return
}
// DeriveKeysSHA256 derives an AES and a HMAC key from the given recovery key.
func DeriveKeysSHA256(key []byte, name string) ([AESCTRKeyLength]byte, [HMACKeyLength]byte) {
var zeroBytes [32]byte
derivedHkdf := hkdf.New(sha256.New, key[:], zeroBytes[:], []byte(name))
var aesKey [AESCTRKeyLength]byte
var hmacKey [HMACKeyLength]byte
derivedHkdf.Read(aesKey[:])
derivedHkdf.Read(hmacKey[:])
return aesKey, hmacKey
}
// PBKDF2SHA512 generates a key of the given bit-length using the given passphrase, salt and iteration count.
func PBKDF2SHA512(password []byte, salt []byte, iters int, keyLenBits int) []byte {
return pbkdf2.Key(password, salt, iters, keyLenBits/8, sha512.New)
}
// DecodeBase58RecoveryKey recovers the secret storage from a recovery key.
func DecodeBase58RecoveryKey(recoveryKey string) []byte {
noSpaces := strings.ReplaceAll(recoveryKey, " ", "")
decoded := base58.Decode(noSpaces)
if len(decoded) != AESCTRKeyLength+3 { // AESCTRKeyLength bytes key and 3 bytes prefix / parity
return nil
}
var parity byte
for _, b := range decoded[:34] {
parity ^= b
}
if parity != decoded[34] || decoded[0] != 0x8B || decoded[1] != 1 {
return nil
}
return decoded[2:34]
}
// EncodeBase58RecoveryKey recovers the secret storage from a recovery key.
func EncodeBase58RecoveryKey(key []byte) string {
var inputBytes [35]byte
copy(inputBytes[2:34], key[:])
inputBytes[0] = 0x8B
inputBytes[1] = 1
var parity byte
for _, b := range inputBytes[:34] {
parity ^= b
}
inputBytes[34] = parity
recoveryKey := base58.Encode(inputBytes[:])
var spacedKey string
for i, c := range recoveryKey {
if i > 0 && i%4 == 0 {
spacedKey += " "
}
spacedKey += string(c)
}
return spacedKey
}
// HMACSHA256B64 calculates the base64 of the SHA256 hmac of the input with the given key.
func HMACSHA256B64(input []byte, hmacKey [HMACKeyLength]byte) string {
h := hmac.New(sha256.New, hmacKey[:])
h.Write(input)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

144
vendor/maunium.net/go/mautrix/error.go generated vendored Normal file
View File

@@ -0,0 +1,144 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package mautrix
import (
"encoding/json"
"errors"
"fmt"
"net/http"
)
// Common error codes from https://matrix.org/docs/spec/client_server/latest#api-standards
//
// Can be used with errors.Is() to check the response code without casting the error:
// err := client.Sync()
// if errors.Is(err, MUnknownToken) {
// // logout
// }
var (
// Forbidden access, e.g. joining a room without permission, failed login.
MForbidden = RespError{ErrCode: "M_FORBIDDEN"}
// The access token specified was not recognised.
MUnknownToken = RespError{ErrCode: "M_UNKNOWN_TOKEN"}
// No access token was specified for the request.
MMissingToken = RespError{ErrCode: "M_MISSING_TOKEN"}
// Request contained valid JSON, but it was malformed in some way, e.g. missing required keys, invalid values for keys.
MBadJSON = RespError{ErrCode: "M_BAD_JSON"}
// Request did not contain valid JSON.
MNotJSON = RespError{ErrCode: "M_NOT_JSON"}
// No resource was found for this request.
MNotFound = RespError{ErrCode: "M_NOT_FOUND"}
// Too many requests have been sent in a short period of time. Wait a while then try again.
MLimitExceeded = RespError{ErrCode: "M_LIMIT_EXCEEDED"}
// The user ID associated with the request has been deactivated.
// Typically for endpoints that prove authentication, such as /login.
MUserDeactivated = RespError{ErrCode: "M_USER_DEACTIVATED"}
// Encountered when trying to register a user ID which has been taken.
MUserInUse = RespError{ErrCode: "M_USER_IN_USE"}
// Encountered when trying to register a user ID which is not valid.
MInvalidUsername = RespError{ErrCode: "M_INVALID_USERNAME"}
// Sent when the room alias given to the createRoom API is already in use.
MRoomInUse = RespError{ErrCode: "M_ROOM_IN_USE"}
// The state change requested cannot be performed, such as attempting to unban a user who is not banned.
MBadState = RespError{ErrCode: "M_BAD_STATE"}
// The request or entity was too large.
MTooLarge = RespError{ErrCode: "M_TOO_LARGE"}
// The resource being requested is reserved by an application service, or the application service making the request has not created the resource.
MExclusive = RespError{ErrCode: "M_EXCLUSIVE"}
// The client's request to create a room used a room version that the server does not support.
MUnsupportedRoomVersion = RespError{ErrCode: "M_UNSUPPORTED_ROOM_VERSION"}
// The client attempted to join a room that has a version the server does not support.
// Inspect the room_version property of the error response for the room's version.
MIncompatibleRoomVersion = RespError{ErrCode: "M_INCOMPATIBLE_ROOM_VERSION"}
)
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
type HTTPError struct {
Request *http.Request
Response *http.Response
ResponseBody string
WrappedError error
RespError *RespError
Message string
}
func (e HTTPError) Is(err error) bool {
return (e.RespError != nil && errors.Is(e.RespError, err)) || (e.WrappedError != nil && errors.Is(e.WrappedError, err))
}
func (e HTTPError) IsStatus(code int) bool {
return e.Response != nil && e.Response.StatusCode == code
}
func (e HTTPError) Error() string {
if e.WrappedError != nil {
return fmt.Sprintf("%s: %v", e.Message, e.WrappedError)
} else if e.RespError != nil {
return fmt.Sprintf("failed to %s %s: %s (HTTP %d): %s", e.Request.Method, e.Request.URL.Path,
e.RespError.ErrCode, e.Response.StatusCode, e.RespError.Err)
} else {
msg := fmt.Sprintf("failed to %s %s: %s", e.Request.Method, e.Request.URL.Path, e.Response.Status)
if len(e.ResponseBody) > 0 {
msg = fmt.Sprintf("%s\n%s", msg, e.ResponseBody)
}
return msg
}
}
func (e HTTPError) Unwrap() error {
if e.WrappedError != nil {
return e.WrappedError
} else if e.RespError != nil {
return *e.RespError
}
return nil
}
// RespError is the standard JSON error response from Homeservers. It also implements the Golang "error" interface.
// See http://matrix.org/docs/spec/client_server/r0.6.1.html#api-standards
type RespError struct {
ErrCode string
Err string
ExtraData map[string]interface{}
}
func (e *RespError) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, &e.ExtraData)
if err != nil {
return err
}
e.ErrCode, _ = e.ExtraData["errcode"].(string)
e.Err, _ = e.ExtraData["error"].(string)
return nil
}
func (e *RespError) MarshalJSON() ([]byte, error) {
if e.ExtraData == nil {
e.ExtraData = make(map[string]interface{})
}
e.ExtraData["errcode"] = e.ErrCode
e.ExtraData["error"] = e.Err
return json.Marshal(&e.ExtraData)
}
// Error returns the errcode and error message.
func (e RespError) Error() string {
return e.ErrCode + ": " + e.Err
}
func (e RespError) Is(err error) bool {
e2, ok := err.(RespError)
if !ok {
return false
}
if e.ErrCode == "M_UNKNOWN" && e2.ErrCode == "M_UNKNOWN" {
return e.Err == e2.Err
}
return e2.ErrCode == e.ErrCode
}

45
vendor/maunium.net/go/mautrix/event/accountdata.go generated vendored Normal file
View File

@@ -0,0 +1,45 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
// TagEventContent represents the content of a m.tag room account data event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-tag
type TagEventContent struct {
Tags Tags `json:"tags"`
}
type Tags map[string]Tag
type Tag struct {
Order json.Number `json:"order,omitempty"`
}
// DirectChatsEventContent represents the content of a m.direct account data event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-direct
type DirectChatsEventContent map[id.UserID][]id.RoomID
// FullyReadEventContent represents the content of a m.fully_read account data event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-fully-read
type FullyReadEventContent struct {
EventID id.EventID `json:"event_id"`
}
// IgnoredUserListEventContent represents the content of a m.ignored_user_list account data event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-ignored-user-list
type IgnoredUserListEventContent struct {
IgnoredUsers map[id.UserID]IgnoredUser `json:"ignored_users"`
}
type IgnoredUser struct {
// This is an empty object
}

486
vendor/maunium.net/go/mautrix/event/content.go generated vendored Normal file
View File

@@ -0,0 +1,486 @@
// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/gob"
"encoding/json"
"errors"
"fmt"
"reflect"
)
// TypeMap is a mapping from event type to the content struct type.
// This is used by Content.ParseRaw() for creating the correct type of struct.
var TypeMap = map[Type]reflect.Type{
StateMember: reflect.TypeOf(MemberEventContent{}),
StatePowerLevels: reflect.TypeOf(PowerLevelsEventContent{}),
StateCanonicalAlias: reflect.TypeOf(CanonicalAliasEventContent{}),
StateRoomName: reflect.TypeOf(RoomNameEventContent{}),
StateRoomAvatar: reflect.TypeOf(RoomAvatarEventContent{}),
StateTopic: reflect.TypeOf(TopicEventContent{}),
StateTombstone: reflect.TypeOf(TombstoneEventContent{}),
StateCreate: reflect.TypeOf(CreateEventContent{}),
StateJoinRules: reflect.TypeOf(JoinRulesEventContent{}),
StateHistoryVisibility: reflect.TypeOf(HistoryVisibilityEventContent{}),
StateGuestAccess: reflect.TypeOf(GuestAccessEventContent{}),
StatePinnedEvents: reflect.TypeOf(PinnedEventsEventContent{}),
StateEncryption: reflect.TypeOf(EncryptionEventContent{}),
StateBridge: reflect.TypeOf(BridgeEventContent{}),
StateHalfShotBridge: reflect.TypeOf(BridgeEventContent{}),
StateSpaceParent: reflect.TypeOf(SpaceParentEventContent{}),
StateSpaceChild: reflect.TypeOf(SpaceChildEventContent{}),
EventMessage: reflect.TypeOf(MessageEventContent{}),
EventSticker: reflect.TypeOf(MessageEventContent{}),
EventEncrypted: reflect.TypeOf(EncryptedEventContent{}),
EventRedaction: reflect.TypeOf(RedactionEventContent{}),
EventReaction: reflect.TypeOf(ReactionEventContent{}),
AccountDataRoomTags: reflect.TypeOf(TagEventContent{}),
AccountDataDirectChats: reflect.TypeOf(DirectChatsEventContent{}),
AccountDataFullyRead: reflect.TypeOf(FullyReadEventContent{}),
AccountDataIgnoredUserList: reflect.TypeOf(IgnoredUserListEventContent{}),
EphemeralEventTyping: reflect.TypeOf(TypingEventContent{}),
EphemeralEventReceipt: reflect.TypeOf(ReceiptEventContent{}),
EphemeralEventPresence: reflect.TypeOf(PresenceEventContent{}),
InRoomVerificationStart: reflect.TypeOf(VerificationStartEventContent{}),
InRoomVerificationReady: reflect.TypeOf(VerificationReadyEventContent{}),
InRoomVerificationAccept: reflect.TypeOf(VerificationAcceptEventContent{}),
InRoomVerificationKey: reflect.TypeOf(VerificationKeyEventContent{}),
InRoomVerificationMAC: reflect.TypeOf(VerificationMacEventContent{}),
InRoomVerificationCancel: reflect.TypeOf(VerificationCancelEventContent{}),
ToDeviceRoomKey: reflect.TypeOf(RoomKeyEventContent{}),
ToDeviceForwardedRoomKey: reflect.TypeOf(ForwardedRoomKeyEventContent{}),
ToDeviceRoomKeyRequest: reflect.TypeOf(RoomKeyRequestEventContent{}),
ToDeviceEncrypted: reflect.TypeOf(EncryptedEventContent{}),
ToDeviceRoomKeyWithheld: reflect.TypeOf(RoomKeyWithheldEventContent{}),
ToDeviceDummy: reflect.TypeOf(DummyEventContent{}),
ToDeviceVerificationStart: reflect.TypeOf(VerificationStartEventContent{}),
ToDeviceVerificationAccept: reflect.TypeOf(VerificationAcceptEventContent{}),
ToDeviceVerificationKey: reflect.TypeOf(VerificationKeyEventContent{}),
ToDeviceVerificationMAC: reflect.TypeOf(VerificationMacEventContent{}),
ToDeviceVerificationCancel: reflect.TypeOf(VerificationCancelEventContent{}),
ToDeviceVerificationRequest: reflect.TypeOf(VerificationRequestEventContent{}),
ToDeviceOrgMatrixRoomKeyWithheld: reflect.TypeOf(RoomKeyWithheldEventContent{}),
CallInvite: reflect.TypeOf(CallInviteEventContent{}),
CallCandidates: reflect.TypeOf(CallCandidatesEventContent{}),
CallAnswer: reflect.TypeOf(CallAnswerEventContent{}),
CallReject: reflect.TypeOf(CallRejectEventContent{}),
CallSelectAnswer: reflect.TypeOf(CallSelectAnswerEventContent{}),
CallNegotiate: reflect.TypeOf(CallNegotiateEventContent{}),
CallHangup: reflect.TypeOf(CallHangupEventContent{}),
}
// Content stores the content of a Matrix event.
//
// By default, the content is only parsed into a map[string]interface{}. However, you can call ParseRaw with the
// correct event type to parse the content into a nicer struct, which you can then access from Parsed or via the
// helper functions.
type Content struct {
VeryRaw json.RawMessage
Raw map[string]interface{}
Parsed interface{}
}
type Relatable interface {
GetRelatesTo() *RelatesTo
OptionalGetRelatesTo() *RelatesTo
SetRelatesTo(rel *RelatesTo)
}
func (content *Content) UnmarshalJSON(data []byte) error {
content.VeryRaw = data
err := json.Unmarshal(data, &content.Raw)
return err
}
func (content *Content) MarshalJSON() ([]byte, error) {
if content.Raw == nil {
if content.Parsed == nil {
if content.VeryRaw == nil {
return []byte("{}"), nil
}
return content.VeryRaw, nil
}
return json.Marshal(content.Parsed)
} else if content.Parsed != nil {
// TODO this whole thing is incredibly hacky
// It needs to produce JSON, where:
// * content.Parsed is applied after content.Raw
// * MarshalJSON() is respected inside content.Parsed
// * Custom field inside nested objects of content.Raw are preserved,
// even if content.Parsed contains the higher-level objects.
// * content.Raw is not modified
unparsed, err := json.Marshal(content.Parsed)
if err != nil {
return nil, err
}
var rawParsed map[string]interface{}
err = json.Unmarshal(unparsed, &rawParsed)
if err != nil {
return nil, err
}
output := make(map[string]interface{})
for key, value := range content.Raw {
output[key] = value
}
mergeMaps(output, rawParsed)
return json.Marshal(output)
}
return json.Marshal(content.Raw)
}
func IsUnsupportedContentType(err error) bool {
return errors.Is(err, UnsupportedContentType)
}
var ContentAlreadyParsed = errors.New("content is already parsed")
var UnsupportedContentType = errors.New("unsupported event type")
func (content *Content) ParseRaw(evtType Type) error {
if content.Parsed != nil {
return ContentAlreadyParsed
}
structType, ok := TypeMap[evtType]
if !ok {
return fmt.Errorf("%w %s", UnsupportedContentType, evtType.Repr())
}
content.Parsed = reflect.New(structType).Interface()
return json.Unmarshal(content.VeryRaw, &content.Parsed)
}
func mergeMaps(into, from map[string]interface{}) {
for key, newValue := range from {
existingValue, ok := into[key]
if !ok {
into[key] = newValue
continue
}
existingValueMap, okEx := existingValue.(map[string]interface{})
newValueMap, okNew := newValue.(map[string]interface{})
if okEx && okNew {
mergeMaps(existingValueMap, newValueMap)
} else {
into[key] = newValue
}
}
}
func init() {
gob.Register(&MemberEventContent{})
gob.Register(&PowerLevelsEventContent{})
gob.Register(&CanonicalAliasEventContent{})
gob.Register(&EncryptionEventContent{})
gob.Register(&BridgeEventContent{})
gob.Register(&SpaceChildEventContent{})
gob.Register(&SpaceParentEventContent{})
gob.Register(&RoomNameEventContent{})
gob.Register(&RoomAvatarEventContent{})
gob.Register(&TopicEventContent{})
gob.Register(&TombstoneEventContent{})
gob.Register(&CreateEventContent{})
gob.Register(&JoinRulesEventContent{})
gob.Register(&HistoryVisibilityEventContent{})
gob.Register(&GuestAccessEventContent{})
gob.Register(&PinnedEventsEventContent{})
gob.Register(&MessageEventContent{})
gob.Register(&MessageEventContent{})
gob.Register(&EncryptedEventContent{})
gob.Register(&RedactionEventContent{})
gob.Register(&ReactionEventContent{})
gob.Register(&TagEventContent{})
gob.Register(&DirectChatsEventContent{})
gob.Register(&FullyReadEventContent{})
gob.Register(&IgnoredUserListEventContent{})
gob.Register(&TypingEventContent{})
gob.Register(&ReceiptEventContent{})
gob.Register(&PresenceEventContent{})
gob.Register(&RoomKeyEventContent{})
gob.Register(&ForwardedRoomKeyEventContent{})
gob.Register(&RoomKeyRequestEventContent{})
gob.Register(&RoomKeyWithheldEventContent{})
}
// Helper cast functions below
func (content *Content) AsMember() *MemberEventContent {
casted, ok := content.Parsed.(*MemberEventContent)
if !ok {
return &MemberEventContent{}
}
return casted
}
func (content *Content) AsPowerLevels() *PowerLevelsEventContent {
casted, ok := content.Parsed.(*PowerLevelsEventContent)
if !ok {
return &PowerLevelsEventContent{}
}
return casted
}
func (content *Content) AsCanonicalAlias() *CanonicalAliasEventContent {
casted, ok := content.Parsed.(*CanonicalAliasEventContent)
if !ok {
return &CanonicalAliasEventContent{}
}
return casted
}
func (content *Content) AsRoomName() *RoomNameEventContent {
casted, ok := content.Parsed.(*RoomNameEventContent)
if !ok {
return &RoomNameEventContent{}
}
return casted
}
func (content *Content) AsRoomAvatar() *RoomAvatarEventContent {
casted, ok := content.Parsed.(*RoomAvatarEventContent)
if !ok {
return &RoomAvatarEventContent{}
}
return casted
}
func (content *Content) AsTopic() *TopicEventContent {
casted, ok := content.Parsed.(*TopicEventContent)
if !ok {
return &TopicEventContent{}
}
return casted
}
func (content *Content) AsTombstone() *TombstoneEventContent {
casted, ok := content.Parsed.(*TombstoneEventContent)
if !ok {
return &TombstoneEventContent{}
}
return casted
}
func (content *Content) AsCreate() *CreateEventContent {
casted, ok := content.Parsed.(*CreateEventContent)
if !ok {
return &CreateEventContent{}
}
return casted
}
func (content *Content) AsJoinRules() *JoinRulesEventContent {
casted, ok := content.Parsed.(*JoinRulesEventContent)
if !ok {
return &JoinRulesEventContent{}
}
return casted
}
func (content *Content) AsHistoryVisibility() *HistoryVisibilityEventContent {
casted, ok := content.Parsed.(*HistoryVisibilityEventContent)
if !ok {
return &HistoryVisibilityEventContent{}
}
return casted
}
func (content *Content) AsGuestAccess() *GuestAccessEventContent {
casted, ok := content.Parsed.(*GuestAccessEventContent)
if !ok {
return &GuestAccessEventContent{}
}
return casted
}
func (content *Content) AsPinnedEvents() *PinnedEventsEventContent {
casted, ok := content.Parsed.(*PinnedEventsEventContent)
if !ok {
return &PinnedEventsEventContent{}
}
return casted
}
func (content *Content) AsEncryption() *EncryptionEventContent {
casted, ok := content.Parsed.(*EncryptionEventContent)
if !ok {
return &EncryptionEventContent{}
}
return casted
}
func (content *Content) AsBridge() *BridgeEventContent {
casted, ok := content.Parsed.(*BridgeEventContent)
if !ok {
return &BridgeEventContent{}
}
return casted
}
func (content *Content) AsSpaceChild() *SpaceChildEventContent {
casted, ok := content.Parsed.(*SpaceChildEventContent)
if !ok {
return &SpaceChildEventContent{}
}
return casted
}
func (content *Content) AsSpaceParent() *SpaceParentEventContent {
casted, ok := content.Parsed.(*SpaceParentEventContent)
if !ok {
return &SpaceParentEventContent{}
}
return casted
}
func (content *Content) AsMessage() *MessageEventContent {
casted, ok := content.Parsed.(*MessageEventContent)
if !ok {
return &MessageEventContent{}
}
return casted
}
func (content *Content) AsEncrypted() *EncryptedEventContent {
casted, ok := content.Parsed.(*EncryptedEventContent)
if !ok {
return &EncryptedEventContent{}
}
return casted
}
func (content *Content) AsRedaction() *RedactionEventContent {
casted, ok := content.Parsed.(*RedactionEventContent)
if !ok {
return &RedactionEventContent{}
}
return casted
}
func (content *Content) AsReaction() *ReactionEventContent {
casted, ok := content.Parsed.(*ReactionEventContent)
if !ok {
return &ReactionEventContent{}
}
return casted
}
func (content *Content) AsTag() *TagEventContent {
casted, ok := content.Parsed.(*TagEventContent)
if !ok {
return &TagEventContent{}
}
return casted
}
func (content *Content) AsDirectChats() *DirectChatsEventContent {
casted, ok := content.Parsed.(*DirectChatsEventContent)
if !ok {
return &DirectChatsEventContent{}
}
return casted
}
func (content *Content) AsFullyRead() *FullyReadEventContent {
casted, ok := content.Parsed.(*FullyReadEventContent)
if !ok {
return &FullyReadEventContent{}
}
return casted
}
func (content *Content) AsIgnoredUserList() *IgnoredUserListEventContent {
casted, ok := content.Parsed.(*IgnoredUserListEventContent)
if !ok {
return &IgnoredUserListEventContent{}
}
return casted
}
func (content *Content) AsTyping() *TypingEventContent {
casted, ok := content.Parsed.(*TypingEventContent)
if !ok {
return &TypingEventContent{}
}
return casted
}
func (content *Content) AsReceipt() *ReceiptEventContent {
casted, ok := content.Parsed.(*ReceiptEventContent)
if !ok {
return &ReceiptEventContent{}
}
return casted
}
func (content *Content) AsPresence() *PresenceEventContent {
casted, ok := content.Parsed.(*PresenceEventContent)
if !ok {
return &PresenceEventContent{}
}
return casted
}
func (content *Content) AsRoomKey() *RoomKeyEventContent {
casted, ok := content.Parsed.(*RoomKeyEventContent)
if !ok {
return &RoomKeyEventContent{}
}
return casted
}
func (content *Content) AsForwardedRoomKey() *ForwardedRoomKeyEventContent {
casted, ok := content.Parsed.(*ForwardedRoomKeyEventContent)
if !ok {
return &ForwardedRoomKeyEventContent{}
}
return casted
}
func (content *Content) AsRoomKeyRequest() *RoomKeyRequestEventContent {
casted, ok := content.Parsed.(*RoomKeyRequestEventContent)
if !ok {
return &RoomKeyRequestEventContent{}
}
return casted
}
func (content *Content) AsRoomKeyWithheld() *RoomKeyWithheldEventContent {
casted, ok := content.Parsed.(*RoomKeyWithheldEventContent)
if !ok {
return &RoomKeyWithheldEventContent{}
}
return casted
}
func (content *Content) AsCallInvite() *CallInviteEventContent {
casted, ok := content.Parsed.(*CallInviteEventContent)
if !ok {
return &CallInviteEventContent{}
}
return casted
}
func (content *Content) AsCallCandidates() *CallCandidatesEventContent {
casted, ok := content.Parsed.(*CallCandidatesEventContent)
if !ok {
return &CallCandidatesEventContent{}
}
return casted
}
func (content *Content) AsCallAnswer() *CallAnswerEventContent {
casted, ok := content.Parsed.(*CallAnswerEventContent)
if !ok {
return &CallAnswerEventContent{}
}
return casted
}
func (content *Content) AsCallReject() *CallRejectEventContent {
casted, ok := content.Parsed.(*CallRejectEventContent)
if !ok {
return &CallRejectEventContent{}
}
return casted
}
func (content *Content) AsCallSelectAnswer() *CallSelectAnswerEventContent {
casted, ok := content.Parsed.(*CallSelectAnswerEventContent)
if !ok {
return &CallSelectAnswerEventContent{}
}
return casted
}
func (content *Content) AsCallNegotiate() *CallNegotiateEventContent {
casted, ok := content.Parsed.(*CallNegotiateEventContent)
if !ok {
return &CallNegotiateEventContent{}
}
return casted
}
func (content *Content) AsCallHangup() *CallHangupEventContent {
casted, ok := content.Parsed.(*CallHangupEventContent)
if !ok {
return &CallHangupEventContent{}
}
return casted
}

143
vendor/maunium.net/go/mautrix/event/encryption.go generated vendored Normal file
View File

@@ -0,0 +1,143 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
// EncryptionEventContent represents the content of a m.room.encryption state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-encryption
type EncryptionEventContent struct {
// The encryption algorithm to be used to encrypt messages sent in this room. Must be 'm.megolm.v1.aes-sha2'.
Algorithm id.Algorithm `json:"algorithm"`
// How long the session should be used before changing it. 604800000 (a week) is the recommended default.
RotationPeriodMillis int64 `json:"rotation_period_ms,omitempty"`
// How many messages should be sent before changing the session. 100 is the recommended default.
RotationPeriodMessages int `json:"rotation_period_msgs,omitempty"`
}
// EncryptedEventContent represents the content of a m.room.encrypted message event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-encrypted
type EncryptedEventContent struct {
Algorithm id.Algorithm `json:"algorithm"`
SenderKey id.SenderKey `json:"sender_key"`
DeviceID id.DeviceID `json:"device_id,omitempty"` // Only present for Megolm events
SessionID id.SessionID `json:"session_id,omitempty"` // Only present for Megolm events
Ciphertext json.RawMessage `json:"ciphertext"`
MegolmCiphertext []byte `json:"-"`
OlmCiphertext OlmCiphertexts `json:"-"`
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
type OlmCiphertexts map[id.Curve25519]struct {
Body string `json:"body"`
Type id.OlmMsgType `json:"type"`
}
type serializableEncryptedEventContent EncryptedEventContent
func (content *EncryptedEventContent) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, (*serializableEncryptedEventContent)(content))
if err != nil {
return err
}
switch content.Algorithm {
case id.AlgorithmOlmV1:
content.OlmCiphertext = make(OlmCiphertexts)
return json.Unmarshal(content.Ciphertext, &content.OlmCiphertext)
case id.AlgorithmMegolmV1:
if len(content.Ciphertext) == 0 || content.Ciphertext[0] != '"' || content.Ciphertext[len(content.Ciphertext)-1] != '"' {
return id.InputNotJSONString
}
content.MegolmCiphertext = content.Ciphertext[1 : len(content.Ciphertext)-1]
}
return nil
}
func (content *EncryptedEventContent) MarshalJSON() ([]byte, error) {
var err error
switch content.Algorithm {
case id.AlgorithmOlmV1:
content.Ciphertext, err = json.Marshal(content.OlmCiphertext)
case id.AlgorithmMegolmV1:
content.Ciphertext = make([]byte, len(content.MegolmCiphertext)+2)
content.Ciphertext[0] = '"'
content.Ciphertext[len(content.Ciphertext)-1] = '"'
copy(content.Ciphertext[1:len(content.Ciphertext)-1], content.MegolmCiphertext)
}
if err != nil {
return nil, err
}
return json.Marshal((*serializableEncryptedEventContent)(content))
}
// RoomKeyEventContent represents the content of a m.room_key to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-key
type RoomKeyEventContent struct {
Algorithm id.Algorithm `json:"algorithm"`
RoomID id.RoomID `json:"room_id"`
SessionID id.SessionID `json:"session_id"`
SessionKey string `json:"session_key"`
}
// ForwardedRoomKeyEventContent represents the content of a m.forwarded_room_key to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-forwarded-room-key
type ForwardedRoomKeyEventContent struct {
RoomKeyEventContent
SenderKey id.SenderKey `json:"sender_key"`
SenderClaimedKey id.Ed25519 `json:"sender_claimed_ed25519_key"`
ForwardingKeyChain []string `json:"forwarding_curve25519_key_chain"`
}
type KeyRequestAction string
const (
KeyRequestActionRequest = "request"
KeyRequestActionCancel = "request_cancellation"
)
// RoomKeyRequestEventContent represents the content of a m.room_key_request to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-key-request
type RoomKeyRequestEventContent struct {
Body RequestedKeyInfo `json:"body"`
Action KeyRequestAction `json:"action"`
RequestingDeviceID id.DeviceID `json:"requesting_device_id"`
RequestID string `json:"request_id"`
}
type RequestedKeyInfo struct {
Algorithm id.Algorithm `json:"algorithm"`
RoomID id.RoomID `json:"room_id"`
SenderKey id.SenderKey `json:"sender_key"`
SessionID id.SessionID `json:"session_id"`
}
type RoomKeyWithheldCode string
const (
RoomKeyWithheldBlacklisted RoomKeyWithheldCode = "m.blacklisted"
RoomKeyWithheldUnverified RoomKeyWithheldCode = "m.unverified"
RoomKeyWithheldUnauthorized RoomKeyWithheldCode = "m.unauthorized"
RoomKeyWithheldUnavailable RoomKeyWithheldCode = "m.unavailable"
RoomKeyWithheldNoOlmSession RoomKeyWithheldCode = "m.no_olm"
)
type RoomKeyWithheldEventContent struct {
RoomID id.RoomID `json:"room_id,omitempty"`
Algorithm id.Algorithm `json:"algorithm"`
SessionID id.SessionID `json:"session_id,omitempty"`
SenderKey id.SenderKey `json:"sender_key"`
Code RoomKeyWithheldCode `json:"code"`
Reason string `json:"reason,omitempty"`
}
type DummyEventContent struct{}

80
vendor/maunium.net/go/mautrix/event/ephemeral.go generated vendored Normal file
View File

@@ -0,0 +1,80 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
// TagEventContent represents the content of a m.typing ephemeral event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-typing
type TypingEventContent struct {
UserIDs []id.UserID `json:"user_ids"`
}
// ReceiptEventContent represents the content of a m.receipt ephemeral event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-receipt
type ReceiptEventContent map[id.EventID]Receipts
type Receipts struct {
Read map[id.UserID]ReadReceipt `json:"m.read"`
}
type ReadReceipt struct {
Timestamp int64 `json:"ts"`
// Extra contains any unknown fields in the read receipt event.
// Most servers don't allow clients to set them, so this will be empty in most cases.
Extra map[string]interface{} `json:"-"`
}
func (rr *ReadReceipt) UnmarshalJSON(data []byte) error {
// Hacky compatibility hack against crappy clients that send double-encoded read receipts.
// TODO is this actually needed? clients can't currently set custom content in receipts 🤔
if data[0] == '"' && data[len(data)-1] == '"' {
var strData string
err := json.Unmarshal(data, &strData)
if err != nil {
return err
}
data = []byte(strData)
}
var parsed map[string]interface{}
err := json.Unmarshal(data, &parsed)
if err != nil {
return err
}
ts, _ := parsed["ts"].(float64)
delete(parsed, "ts")
*rr = ReadReceipt{
Timestamp: int64(ts),
Extra: parsed,
}
return nil
}
type Presence string
const (
PresenceOnline Presence = "online"
PresenceOffline Presence = "offline"
PresenceUnavailable Presence = "unavailable"
)
// PresenceEventContent represents the content of a m.presence ephemeral event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-presence
type PresenceEventContent struct {
Presence Presence `json:"presence"`
Displayname string `json:"displayname,omitempty"`
AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
LastActiveAgo int64 `json:"last_active_ago,omitempty"`
CurrentlyActive bool `json:"currently_active,omitempty"`
StatusMessage string `json:"status_msg,omitempty"`
}

138
vendor/maunium.net/go/mautrix/event/events.go generated vendored Normal file
View File

@@ -0,0 +1,138 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
// Event represents a single Matrix event.
type Event struct {
StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
Sender id.UserID `json:"sender,omitempty"` // The user ID of the sender of the event
Type Type `json:"type"` // The event type
Timestamp int64 `json:"origin_server_ts,omitempty"` // The unix timestamp when this message was sent by the origin server
ID id.EventID `json:"event_id,omitempty"` // The unique ID of this event
RoomID id.RoomID `json:"room_id,omitempty"` // The room the event was sent to. May be nil (e.g. for presence)
Content Content `json:"content"` // The JSON content of the event.
Redacts id.EventID `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
Mautrix MautrixInfo `json:"-"`
ToUserID id.UserID `json:"to_user_id,omitempty"` // The user ID that the to-device event was sent to. Only present in MSC2409 appservice transactions.
ToDeviceID id.DeviceID `json:"to_device_id,omitempty"` // The device ID that the to-device event was sent to. Only present in MSC2409 appservice transactions.
}
type eventForMarshaling struct {
StateKey *string `json:"state_key,omitempty"`
Sender id.UserID `json:"sender,omitempty"`
Type Type `json:"type"`
Timestamp int64 `json:"origin_server_ts,omitempty"`
ID id.EventID `json:"event_id,omitempty"`
RoomID id.RoomID `json:"room_id,omitempty"`
Content Content `json:"content"`
Redacts id.EventID `json:"redacts,omitempty"`
Unsigned *Unsigned `json:"unsigned,omitempty"`
PrevContent *Content `json:"prev_content,omitempty"`
ReplacesState *id.EventID `json:"replaces_state,omitempty"`
ToUserID id.UserID `json:"to_user_id,omitempty"`
ToDeviceID id.DeviceID `json:"to_device_id,omitempty"`
}
// UnmarshalJSON unmarshals the event, including moving prev_content from the top level to inside unsigned.
func (evt *Event) UnmarshalJSON(data []byte) error {
var efm eventForMarshaling
err := json.Unmarshal(data, &efm)
if err != nil {
return err
}
evt.StateKey = efm.StateKey
evt.Sender = efm.Sender
evt.Type = efm.Type
evt.Timestamp = efm.Timestamp
evt.ID = efm.ID
evt.RoomID = efm.RoomID
evt.Content = efm.Content
evt.Redacts = efm.Redacts
if efm.Unsigned != nil {
evt.Unsigned = *efm.Unsigned
}
if efm.PrevContent != nil && evt.Unsigned.PrevContent == nil {
evt.Unsigned.PrevContent = efm.PrevContent
}
if efm.ReplacesState != nil && *efm.ReplacesState != "" && evt.Unsigned.ReplacesState == "" {
evt.Unsigned.ReplacesState = *efm.ReplacesState
}
evt.ToUserID = efm.ToUserID
evt.ToDeviceID = efm.ToDeviceID
return nil
}
// MarshalJSON marshals the event, including omitting the unsigned field if it's empty.
//
// This is necessary because Unsigned is not a pointer (for convenience reasons),
// and encoding/json doesn't know how to check if a non-pointer struct is empty.
//
// TODO(tulir): maybe it makes more sense to make Unsigned a pointer and make an easy and safe way to access it?
func (evt *Event) MarshalJSON() ([]byte, error) {
unsigned := &evt.Unsigned
if unsigned.IsEmpty() {
unsigned = nil
}
return json.Marshal(&eventForMarshaling{
StateKey: evt.StateKey,
Sender: evt.Sender,
Type: evt.Type,
Timestamp: evt.Timestamp,
ID: evt.ID,
RoomID: evt.RoomID,
Content: evt.Content,
Redacts: evt.Redacts,
Unsigned: unsigned,
ToUserID: evt.ToUserID,
ToDeviceID: evt.ToDeviceID,
})
}
type MautrixInfo struct {
Verified bool
}
func (evt *Event) GetStateKey() string {
if evt.StateKey != nil {
return *evt.StateKey
}
return ""
}
type StrippedState struct {
Content Content `json:"content"`
Type Type `json:"type"`
StateKey string `json:"state_key"`
}
type Unsigned struct {
PrevContent *Content `json:"prev_content,omitempty"`
PrevSender id.UserID `json:"prev_sender,omitempty"`
ReplacesState id.EventID `json:"replaces_state,omitempty"`
Age int64 `json:"age,omitempty"`
TransactionID string `json:"transaction_id,omitempty"`
Relations Relations `json:"m.relations,omitempty"`
RedactedBecause *Event `json:"redacted_because,omitempty"`
InviteRoomState []StrippedState `json:"invite_room_state,omitempty"`
}
func (us *Unsigned) IsEmpty() bool {
return us.PrevContent == nil && us.PrevSender == "" && us.ReplacesState == "" && us.Age == 0 &&
us.TransactionID == "" && us.RedactedBecause == nil && us.InviteRoomState == nil && us.Relations.Raw == nil &&
us.Relations.Annotations.Map == nil && us.Relations.References.List == nil && us.Relations.Replaces.List == nil
}

53
vendor/maunium.net/go/mautrix/event/member.go generated vendored Normal file
View File

@@ -0,0 +1,53 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
// Membership is an enum specifying the membership state of a room member.
type Membership string
func (ms Membership) IsInviteOrJoin() bool {
return ms == MembershipJoin || ms == MembershipInvite
}
func (ms Membership) IsLeaveOrBan() bool {
return ms == MembershipLeave || ms == MembershipBan
}
// The allowed membership states as specified in spec section 10.5.5.
const (
MembershipJoin Membership = "join"
MembershipLeave Membership = "leave"
MembershipInvite Membership = "invite"
MembershipBan Membership = "ban"
MembershipKnock Membership = "knock"
)
// MemberEventContent represents the content of a m.room.member state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-member
type MemberEventContent struct {
Membership Membership `json:"membership"`
AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
Displayname string `json:"displayname,omitempty"`
IsDirect bool `json:"is_direct,omitempty"`
ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"`
Reason string `json:"reason,omitempty"`
}
type ThirdPartyInvite struct {
DisplayName string `json:"display_name"`
Signed struct {
Token string `json:"token"`
Signatures json.RawMessage `json:"signatures"`
MXID string `json:"mxid"`
}
}

246
vendor/maunium.net/go/mautrix/event/message.go generated vendored Normal file
View File

@@ -0,0 +1,246 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"strconv"
"maunium.net/go/mautrix/crypto/attachment"
"maunium.net/go/mautrix/id"
)
// MessageType is the sub-type of a m.room.message event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-message-msgtypes
type MessageType string
// Msgtypes
const (
MsgText MessageType = "m.text"
MsgEmote MessageType = "m.emote"
MsgNotice MessageType = "m.notice"
MsgImage MessageType = "m.image"
MsgLocation MessageType = "m.location"
MsgVideo MessageType = "m.video"
MsgAudio MessageType = "m.audio"
MsgFile MessageType = "m.file"
MsgVerificationRequest MessageType = "m.key.verification.request"
)
// Format specifies the format of the formatted_body in m.room.message events.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-message-msgtypes
type Format string
// Message formats
const (
FormatHTML Format = "org.matrix.custom.html"
)
// RedactionEventContent represents the content of a m.room.redaction message event.
//
// The redacted event ID is still at the top level, but will move in a future room version.
// See https://github.com/matrix-org/matrix-doc/pull/2244 and https://github.com/matrix-org/matrix-doc/pull/2174
//
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-redaction
type RedactionEventContent struct {
Reason string `json:"reason,omitempty"`
}
// ReactionEventContent represents the content of a m.reaction message event.
// This is not yet in a spec release, see https://github.com/matrix-org/matrix-doc/pull/1849
type ReactionEventContent struct {
RelatesTo RelatesTo `json:"m.relates_to"`
}
func (content *ReactionEventContent) GetRelatesTo() *RelatesTo {
return &content.RelatesTo
}
func (content *ReactionEventContent) OptionalGetRelatesTo() *RelatesTo {
return &content.RelatesTo
}
func (content *ReactionEventContent) SetRelatesTo(rel *RelatesTo) {
content.RelatesTo = *rel
}
// MssageEventContent represents the content of a m.room.message event.
//
// It is also used to represent m.sticker events, as they are equivalent to m.room.message
// with the exception of the msgtype field.
//
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-message
type MessageEventContent struct {
// Base m.room.message fields
MsgType MessageType `json:"msgtype"`
Body string `json:"body"`
// Extra fields for text types
Format Format `json:"format,omitempty"`
FormattedBody string `json:"formatted_body,omitempty"`
// Extra field for m.location
GeoURI string `json:"geo_uri,omitempty"`
// Extra fields for media types
URL id.ContentURIString `json:"url,omitempty"`
Info *FileInfo `json:"info,omitempty"`
File *EncryptedFileInfo `json:"file,omitempty"`
// Edits and relations
NewContent *MessageEventContent `json:"m.new_content,omitempty"`
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
// In-room verification
To id.UserID `json:"to,omitempty"`
FromDevice id.DeviceID `json:"from_device,omitempty"`
Methods []VerificationMethod `json:"methods,omitempty"`
replyFallbackRemoved bool
}
func (content *MessageEventContent) GetRelatesTo() *RelatesTo {
if content.RelatesTo == nil {
content.RelatesTo = &RelatesTo{}
}
return content.RelatesTo
}
func (content *MessageEventContent) OptionalGetRelatesTo() *RelatesTo {
return content.RelatesTo
}
func (content *MessageEventContent) SetRelatesTo(rel *RelatesTo) {
content.RelatesTo = rel
}
func (content *MessageEventContent) SetEdit(original id.EventID) {
newContent := *content
content.NewContent = &newContent
content.RelatesTo = &RelatesTo{
Type: RelReplace,
EventID: original,
}
if content.MsgType == MsgText || content.MsgType == MsgNotice {
content.Body = "* " + content.Body
if content.Format == FormatHTML && len(content.FormattedBody) > 0 {
content.FormattedBody = "* " + content.FormattedBody
}
}
}
func (content *MessageEventContent) GetFile() *EncryptedFileInfo {
if content.File == nil {
content.File = &EncryptedFileInfo{}
}
return content.File
}
func (content *MessageEventContent) GetInfo() *FileInfo {
if content.Info == nil {
content.Info = &FileInfo{}
}
return content.Info
}
type EncryptedFileInfo struct {
attachment.EncryptedFile
URL id.ContentURIString `json:"url"`
}
type FileInfo struct {
MimeType string `json:"mimetype,omitempty"`
ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
ThumbnailURL id.ContentURIString `json:"thumbnail_url,omitempty"`
ThumbnailFile *EncryptedFileInfo `json:"thumbnail_file,omitempty"`
Width int `json:"-"`
Height int `json:"-"`
Duration int `json:"-"`
Size int `json:"-"`
}
type serializableFileInfo struct {
MimeType string `json:"mimetype,omitempty"`
ThumbnailInfo *serializableFileInfo `json:"thumbnail_info,omitempty"`
ThumbnailURL id.ContentURIString `json:"thumbnail_url,omitempty"`
ThumbnailFile *EncryptedFileInfo `json:"thumbnail_file,omitempty"`
Width json.Number `json:"w,omitempty"`
Height json.Number `json:"h,omitempty"`
Duration json.Number `json:"duration,omitempty"`
Size json.Number `json:"size,omitempty"`
}
func (sfi *serializableFileInfo) CopyFrom(fileInfo *FileInfo) *serializableFileInfo {
if fileInfo == nil {
return nil
}
*sfi = serializableFileInfo{
MimeType: fileInfo.MimeType,
ThumbnailURL: fileInfo.ThumbnailURL,
ThumbnailInfo: (&serializableFileInfo{}).CopyFrom(fileInfo.ThumbnailInfo),
ThumbnailFile: fileInfo.ThumbnailFile,
}
if fileInfo.Width > 0 {
sfi.Width = json.Number(strconv.Itoa(fileInfo.Width))
}
if fileInfo.Height > 0 {
sfi.Height = json.Number(strconv.Itoa(fileInfo.Height))
}
if fileInfo.Size > 0 {
sfi.Size = json.Number(strconv.Itoa(fileInfo.Size))
}
if fileInfo.Duration > 0 {
sfi.Duration = json.Number(strconv.Itoa(int(fileInfo.Duration)))
}
return sfi
}
func (sfi *serializableFileInfo) CopyTo(fileInfo *FileInfo) {
*fileInfo = FileInfo{
Width: numberToInt(sfi.Width),
Height: numberToInt(sfi.Height),
Size: numberToInt(sfi.Size),
Duration: numberToInt(sfi.Duration),
MimeType: sfi.MimeType,
ThumbnailURL: sfi.ThumbnailURL,
}
if sfi.ThumbnailInfo != nil {
fileInfo.ThumbnailInfo = &FileInfo{}
sfi.ThumbnailInfo.CopyTo(fileInfo.ThumbnailInfo)
}
}
func (fileInfo *FileInfo) UnmarshalJSON(data []byte) error {
sfi := &serializableFileInfo{}
if err := json.Unmarshal(data, sfi); err != nil {
return err
}
sfi.CopyTo(fileInfo)
return nil
}
func (fileInfo *FileInfo) MarshalJSON() ([]byte, error) {
return json.Marshal((&serializableFileInfo{}).CopyFrom(fileInfo))
}
func numberToInt(val json.Number) int {
f64, _ := val.Float64()
if f64 > 0 {
return int(f64)
}
return 0
}
func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo {
if fileInfo.ThumbnailInfo == nil {
fileInfo.ThumbnailInfo = &FileInfo{}
}
return fileInfo.ThumbnailInfo
}

136
vendor/maunium.net/go/mautrix/event/powerlevels.go generated vendored Normal file
View File

@@ -0,0 +1,136 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"sync"
"maunium.net/go/mautrix/id"
)
// PowerLevelsEventContent represents the content of a m.room.power_levels state event content.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-power-levels
type PowerLevelsEventContent struct {
usersLock sync.RWMutex `json:"-"`
Users map[id.UserID]int `json:"users,omitempty"`
UsersDefault int `json:"users_default,omitempty"`
eventsLock sync.RWMutex `json:"-"`
Events map[string]int `json:"events,omitempty"`
EventsDefault int `json:"events_default,omitempty"`
StateDefaultPtr *int `json:"state_default,omitempty"`
InvitePtr *int `json:"invite,omitempty"`
KickPtr *int `json:"kick,omitempty"`
BanPtr *int `json:"ban,omitempty"`
RedactPtr *int `json:"redact,omitempty"`
HistoricalPtr *int `json:"historical,omitempty"`
}
func (pl *PowerLevelsEventContent) Invite() int {
if pl.InvitePtr != nil {
return *pl.InvitePtr
}
return 50
}
func (pl *PowerLevelsEventContent) Kick() int {
if pl.KickPtr != nil {
return *pl.KickPtr
}
return 50
}
func (pl *PowerLevelsEventContent) Ban() int {
if pl.BanPtr != nil {
return *pl.BanPtr
}
return 50
}
func (pl *PowerLevelsEventContent) Redact() int {
if pl.RedactPtr != nil {
return *pl.RedactPtr
}
return 50
}
func (pl *PowerLevelsEventContent) Historical() int {
if pl.HistoricalPtr != nil {
return *pl.HistoricalPtr
}
return 100
}
func (pl *PowerLevelsEventContent) StateDefault() int {
if pl.StateDefaultPtr != nil {
return *pl.StateDefaultPtr
}
return 50
}
func (pl *PowerLevelsEventContent) GetUserLevel(userID id.UserID) int {
pl.usersLock.RLock()
defer pl.usersLock.RUnlock()
level, ok := pl.Users[userID]
if !ok {
return pl.UsersDefault
}
return level
}
func (pl *PowerLevelsEventContent) SetUserLevel(userID id.UserID, level int) {
pl.usersLock.Lock()
defer pl.usersLock.Unlock()
if level == pl.UsersDefault {
delete(pl.Users, userID)
} else {
pl.Users[userID] = level
}
}
func (pl *PowerLevelsEventContent) EnsureUserLevel(userID id.UserID, level int) bool {
existingLevel := pl.GetUserLevel(userID)
if existingLevel != level {
pl.SetUserLevel(userID, level)
return true
}
return false
}
func (pl *PowerLevelsEventContent) GetEventLevel(eventType Type) int {
pl.eventsLock.RLock()
defer pl.eventsLock.RUnlock()
level, ok := pl.Events[eventType.String()]
if !ok {
if eventType.IsState() {
return pl.StateDefault()
}
return pl.EventsDefault
}
return level
}
func (pl *PowerLevelsEventContent) SetEventLevel(eventType Type, level int) {
pl.eventsLock.Lock()
defer pl.eventsLock.Unlock()
if (eventType.IsState() && level == pl.StateDefault()) || (!eventType.IsState() && level == pl.EventsDefault) {
delete(pl.Events, eventType.String())
} else {
pl.Events[eventType.String()] = level
}
}
func (pl *PowerLevelsEventContent) EnsureEventLevel(eventType Type, level int) bool {
existingLevel := pl.GetEventLevel(eventType)
if existingLevel != level {
pl.SetEventLevel(eventType, level)
return true
}
return false
}

200
vendor/maunium.net/go/mautrix/event/relations.go generated vendored Normal file
View File

@@ -0,0 +1,200 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"maunium.net/go/mautrix/id"
)
type RelationType string
const (
RelReplace RelationType = "m.replace"
RelReference RelationType = "m.reference"
RelAnnotation RelationType = "m.annotation"
RelReply RelationType = "net.maunium.reply"
)
type RelatesTo struct {
Type RelationType
EventID id.EventID
Key string
}
type serializableInReplyTo struct {
EventID id.EventID `json:"event_id,omitempty"`
}
type serializableRelatesTo struct {
InReplyTo *serializableInReplyTo `json:"m.in_reply_to,omitempty"`
Type RelationType `json:"rel_type,omitempty"`
EventID id.EventID `json:"event_id,omitempty"`
Key string `json:"key,omitempty"`
}
func (rel *RelatesTo) GetReplaceID() id.EventID {
if rel.Type == RelReplace {
return rel.EventID
}
return ""
}
func (rel *RelatesTo) GetReferenceID() id.EventID {
if rel.Type == RelReference {
return rel.EventID
}
return ""
}
func (rel *RelatesTo) GetReplyID() id.EventID {
if rel.Type == RelReply {
return rel.EventID
}
return ""
}
func (rel *RelatesTo) GetAnnotationID() id.EventID {
if rel.Type == RelAnnotation {
return rel.EventID
}
return ""
}
func (rel *RelatesTo) GetAnnotationKey() string {
if rel.Type == RelAnnotation {
return rel.Key
}
return ""
}
func (rel *RelatesTo) UnmarshalJSON(data []byte) error {
var srel serializableRelatesTo
if err := json.Unmarshal(data, &srel); err != nil {
return err
}
if len(srel.Type) > 0 {
rel.Type = srel.Type
rel.EventID = srel.EventID
rel.Key = srel.Key
} else if srel.InReplyTo != nil && len(srel.InReplyTo.EventID) > 0 {
rel.Type = RelReply
rel.EventID = srel.InReplyTo.EventID
rel.Key = ""
}
return nil
}
func (rel *RelatesTo) MarshalJSON() ([]byte, error) {
srel := serializableRelatesTo{Type: rel.Type, EventID: rel.EventID, Key: rel.Key}
if rel.Type == RelReply {
srel.InReplyTo = &serializableInReplyTo{rel.EventID}
}
return json.Marshal(&srel)
}
type RelationChunkItem struct {
Type RelationType `json:"type"`
EventID string `json:"event_id,omitempty"`
Key string `json:"key,omitempty"`
Count int `json:"count,omitempty"`
}
type RelationChunk struct {
Chunk []RelationChunkItem `json:"chunk"`
Limited bool `json:"limited"`
Count int `json:"count"`
}
type AnnotationChunk struct {
RelationChunk
Map map[string]int `json:"-"`
}
type serializableAnnotationChunk AnnotationChunk
func (ac *AnnotationChunk) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, (*serializableAnnotationChunk)(ac)); err != nil {
return err
}
ac.Map = make(map[string]int)
for _, item := range ac.Chunk {
ac.Map[item.Key] += item.Count
}
return nil
}
func (ac *AnnotationChunk) Serialize() RelationChunk {
ac.Chunk = make([]RelationChunkItem, len(ac.Map))
i := 0
for key, count := range ac.Map {
ac.Chunk[i] = RelationChunkItem{
Type: RelAnnotation,
Key: key,
Count: count,
}
}
return ac.RelationChunk
}
type EventIDChunk struct {
RelationChunk
List []string `json:"-"`
}
type serializableEventIDChunk EventIDChunk
func (ec *EventIDChunk) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, (*serializableEventIDChunk)(ec)); err != nil {
return err
}
for _, item := range ec.Chunk {
ec.List = append(ec.List, item.EventID)
}
return nil
}
func (ec *EventIDChunk) Serialize(typ RelationType) RelationChunk {
ec.Chunk = make([]RelationChunkItem, len(ec.List))
for i, eventID := range ec.List {
ec.Chunk[i] = RelationChunkItem{
Type: typ,
EventID: eventID,
}
}
return ec.RelationChunk
}
type Relations struct {
Raw map[RelationType]RelationChunk `json:"-"`
Annotations AnnotationChunk `json:"m.annotation,omitempty"`
References EventIDChunk `json:"m.reference,omitempty"`
Replaces EventIDChunk `json:"m.replace,omitempty"`
}
type serializableRelations Relations
func (relations *Relations) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &relations.Raw); err != nil {
return err
}
return json.Unmarshal(data, (*serializableRelations)(relations))
}
func (relations *Relations) MarshalJSON() ([]byte, error) {
if relations.Raw == nil {
relations.Raw = make(map[RelationType]RelationChunk)
}
relations.Raw[RelAnnotation] = relations.Annotations.Serialize()
relations.Raw[RelReference] = relations.References.Serialize(RelReference)
relations.Raw[RelReplace] = relations.Replaces.Serialize(RelReplace)
return json.Marshal(relations.Raw)
}

108
vendor/maunium.net/go/mautrix/event/reply.go generated vendored Normal file
View File

@@ -0,0 +1,108 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"fmt"
"regexp"
"strings"
"golang.org/x/net/html"
"maunium.net/go/mautrix/id"
)
var HTMLReplyFallbackRegex = regexp.MustCompile(`^<mx-reply>[\s\S]+?</mx-reply>`)
func TrimReplyFallbackHTML(html string) string {
return HTMLReplyFallbackRegex.ReplaceAllString(html, "")
}
func TrimReplyFallbackText(text string) string {
if !strings.HasPrefix(text, "> ") || !strings.Contains(text, "\n") {
return text
}
lines := strings.Split(text, "\n")
for len(lines) > 0 && strings.HasPrefix(lines[0], "> ") {
lines = lines[1:]
}
return strings.TrimSpace(strings.Join(lines, "\n"))
}
func (content *MessageEventContent) RemoveReplyFallback() {
if len(content.GetReplyTo()) > 0 && !content.replyFallbackRemoved {
if content.Format == FormatHTML {
content.FormattedBody = TrimReplyFallbackHTML(content.FormattedBody)
}
content.Body = TrimReplyFallbackText(content.Body)
content.replyFallbackRemoved = true
}
}
func (content *MessageEventContent) GetReplyTo() id.EventID {
if content.RelatesTo != nil && content.RelatesTo.Type == RelReply {
return content.RelatesTo.EventID
}
return ""
}
const ReplyFormat = `<mx-reply><blockquote><a href="https://matrix.to/#/%s/%s">In reply to</a> <a href="https://matrix.to/#/%s">%s</a><br>%s</blockquote></mx-reply>`
func (evt *Event) GenerateReplyFallbackHTML() string {
parsedContent, ok := evt.Content.Parsed.(*MessageEventContent)
if !ok {
return ""
}
parsedContent.RemoveReplyFallback()
body := parsedContent.FormattedBody
if len(body) == 0 {
body = html.EscapeString(parsedContent.Body)
}
senderDisplayName := evt.Sender
return fmt.Sprintf(ReplyFormat, evt.RoomID, evt.ID, evt.Sender, senderDisplayName, body)
}
func (evt *Event) GenerateReplyFallbackText() string {
parsedContent, ok := evt.Content.Parsed.(*MessageEventContent)
if !ok {
return ""
}
parsedContent.RemoveReplyFallback()
body := parsedContent.Body
lines := strings.Split(strings.TrimSpace(body), "\n")
firstLine, lines := lines[0], lines[1:]
senderDisplayName := evt.Sender
var fallbackText strings.Builder
_, _ = fmt.Fprintf(&fallbackText, "> <%s> %s", senderDisplayName, firstLine)
for _, line := range lines {
_, _ = fmt.Fprintf(&fallbackText, "\n> %s", line)
}
fallbackText.WriteString("\n\n")
return fallbackText.String()
}
func (content *MessageEventContent) SetReply(inReplyTo *Event) {
content.RelatesTo = &RelatesTo{
EventID: inReplyTo.ID,
Type: RelReply,
}
if content.MsgType == MsgText || content.MsgType == MsgNotice {
if len(content.FormattedBody) == 0 || content.Format != FormatHTML {
content.FormattedBody = html.EscapeString(content.Body)
content.Format = FormatHTML
}
content.FormattedBody = inReplyTo.GenerateReplyFallbackHTML() + content.FormattedBody
content.Body = inReplyTo.GenerateReplyFallbackText() + content.Body
content.replyFallbackRemoved = false
}
}

138
vendor/maunium.net/go/mautrix/event/state.go generated vendored Normal file
View File

@@ -0,0 +1,138 @@
// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"maunium.net/go/mautrix/id"
)
// CanonicalAliasEventContent represents the content of a m.room.canonical_alias state event.
// https://matrix.org/docs/spec/client_server/r0.6.1#m-room-canonical-alias
type CanonicalAliasEventContent struct {
Alias id.RoomAlias `json:"alias"`
AltAliases []id.RoomAlias `json:"alt_aliases,omitempty"`
}
// RoomNameEventContent represents the content of a m.room.name state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-name
type RoomNameEventContent struct {
Name string `json:"name"`
}
// RoomAvatarEventContent represents the content of a m.room.avatar state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-avatar
type RoomAvatarEventContent struct {
URL id.ContentURI `json:"url"`
}
// TopicEventContent represents the content of a m.room.topic state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-topic
type TopicEventContent struct {
Topic string `json:"topic"`
}
// TombstoneEventContent represents the content of a m.room.tombstone state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-tombstone
type TombstoneEventContent struct {
Body string `json:"body"`
ReplacementRoom id.RoomID `json:"replacement_room"`
}
// CreateEventContent represents the content of a m.room.create state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-create
type CreateEventContent struct {
Type RoomType `json:"type,omitempty"`
Creator id.UserID `json:"creator,omitempty"`
Federate bool `json:"m.federate,omitempty"`
RoomVersion string `json:"version,omitempty"`
Predecessor struct {
RoomID id.RoomID `json:"room_id"`
EventID id.EventID `json:"event_id"`
} `json:"predecessor"`
}
// JoinRule specifies how open a room is to new members.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-join-rules
type JoinRule string
const (
JoinRulePublic JoinRule = "public"
JoinRuleKnock JoinRule = "knock"
JoinRuleInvite JoinRule = "invite"
JoinRulePrivate JoinRule = "private"
)
// JoinRulesEventContent represents the content of a m.room.join_rules state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-join-rules
type JoinRulesEventContent struct {
JoinRule JoinRule `json:"join_rule"`
}
// PinnedEventsEventContent represents the content of a m.room.pinned_events state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-pinned-events
type PinnedEventsEventContent struct {
Pinned []id.EventID `json:"pinned"`
}
// HistoryVisibility specifies who can see new messages.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-history-visibility
type HistoryVisibility string
const (
HistoryVisibilityInvited HistoryVisibility = "invited"
HistoryVisibilityJoined HistoryVisibility = "joined"
HistoryVisibilityShared HistoryVisibility = "shared"
HistoryVisibilityWorldReadable HistoryVisibility = "world_readable"
)
// HistoryVisibilityEventContent represents the content of a m.room.history_visibility state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-history-visibility
type HistoryVisibilityEventContent struct {
HistoryVisibility HistoryVisibility `json:"history_visibility"`
}
// GuestAccess specifies whether or not guest accounts can join.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-guest-access
type GuestAccess string
const (
GuestAccessCanJoin GuestAccess = "can_join"
GuestAccessForbidden GuestAccess = "forbidden"
)
// GuestAccessEventContent represents the content of a m.room.guest_access state event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-guest-access
type GuestAccessEventContent struct {
GuestAccess GuestAccess `json:"guest_access"`
}
type BridgeInfoSection struct {
ID string `json:"id"`
DisplayName string `json:"displayname,omitempty"`
AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
ExternalURL string `json:"external_url,omitempty"`
}
// BridgeEventContent represents the content of a m.bridge state event.
// https://github.com/matrix-org/matrix-doc/pull/2346
type BridgeEventContent struct {
BridgeBot id.UserID `json:"bridgebot"`
Creator id.UserID `json:"creator,omitempty"`
Protocol BridgeInfoSection `json:"protocol"`
Network *BridgeInfoSection `json:"network,omitempty"`
Channel BridgeInfoSection `json:"channel"`
}
type SpaceChildEventContent struct {
Via []string `json:"via,omitempty"`
Order string `json:"order,omitempty"`
}
type SpaceParentEventContent struct {
Via []string `json:"via,omitempty"`
Canonical bool `json:"canonical,omitempty"`
}

248
vendor/maunium.net/go/mautrix/event/type.go generated vendored Normal file
View File

@@ -0,0 +1,248 @@
// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"fmt"
"strings"
)
type RoomType string
const (
RoomTypeDefault RoomType = ""
RoomTypeSpace RoomType = "m.space"
)
type TypeClass int
func (tc TypeClass) Name() string {
switch tc {
case MessageEventType:
return "message"
case StateEventType:
return "state"
case EphemeralEventType:
return "ephemeral"
case AccountDataEventType:
return "account data"
case ToDeviceEventType:
return "to-device"
default:
return "unknown"
}
}
const (
// Unknown events
UnknownEventType TypeClass = iota
// Normal message events
MessageEventType
// State events
StateEventType
// Ephemeral events
EphemeralEventType
// Account data events
AccountDataEventType
// Device-to-device events
ToDeviceEventType
)
type Type struct {
Type string
Class TypeClass
}
func NewEventType(name string) Type {
evtType := Type{Type: name}
evtType.Class = evtType.GuessClass()
return evtType
}
func (et *Type) IsState() bool {
return et.Class == StateEventType
}
func (et *Type) IsEphemeral() bool {
return et.Class == EphemeralEventType
}
func (et *Type) IsAccountData() bool {
return et.Class == AccountDataEventType
}
func (et *Type) IsToDevice() bool {
return et.Class == ToDeviceEventType
}
func (et *Type) IsInRoomVerification() bool {
switch et.Type {
case InRoomVerificationStart.Type, InRoomVerificationReady.Type, InRoomVerificationAccept.Type,
InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type:
return true
default:
return false
}
}
func (et *Type) IsCall() bool {
switch et.Type {
case CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
CallNegotiate.Type, CallHangup.Type:
return true
default:
return false
}
}
func (et *Type) IsCustom() bool {
return !strings.HasPrefix(et.Type, "m.")
}
func (et *Type) GuessClass() TypeClass {
switch et.Type {
case StateAliases.Type, StateCanonicalAlias.Type, StateCreate.Type, StateJoinRules.Type, StateMember.Type,
StatePowerLevels.Type, StateRoomName.Type, StateRoomAvatar.Type, StateTopic.Type, StatePinnedEvents.Type,
StateTombstone.Type, StateEncryption.Type, StateBridge.Type, StateHalfShotBridge.Type, StateSpaceParent.Type,
StateSpaceChild.Type:
return StateEventType
case EphemeralEventReceipt.Type, EphemeralEventTyping.Type, EphemeralEventPresence.Type:
return EphemeralEventType
case AccountDataDirectChats.Type, AccountDataPushRules.Type, AccountDataRoomTags.Type,
AccountDataSecretStorageKey.Type, AccountDataSecretStorageDefaultKey.Type,
AccountDataCrossSigningMaster.Type, AccountDataCrossSigningSelf.Type, AccountDataCrossSigningUser.Type:
return AccountDataEventType
case EventRedaction.Type, EventMessage.Type, EventEncrypted.Type, EventReaction.Type, EventSticker.Type,
InRoomVerificationStart.Type, InRoomVerificationReady.Type, InRoomVerificationAccept.Type,
InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type,
CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
CallNegotiate.Type, CallHangup.Type:
return MessageEventType
case ToDeviceRoomKey.Type, ToDeviceRoomKeyRequest.Type, ToDeviceForwardedRoomKey.Type, ToDeviceRoomKeyWithheld.Type:
return ToDeviceEventType
default:
return UnknownEventType
}
}
func (et *Type) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, &et.Type)
if err != nil {
return err
}
et.Class = et.GuessClass()
return nil
}
func (et *Type) MarshalJSON() ([]byte, error) {
return json.Marshal(&et.Type)
}
func (et Type) UnmarshalText(data []byte) error {
et.Type = string(data)
et.Class = et.GuessClass()
return nil
}
func (et Type) MarshalText() ([]byte, error) {
return []byte(et.Type), nil
}
func (et *Type) String() string {
return et.Type
}
func (et *Type) Repr() string {
return fmt.Sprintf("%s (%s)", et.Type, et.Class.Name())
}
// State events
var (
StateAliases = Type{"m.room.aliases", StateEventType}
StateCanonicalAlias = Type{"m.room.canonical_alias", StateEventType}
StateCreate = Type{"m.room.create", StateEventType}
StateJoinRules = Type{"m.room.join_rules", StateEventType}
StateHistoryVisibility = Type{"m.room.history_visibility", StateEventType}
StateGuestAccess = Type{"m.room.guest_access", StateEventType}
StateMember = Type{"m.room.member", StateEventType}
StatePowerLevels = Type{"m.room.power_levels", StateEventType}
StateRoomName = Type{"m.room.name", StateEventType}
StateTopic = Type{"m.room.topic", StateEventType}
StateRoomAvatar = Type{"m.room.avatar", StateEventType}
StatePinnedEvents = Type{"m.room.pinned_events", StateEventType}
StateTombstone = Type{"m.room.tombstone", StateEventType}
StateEncryption = Type{"m.room.encryption", StateEventType}
StateBridge = Type{"m.bridge", StateEventType}
StateHalfShotBridge = Type{"uk.half-shot.bridge", StateEventType}
StateSpaceChild = Type{"m.space.child", StateEventType}
StateSpaceParent = Type{"m.space.parent", StateEventType}
)
// Message events
var (
EventRedaction = Type{"m.room.redaction", MessageEventType}
EventMessage = Type{"m.room.message", MessageEventType}
EventEncrypted = Type{"m.room.encrypted", MessageEventType}
EventReaction = Type{"m.reaction", MessageEventType}
EventSticker = Type{"m.sticker", MessageEventType}
InRoomVerificationStart = Type{"m.key.verification.start", MessageEventType}
InRoomVerificationReady = Type{"m.key.verification.ready", MessageEventType}
InRoomVerificationAccept = Type{"m.key.verification.accept", MessageEventType}
InRoomVerificationKey = Type{"m.key.verification.key", MessageEventType}
InRoomVerificationMAC = Type{"m.key.verification.mac", MessageEventType}
InRoomVerificationCancel = Type{"m.key.verification.cancel", MessageEventType}
CallInvite = Type{"m.call.invite", MessageEventType}
CallCandidates = Type{"m.call.candidates", MessageEventType}
CallAnswer = Type{"m.call.answer", MessageEventType}
CallReject = Type{"m.call.reject", MessageEventType}
CallSelectAnswer = Type{"m.call.select_answer", MessageEventType}
CallNegotiate = Type{"m.call.negotiate", MessageEventType}
CallHangup = Type{"m.call.hangup", MessageEventType}
)
// Ephemeral events
var (
EphemeralEventReceipt = Type{"m.receipt", EphemeralEventType}
EphemeralEventTyping = Type{"m.typing", EphemeralEventType}
EphemeralEventPresence = Type{"m.presence", EphemeralEventType}
)
// Account data events
var (
AccountDataDirectChats = Type{"m.direct", AccountDataEventType}
AccountDataPushRules = Type{"m.push_rules", AccountDataEventType}
AccountDataRoomTags = Type{"m.tag", AccountDataEventType}
AccountDataFullyRead = Type{"m.fully_read", AccountDataEventType}
AccountDataIgnoredUserList = Type{"m.ignored_user_list", AccountDataEventType}
AccountDataSecretStorageDefaultKey = Type{"m.secret_storage.default_key", AccountDataEventType}
AccountDataSecretStorageKey = Type{"m.secret_storage.key", AccountDataEventType}
AccountDataCrossSigningMaster = Type{"m.cross_signing.master", AccountDataEventType}
AccountDataCrossSigningUser = Type{"m.cross_signing.user_signing", AccountDataEventType}
AccountDataCrossSigningSelf = Type{"m.cross_signing.self_signing", AccountDataEventType}
)
// Device-to-device events
var (
ToDeviceRoomKey = Type{"m.room_key", ToDeviceEventType}
ToDeviceRoomKeyRequest = Type{"m.room_key_request", ToDeviceEventType}
ToDeviceForwardedRoomKey = Type{"m.forwarded_room_key", ToDeviceEventType}
ToDeviceEncrypted = Type{"m.room.encrypted", ToDeviceEventType}
ToDeviceRoomKeyWithheld = Type{"m.room_key.withheld", ToDeviceEventType}
ToDeviceDummy = Type{"m.dummy", ToDeviceEventType}
ToDeviceVerificationRequest = Type{"m.key.verification.request", ToDeviceEventType}
ToDeviceVerificationStart = Type{"m.key.verification.start", ToDeviceEventType}
ToDeviceVerificationAccept = Type{"m.key.verification.accept", ToDeviceEventType}
ToDeviceVerificationKey = Type{"m.key.verification.key", ToDeviceEventType}
ToDeviceVerificationMAC = Type{"m.key.verification.mac", ToDeviceEventType}
ToDeviceVerificationCancel = Type{"m.key.verification.cancel", ToDeviceEventType}
ToDeviceOrgMatrixRoomKeyWithheld = Type{"org.matrix.room_key.withheld", ToDeviceEventType}
)

306
vendor/maunium.net/go/mautrix/event/verification.go generated vendored Normal file
View File

@@ -0,0 +1,306 @@
// Copyright (c) 2020 Nikos Filippakis
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"maunium.net/go/mautrix/id"
)
type VerificationMethod string
const VerificationMethodSAS VerificationMethod = "m.sas.v1"
// VerificationRequestEventContent represents the content of a m.key.verification.request to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-request
type VerificationRequestEventContent struct {
// The device ID which is initiating the request.
FromDevice id.DeviceID `json:"from_device"`
// An opaque identifier for the verification request. Must be unique with respect to the devices involved.
TransactionID string `json:"transaction_id,omitempty"`
// The verification methods supported by the sender.
Methods []VerificationMethod `json:"methods"`
// The POSIX timestamp in milliseconds for when the request was made.
Timestamp int64 `json:"timestamp,omitempty"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vrec *VerificationRequestEventContent) SupportsVerificationMethod(meth VerificationMethod) bool {
for _, supportedMeth := range vrec.Methods {
if supportedMeth == meth {
return true
}
}
return false
}
type KeyAgreementProtocol string
const (
KeyAgreementCurve25519 KeyAgreementProtocol = "curve25519"
KeyAgreementCurve25519HKDFSHA256 KeyAgreementProtocol = "curve25519-hkdf-sha256"
)
type VerificationHashMethod string
const VerificationHashSHA256 VerificationHashMethod = "sha256"
type MACMethod string
const HKDFHMACSHA256 MACMethod = "hkdf-hmac-sha256"
type SASMethod string
const (
SASDecimal SASMethod = "decimal"
SASEmoji SASMethod = "emoji"
)
// VerificationStartEventContent represents the content of a m.key.verification.start to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-start
type VerificationStartEventContent struct {
// The device ID which is initiating the process.
FromDevice id.DeviceID `json:"from_device"`
// An opaque identifier for the verification process. Must be unique with respect to the devices involved.
TransactionID string `json:"transaction_id,omitempty"`
// The verification method to use.
Method VerificationMethod `json:"method"`
// The key agreement protocols the sending device understands.
KeyAgreementProtocols []KeyAgreementProtocol `json:"key_agreement_protocols"`
// The hash methods the sending device understands.
Hashes []VerificationHashMethod `json:"hashes"`
// The message authentication codes that the sending device understands.
MessageAuthenticationCodes []MACMethod `json:"message_authentication_codes"`
// The SAS methods the sending device (and the sending device's user) understands.
ShortAuthenticationString []SASMethod `json:"short_authentication_string"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vsec *VerificationStartEventContent) SupportsKeyAgreementProtocol(proto KeyAgreementProtocol) bool {
for _, supportedProto := range vsec.KeyAgreementProtocols {
if supportedProto == proto {
return true
}
}
return false
}
func (vsec *VerificationStartEventContent) SupportsHashMethod(alg VerificationHashMethod) bool {
for _, supportedAlg := range vsec.Hashes {
if supportedAlg == alg {
return true
}
}
return false
}
func (vsec *VerificationStartEventContent) SupportsMACMethod(meth MACMethod) bool {
for _, supportedMeth := range vsec.MessageAuthenticationCodes {
if supportedMeth == meth {
return true
}
}
return false
}
func (vsec *VerificationStartEventContent) SupportsSASMethod(meth SASMethod) bool {
for _, supportedMeth := range vsec.ShortAuthenticationString {
if supportedMeth == meth {
return true
}
}
return false
}
func (vsec *VerificationStartEventContent) GetRelatesTo() *RelatesTo {
if vsec.RelatesTo == nil {
vsec.RelatesTo = &RelatesTo{}
}
return vsec.RelatesTo
}
func (vsec *VerificationStartEventContent) OptionalGetRelatesTo() *RelatesTo {
return vsec.RelatesTo
}
func (vsec *VerificationStartEventContent) SetRelatesTo(rel *RelatesTo) {
vsec.RelatesTo = rel
}
// VerificationReadyEventContent represents the content of a m.key.verification.ready event.
type VerificationReadyEventContent struct {
// The device ID which accepted the process.
FromDevice id.DeviceID `json:"from_device"`
// The verification methods supported by the sender.
Methods []VerificationMethod `json:"methods"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
var _ Relatable = (*VerificationReadyEventContent)(nil)
func (vrec *VerificationReadyEventContent) GetRelatesTo() *RelatesTo {
if vrec.RelatesTo == nil {
vrec.RelatesTo = &RelatesTo{}
}
return vrec.RelatesTo
}
func (vrec *VerificationReadyEventContent) OptionalGetRelatesTo() *RelatesTo {
return vrec.RelatesTo
}
func (vrec *VerificationReadyEventContent) SetRelatesTo(rel *RelatesTo) {
vrec.RelatesTo = rel
}
// VerificationAcceptEventContent represents the content of a m.key.verification.accept to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-accept
type VerificationAcceptEventContent struct {
// An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
TransactionID string `json:"transaction_id,omitempty"`
// The verification method to use.
Method VerificationMethod `json:"method"`
// The key agreement protocol the device is choosing to use, out of the options in the m.key.verification.start message.
KeyAgreementProtocol KeyAgreementProtocol `json:"key_agreement_protocol"`
// The hash method the device is choosing to use, out of the options in the m.key.verification.start message.
Hash VerificationHashMethod `json:"hash"`
// The message authentication code the device is choosing to use, out of the options in the m.key.verification.start message.
MessageAuthenticationCode MACMethod `json:"message_authentication_code"`
// The SAS methods both devices involved in the verification process understand. Must be a subset of the options in the m.key.verification.start message.
ShortAuthenticationString []SASMethod `json:"short_authentication_string"`
// The hash (encoded as unpadded base64) of the concatenation of the device's ephemeral public key (encoded as unpadded base64) and the canonical JSON representation of the m.key.verification.start message.
Commitment string `json:"commitment"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vaec *VerificationAcceptEventContent) GetRelatesTo() *RelatesTo {
if vaec.RelatesTo == nil {
vaec.RelatesTo = &RelatesTo{}
}
return vaec.RelatesTo
}
func (vaec *VerificationAcceptEventContent) OptionalGetRelatesTo() *RelatesTo {
return vaec.RelatesTo
}
func (vaec *VerificationAcceptEventContent) SetRelatesTo(rel *RelatesTo) {
vaec.RelatesTo = rel
}
// VerificationKeyEventContent represents the content of a m.key.verification.key to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-key
type VerificationKeyEventContent struct {
// An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
TransactionID string `json:"transaction_id,omitempty"`
// The device's ephemeral public key, encoded as unpadded base64.
Key string `json:"key"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vkec *VerificationKeyEventContent) GetRelatesTo() *RelatesTo {
if vkec.RelatesTo == nil {
vkec.RelatesTo = &RelatesTo{}
}
return vkec.RelatesTo
}
func (vkec *VerificationKeyEventContent) OptionalGetRelatesTo() *RelatesTo {
return vkec.RelatesTo
}
func (vkec *VerificationKeyEventContent) SetRelatesTo(rel *RelatesTo) {
vkec.RelatesTo = rel
}
// VerificationMacEventContent represents the content of a m.key.verification.mac to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-mac
type VerificationMacEventContent struct {
// An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
TransactionID string `json:"transaction_id,omitempty"`
// A map of the key ID to the MAC of the key, using the algorithm in the verification process. The MAC is encoded as unpadded base64.
Mac map[id.KeyID]string `json:"mac"`
// The MAC of the comma-separated, sorted, list of key IDs given in the mac property, encoded as unpadded base64.
Keys string `json:"keys"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vmec *VerificationMacEventContent) GetRelatesTo() *RelatesTo {
if vmec.RelatesTo == nil {
vmec.RelatesTo = &RelatesTo{}
}
return vmec.RelatesTo
}
func (vmec *VerificationMacEventContent) OptionalGetRelatesTo() *RelatesTo {
return vmec.RelatesTo
}
func (vmec *VerificationMacEventContent) SetRelatesTo(rel *RelatesTo) {
vmec.RelatesTo = rel
}
type VerificationCancelCode string
const (
VerificationCancelByUser VerificationCancelCode = "m.user"
VerificationCancelByTimeout VerificationCancelCode = "m.timeout"
VerificationCancelUnknownTransaction VerificationCancelCode = "m.unknown_transaction"
VerificationCancelUnknownMethod VerificationCancelCode = "m.unknown_method"
VerificationCancelUnexpectedMessage VerificationCancelCode = "m.unexpected_message"
VerificationCancelKeyMismatch VerificationCancelCode = "m.key_mismatch"
VerificationCancelUserMismatch VerificationCancelCode = "m.user_mismatch"
VerificationCancelInvalidMessage VerificationCancelCode = "m.invalid_message"
VerificationCancelAccepted VerificationCancelCode = "m.accepted"
VerificationCancelSASMismatch VerificationCancelCode = "m.mismatched_sas"
VerificationCancelCommitmentMismatch VerificationCancelCode = "m.mismatched_commitment"
)
// VerificationCancelEventContent represents the content of a m.key.verification.cancel to_device event.
// https://matrix.org/docs/spec/client_server/r0.6.0#m-key-verification-cancel
type VerificationCancelEventContent struct {
// The opaque identifier for the verification process/request.
TransactionID string `json:"transaction_id,omitempty"`
// A human readable description of the code. The client should only rely on this string if it does not understand the code.
Reason string `json:"reason"`
// The error code for why the process/request was cancelled by the user.
Code VerificationCancelCode `json:"code"`
// The user that the event is sent to for in-room verification.
To id.UserID `json:"to,omitempty"`
// Original event ID for in-room verification.
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
}
func (vcec *VerificationCancelEventContent) GetRelatesTo() *RelatesTo {
if vcec.RelatesTo == nil {
vcec.RelatesTo = &RelatesTo{}
}
return vcec.RelatesTo
}
func (vcec *VerificationCancelEventContent) OptionalGetRelatesTo() *RelatesTo {
return vcec.RelatesTo
}
func (vcec *VerificationCancelEventContent) SetRelatesTo(rel *RelatesTo) {
vcec.RelatesTo = rel
}

116
vendor/maunium.net/go/mautrix/event/voip.go generated vendored Normal file
View File

@@ -0,0 +1,116 @@
// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package event
import (
"encoding/json"
"fmt"
"strconv"
)
type CallHangupReason string
const (
CallHangupICEFailed CallHangupReason = "ice_failed"
CallHangupInviteTimeout CallHangupReason = "invite_timeout"
CallHangupUserHangup CallHangupReason = "user_hangup"
CallHangupUserMediaFailed CallHangupReason = "user_media_failed"
CallHangupUnknownError CallHangupReason = "unknown_error"
)
type CallDataType string
const (
CallDataTypeOffer CallDataType = "offer"
CallDataTypeAnswer CallDataType = "answer"
)
type CallData struct {
SDP string `json:"sdp"`
Type CallDataType `json:"type"`
}
type CallCandidate struct {
Candidate string `json:"candidate"`
SDPMLineIndex int `json:"sdpMLineIndex"`
SDPMID string `json:"sdpMid"`
}
type CallVersion string
func (cv *CallVersion) UnmarshalJSON(raw []byte) error {
var numberVersion int
err := json.Unmarshal(raw, &numberVersion)
if err != nil {
var stringVersion string
err = json.Unmarshal(raw, &stringVersion)
if err != nil {
return fmt.Errorf("failed to parse CallVersion: %w", err)
}
*cv = CallVersion(stringVersion)
} else {
*cv = CallVersion(strconv.Itoa(numberVersion))
}
return nil
}
func (cv *CallVersion) MarshalJSON() ([]byte, error) {
for _, char := range *cv {
if char < '0' || char > '9' {
// The version contains weird characters, return as string.
return json.Marshal(string(*cv))
}
}
// The version consists of only ASCII digits, return as an integer.
return []byte(*cv), nil
}
func (cv *CallVersion) Int() (int, error) {
return strconv.Atoi(string(*cv))
}
type BaseCallEventContent struct {
CallID string `json:"call_id"`
PartyID string `json:"party_id"`
Version CallVersion `json:"version"`
}
type CallInviteEventContent struct {
BaseCallEventContent
Lifetime int `json:"lifetime"`
Offer CallData `json:"offer"`
}
type CallCandidatesEventContent struct {
BaseCallEventContent
Candidates []CallCandidate `json:"candidates"`
}
type CallRejectEventContent struct {
BaseCallEventContent
}
type CallAnswerEventContent struct {
BaseCallEventContent
Answer CallData `json:"answer"`
}
type CallSelectAnswerEventContent struct {
BaseCallEventContent
SelectedPartyID string `json:"selected_party_id"`
}
type CallNegotiateEventContent struct {
BaseCallEventContent
Lifetime int `json:"lifetime"`
Description CallData `json:"description"`
}
type CallHangupEventContent struct {
BaseCallEventContent
Reason CallHangupReason `json:"reason"`
}

93
vendor/maunium.net/go/mautrix/filter.go generated vendored Normal file
View File

@@ -0,0 +1,93 @@
// Copyright 2017 Jan Christian Grünhage
package mautrix
import (
"errors"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
type EventFormat string
const (
EventFormatClient EventFormat = "client"
EventFormatFederation EventFormat = "federation"
)
//Filter is used by clients to specify how the server should filter responses to e.g. sync requests
//Specified by: https://matrix.org/docs/spec/client_server/r0.6.0.html#filtering
type Filter struct {
AccountData FilterPart `json:"account_data,omitempty"`
EventFields []string `json:"event_fields,omitempty"`
EventFormat EventFormat `json:"event_format,omitempty"`
Presence FilterPart `json:"presence,omitempty"`
Room RoomFilter `json:"room,omitempty"`
}
// RoomFilter is used to define filtering rules for room events
type RoomFilter struct {
AccountData FilterPart `json:"account_data,omitempty"`
Ephemeral FilterPart `json:"ephemeral,omitempty"`
IncludeLeave bool `json:"include_leave,omitempty"`
NotRooms []id.RoomID `json:"not_rooms,omitempty"`
Rooms []id.RoomID `json:"rooms,omitempty"`
State FilterPart `json:"state,omitempty"`
Timeline FilterPart `json:"timeline,omitempty"`
}
// FilterPart is used to define filtering rules for specific categories of events
type FilterPart struct {
NotRooms []id.RoomID `json:"not_rooms,omitempty"`
Rooms []id.RoomID `json:"rooms,omitempty"`
Limit int `json:"limit,omitempty"`
NotSenders []id.UserID `json:"not_senders,omitempty"`
NotTypes []event.Type `json:"not_types,omitempty"`
Senders []id.UserID `json:"senders,omitempty"`
Types []event.Type `json:"types,omitempty"`
ContainsURL *bool `json:"contains_url,omitempty"`
LazyLoadMembers bool `json:"lazy_load_members,omitempty"`
IncludeRedundantMembers bool `json:"include_redundant_members,omitempty"`
}
// Validate checks if the filter contains valid property values
func (filter *Filter) Validate() error {
if filter.EventFormat != EventFormatClient && filter.EventFormat != EventFormatFederation {
return errors.New("Bad event_format value. Must be one of [\"client\", \"federation\"]")
}
return nil
}
// DefaultFilter returns the default filter used by the Matrix server if no filter is provided in the request
func DefaultFilter() Filter {
return Filter{
AccountData: DefaultFilterPart(),
EventFields: nil,
EventFormat: "client",
Presence: DefaultFilterPart(),
Room: RoomFilter{
AccountData: DefaultFilterPart(),
Ephemeral: DefaultFilterPart(),
IncludeLeave: false,
NotRooms: nil,
Rooms: nil,
State: DefaultFilterPart(),
Timeline: DefaultFilterPart(),
},
}
}
// DefaultFilterPart returns the default filter part used by the Matrix server if no filter is provided in the request
func DefaultFilterPart() FilterPart {
return FilterPart{
NotRooms: nil,
Rooms: nil,
Limit: 20,
NotSenders: nil,
NotTypes: nil,
Senders: nil,
Types: nil,
}
}

133
vendor/maunium.net/go/mautrix/id/contenturi.go generated vendored Normal file
View File

@@ -0,0 +1,133 @@
// Copyright (c) 2020 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package id
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strings"
)
var (
InvalidContentURI = errors.New("invalid Matrix content URI")
InputNotJSONString = errors.New("input doesn't look like a JSON string")
)
// ContentURIString is a string that's expected to be a Matrix content URI.
// It's useful for delaying the parsing of the content URI to move errors from the event content
// JSON parsing step to a later step where more appropriate errors can be produced.
type ContentURIString string
func (uriString ContentURIString) Parse() (ContentURI, error) {
return ParseContentURI(string(uriString))
}
func (uriString ContentURIString) ParseOrIgnore() ContentURI {
parsed, _ := ParseContentURI(string(uriString))
return parsed
}
// ContentURI represents a Matrix content URI.
// https://matrix.org/docs/spec/client_server/r0.6.0#matrix-content-mxc-uris
type ContentURI struct {
Homeserver string
FileID string
}
func MustParseContentURI(uri string) ContentURI {
parsed, err := ParseContentURI(uri)
if err != nil {
panic(err)
}
return parsed
}
// ParseContentURI parses a Matrix content URI.
func ParseContentURI(uri string) (parsed ContentURI, err error) {
if len(uri) == 0 {
return
} else if !strings.HasPrefix(uri, "mxc://") {
err = InvalidContentURI
} else if index := strings.IndexRune(uri[6:], '/'); index == -1 || index == len(uri)-7 {
err = InvalidContentURI
} else {
parsed.Homeserver = uri[6 : 6+index]
parsed.FileID = uri[6+index+1:]