Merge branch 'main' into update_activity

This commit is contained in:
tobi 2025-04-22 12:38:50 +02:00
commit ec0888c399
54 changed files with 657 additions and 4177 deletions

16
go.mod
View file

@ -39,7 +39,7 @@ require (
github.com/coreos/go-oidc/v3 v3.12.0
github.com/gin-contrib/cors v1.7.4
github.com/gin-contrib/gzip v1.2.3
github.com/gin-contrib/sessions v1.0.2
github.com/gin-contrib/sessions v1.0.3
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/form/v4 v4.2.1
github.com/go-swagger/go-swagger v0.31.0
@ -62,7 +62,7 @@ require (
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0
github.com/tdewolff/minify/v2 v2.23.0
github.com/tdewolff/minify/v2 v2.23.1
github.com/technologize/otel-go-contrib v1.1.1
github.com/temoto/robotstxt v1.1.2
github.com/tetratelabs/wazero v1.9.0
@ -73,7 +73,7 @@ require (
github.com/uptrace/bun/dialect/sqlitedialect v1.2.11
github.com/uptrace/bun/extra/bunotel v1.2.11
github.com/wagslane/go-password-validator v0.3.0
github.com/yuin/goldmark v1.7.8
github.com/yuin/goldmark v1.7.10
go.opentelemetry.io/otel v1.35.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0
@ -86,7 +86,7 @@ require (
golang.org/x/crypto v0.37.0
golang.org/x/image v0.24.0
golang.org/x/net v0.38.0
golang.org/x/oauth2 v0.27.0
golang.org/x/oauth2 v0.29.0
golang.org/x/sys v0.32.0
golang.org/x/text v0.24.0
gopkg.in/mcuadros/go-syslog.v2 v2.3.0
@ -153,7 +153,7 @@ require (
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.2.2 // indirect
github.com/gorilla/sessions v1.4.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
@ -200,7 +200,7 @@ require (
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tdewolff/parse/v2 v2.7.22 // indirect
github.com/tdewolff/parse/v2 v2.7.23 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@ -208,12 +208,12 @@ require (
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.mongodb.org/mongo-driver v1.17.3 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.15.0 // indirect
golang.org/x/arch v0.16.0 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.13.0 // indirect

32
go.sum generated
View file

@ -139,8 +139,8 @@ github.com/gin-contrib/cors v1.7.4 h1:/fC6/wk7rCRtqKqki8lLr2Xq+hnV49aXDLIuSek9g4
github.com/gin-contrib/cors v1.7.4/go.mod h1:vGc/APSgLMlQfEJV5NAzkrAHb0C8DetL3K6QZuvGii0=
github.com/gin-contrib/gzip v1.2.3 h1:dAhT722RuEG330ce2agAs75z7yB+NKvX/ZM1r8w0u2U=
github.com/gin-contrib/gzip v1.2.3/go.mod h1:ad72i4Bzmaypk8M762gNXa2wkxxjbz0icRNnuLJ9a/c=
github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA=
github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs=
github.com/gin-contrib/sessions v1.0.3 h1:AZ4j0AalLsGqdrKNbbrKcXx9OJZqViirvNGsJTxcQps=
github.com/gin-contrib/sessions v1.0.3/go.mod h1:5i4XMx4KPtQihnzxEqG9u1K446lO3G19jAi2GtbfsAI=
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
@ -241,8 +241,8 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
@ -412,10 +412,10 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tdewolff/minify/v2 v2.23.0 h1:ZdVmMkGYApnUpmOL/H/PCEk6qg6OFHzVDXgk07z9TW0=
github.com/tdewolff/minify/v2 v2.23.0/go.mod h1:ll/rxPfOGIgN9G4JXg+3jMtPTPEnEJB3nGtEG08sHl8=
github.com/tdewolff/parse/v2 v2.7.22 h1:ROVbrjtp5RoXi22YSZaOks5DaOcXBJ3PZO5hyyQ9Bbs=
github.com/tdewolff/parse/v2 v2.7.22/go.mod h1:I7TXO37t3aSG9SlPUBefAhgIF8nt7yYUwVGgETIoBcA=
github.com/tdewolff/minify/v2 v2.23.1 h1:r6sKQrumHzskWZRdhiRa+pZhn7CdBMojACNP9fuKpXQ=
github.com/tdewolff/minify/v2 v2.23.1/go.mod h1:RkUGjklq6uIsBoOdzY3ll35HKKQ2aFqLQhnanBHhDyU=
github.com/tdewolff/parse/v2 v2.7.23 h1:sCW2PNTCM1yVldh5YK/8wrpRI9rSbloUZWjAydlN2IA=
github.com/tdewolff/parse/v2 v2.7.23/go.mod h1:I7TXO37t3aSG9SlPUBefAhgIF8nt7yYUwVGgETIoBcA=
github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/technologize/otel-go-contrib v1.1.1 h1:wZH9aSPNWZWIkEh3vfaKfMb15AJ80jJ1aVj/4GZdqIw=
@ -487,12 +487,12 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.10 h1:S+LrtBjRmqMac2UdtB6yyCEJm+UILZ2fefI4p7o0QpI=
github.com/yuin/goldmark v1.7.10/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.37.0-concurrency-workaround h1:QbfrBqNKgAFSSK89fYf547vxDQuz8p6iJUzzAMrusNk=
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.37.0-concurrency-workaround/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
@ -521,8 +521,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@ -562,8 +562,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View file

@ -267,7 +267,7 @@ func (p *Processor) importOrUpdateDomainPerm(
}
var errWithCode gtserror.WithCode
if domainPerm != nil {
if !util.IsNil(domainPerm) {
// Permission already exists, update it.
apiDomainPerm, errWithCode = p.DomainPermissionUpdate(
ctx,
@ -394,15 +394,21 @@ func (p *Processor) DomainPermissionGet(
err = gtserror.New("unrecognized permission type")
}
if err != nil {
if errors.Is(err, db.ErrNoEntries) {
err = fmt.Errorf("no domain %s exists with id %s", permissionType.String(), id)
return nil, gtserror.NewErrorNotFound(err, err.Error())
}
err = gtserror.Newf("error getting domain %s with id %s: %w", permissionType.String(), id, err)
if err != nil && errors.Is(err, db.ErrNoEntries) {
err = gtserror.Newf(
"db error getting domain %s with id %s: %w",
permissionType.String(), id, err,
)
return nil, gtserror.NewErrorInternalError(err)
}
if util.IsNil(domainPerm) {
errText := fmt.Sprintf(
"no domain %s exists with id %s",
permissionType.String(), id,
)
return nil, gtserror.NewErrorNotFound(errors.New(errText), errText)
}
return p.apiDomainPerm(ctx, domainPerm, export)
}

View file

@ -249,7 +249,7 @@ func (m *Module) profileMicroblog(c *gin.Context, p *profile) {
},
{
Bottom: true,
Src: jsBlurhash,
Src: jsFrontendPrerender,
},
},
Extra: map[string]any{
@ -323,7 +323,7 @@ func (m *Module) profileGallery(c *gin.Context, p *profile) {
},
{
Bottom: true,
Src: jsBlurhash,
Src: jsFrontendPrerender,
},
},
Extra: map[string]any{

View file

@ -154,7 +154,7 @@ func (m *Module) threadGETHandler(c *gin.Context) {
},
{
Bottom: true,
Src: jsBlurhash,
Src: jsFrontendPrerender,
},
},
Extra: map[string]any{

View file

@ -67,9 +67,9 @@ const (
cssSettings = distPathPrefix + "/settings-style.css"
cssTag = distPathPrefix + "/tag.css"
jsFrontend = distPathPrefix + "/frontend.js" // Progressive enhancement frontend JS.
jsBlurhash = distPathPrefix + "/blurhash.js" // Blurhash rendering JS.
jsSettings = distPathPrefix + "/settings.js" // Settings panel React application.
jsFrontend = distPathPrefix + "/frontend.js" // Progressive enhancement frontend JS.
jsFrontendPrerender = distPathPrefix + "/frontend_prerender.js" // Frontend JS that should run before page renders.
jsSettings = distPathPrefix + "/settings.js" // Settings panel React application.
)
type Module struct {

50
vendor/github.com/gin-contrib/sessions/.golangci.yml generated vendored Normal file
View file

@ -0,0 +1,50 @@
version: "2"
linters:
default: none
enable:
- bodyclose
- dogsled
- dupl
- errcheck
- exhaustive
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goprintffuncname
- gosec
- govet
- ineffassign
- lll
- misspell
- nakedret
- noctx
- nolintlint
- rowserrcheck
- staticcheck
- unconvert
- unparam
- unused
- whitespace
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$

2
vendor/github.com/gin-contrib/sessions/bearer.yml generated vendored Normal file
View file

@ -0,0 +1,2 @@
rule:
skip-rule: [go_gorilla_cookie_missing_http_only, go_gorilla_insecure_cookie]

View file

@ -1,7 +1,7 @@
package sessions
import (
"log"
"log/slog"
"net/http"
"github.com/gin-gonic/gin"
@ -11,7 +11,7 @@ import (
const (
DefaultKey = "github.com/gin-contrib/sessions"
errorFormat = "[sessions] ERROR! %s\n"
errorFormat = "[sessions] ERROR!"
)
type Store interface {
@ -131,7 +131,10 @@ func (s *session) Session() *sessions.Session {
var err error
s.session, err = s.store.Get(s.request, s.name)
if err != nil {
log.Printf(errorFormat, err)
slog.Error(errorFormat,
"err", err,
)
return nil
}
}
return s.session

View file

@ -1,4 +1,4 @@
Copyright (c) 2023 The Gorilla Authors. All rights reserved.
Copyright (c) 2024 The Gorilla Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View file

@ -1,4 +1,7 @@
# sessions
# Gorilla Sessions
> [!IMPORTANT]
> The latest version of this repository requires go 1.23 because of the new partitioned attribute. The last version that is compatible with older versions of go is v1.3.0.
![testing](https://github.com/gorilla/sessions/actions/workflows/test.yml/badge.svg)
[![codecov](https://codecov.io/github/gorilla/sessions/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/sessions)
@ -59,8 +62,7 @@ secret key used to authenticate the session. Inside the handler, we call
some session values in session.Values, which is a `map[interface{}]interface{}`.
And finally we call `session.Save()` to save the session in the response.
More examples are available [on the Gorilla
website](https://www.gorillatoolkit.org/pkg/sessions).
More examples are available at [package documentation](https://pkg.go.dev/github.com/gorilla/sessions).
## Store Implementations
@ -75,6 +77,7 @@ Other implementations of the `sessions.Store` interface:
- [github.com/dsoprea/go-appengine-sessioncascade](https://github.com/dsoprea/go-appengine-sessioncascade) - Memcache/Datastore/Context in AppEngine
- [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB
- [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL
- [github.com/danielepintore/gorilla-sessions-mysql](https://github.com/danielepintore/gorilla-sessions-mysql) - MySQL
- [github.com/EnumApps/clustersqlstore](https://github.com/EnumApps/clustersqlstore) - MySQL Cluster
- [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL
- [github.com/boj/redistore](https://github.com/boj/redistore) - Redis

View file

@ -1,5 +1,6 @@
//go:build !go1.11
// +build !go1.11
// Copyright 2012 The Gorilla 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 sessions
@ -8,13 +9,15 @@ import "net/http"
// newCookieFromOptions returns an http.Cookie with the options set.
func newCookieFromOptions(name, value string, options *Options) *http.Cookie {
return &http.Cookie{
Name: name,
Value: value,
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
Name: name,
Value: value,
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
Partitioned: options.Partitioned,
SameSite: options.SameSite,
}
}

View file

@ -1,21 +0,0 @@
//go:build go1.11
// +build go1.11
package sessions
import "net/http"
// newCookieFromOptions returns an http.Cookie with the options set.
func newCookieFromOptions(name, value string, options *Options) *http.Cookie {
return &http.Cookie{
Name: name,
Value: value,
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
SameSite: options.SameSite,
}
}

View file

@ -1,8 +1,11 @@
//go:build !go1.11
// +build !go1.11
// Copyright 2012 The Gorilla 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 sessions
import "net/http"
// Options stores configuration for a session or session store.
//
// Fields are a subset of http.Cookie fields.
@ -13,7 +16,9 @@ type Options struct {
// deleted after the browser session ends.
// MaxAge<0 means delete cookie immediately.
// MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int
Secure bool
HttpOnly bool
MaxAge int
Secure bool
HttpOnly bool
Partitioned bool
SameSite http.SameSite
}

View file

@ -1,23 +0,0 @@
//go:build go1.11
// +build go1.11
package sessions
import "net/http"
// Options stores configuration for a session or session store.
//
// Fields are a subset of http.Cookie fields.
type Options struct {
Path string
Domain string
// MaxAge=0 means no Max-Age attribute specified and the cookie will be
// deleted after the browser session ends.
// MaxAge<0 means delete cookie immediately.
// MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int
Secure bool
HttpOnly bool
// Defaults to http.SameSiteDefaultMode
SameSite http.SameSite
}

View file

@ -14,6 +14,11 @@ import (
"github.com/gorilla/securecookie"
)
const (
// File name prefix for session files.
sessionFilePrefix = "session_"
)
// Store is an interface for custom session stores.
//
// See CookieStore and FilesystemStore for examples.
@ -49,8 +54,10 @@ func NewCookieStore(keyPairs ...[]byte) *CookieStore {
cs := &CookieStore{
Codecs: securecookie.CodecsFromPairs(keyPairs...),
Options: &Options{
Path: "/",
MaxAge: 86400 * 30,
Path: "/",
MaxAge: 86400 * 30,
SameSite: http.SameSiteNoneMode,
Secure: true,
},
}
@ -257,7 +264,7 @@ func (s *FilesystemStore) save(session *Session) error {
if err != nil {
return err
}
filename := filepath.Join(s.path, "session_"+session.ID)
filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID))
fileMutex.Lock()
defer fileMutex.Unlock()
return os.WriteFile(filename, []byte(encoded), 0600)
@ -265,7 +272,7 @@ func (s *FilesystemStore) save(session *Session) error {
// load reads a file and decodes its content into session.Values.
func (s *FilesystemStore) load(session *Session) error {
filename := filepath.Join(s.path, "session_"+session.ID)
filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID))
fileMutex.RLock()
defer fileMutex.RUnlock()
fdata, err := os.ReadFile(filepath.Clean(filename))
@ -281,7 +288,7 @@ func (s *FilesystemStore) load(session *Session) error {
// delete session file
func (s *FilesystemStore) erase(session *Session) error {
filename := filepath.Join(s.path, "session_"+session.ID)
filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID))
fileMutex.RLock()
defer fileMutex.RUnlock()

View file

@ -162,7 +162,16 @@ func (l *Lexer) Next() (TokenType, []byte) {
for {
c = l.r.Peek(0)
if c == '<' {
if 0 < len(l.tmplBegin) && l.at(l.tmplBegin...) {
if 0 < l.r.Pos() {
l.text = l.r.Shift()
return TextToken, l.text
}
l.r.Move(len(l.tmplBegin))
l.moveTemplate()
l.hasTmpl = true
return TemplateToken, l.r.Shift()
} else if c == '<' {
c = l.r.Peek(1)
isEndTag := c == '/' && l.r.Peek(2) != '>' && (l.r.Peek(2) != 0 || l.r.PeekErr(2) == nil)
if !isEndTag && (c < 'a' || 'z' < c) && (c < 'A' || 'Z' < c) && c != '!' && c != '?' {
@ -190,15 +199,6 @@ func (l *Lexer) Next() (TokenType, []byte) {
l.r.Move(1)
return CommentToken, l.shiftBogusComment()
}
} else if 0 < len(l.tmplBegin) && l.at(l.tmplBegin...) {
if 0 < l.r.Pos() {
l.text = l.r.Shift()
return TextToken, l.text
}
l.r.Move(len(l.tmplBegin))
l.moveTemplate()
l.hasTmpl = true
return TemplateToken, l.r.Shift()
} else if c == 0 && l.r.Err() != nil {
if 0 < l.r.Pos() {
l.text = l.r.Shift()

View file

@ -1,6 +1,3 @@
run:
deadline: 10m
issues:
exclude-use-default: false
exclude-rules:

View file

@ -1,4 +1,4 @@
.PHONY: test fuzz lint
.PHONY: test fuzz lint gen
lint:
golangci-lint run -c .golangci.yml ./...
@ -10,4 +10,7 @@ cov: test
go tool cover -html=profile.out
fuzz:
cd ./fuzz && go test -fuzz=Fuzz
cd ./fuzz && go test -fuzz=FuzzDefault
gen:
go generate ./...

View file

@ -2,7 +2,7 @@ goldmark
==========================================
[![https://pkg.go.dev/github.com/yuin/goldmark](https://pkg.go.dev/badge/github.com/yuin/goldmark.svg)](https://pkg.go.dev/github.com/yuin/goldmark)
[![https://github.com/yuin/goldmark/actions?query=workflow:test](https://github.com/yuin/goldmark/workflows/test/badge.svg?branch=master&event=push)](https://github.com/yuin/goldmark/actions?query=workflow:test)
[![https://github.com/yuin/goldmark/actions?query=workflow:test](https://github.com/yuin/goldmark/actions/workflows/test.yaml/badge.svg?branch=master&event=push)](https://github.com/yuin/goldmark/actions?query=workflow:test)
[![https://coveralls.io/github/yuin/goldmark](https://coveralls.io/repos/github/yuin/goldmark/badge.svg?branch=master)](https://coveralls.io/github/yuin/goldmark)
[![https://goreportcard.com/report/github.com/yuin/goldmark](https://goreportcard.com/badge/github.com/yuin/goldmark)](https://goreportcard.com/report/github.com/yuin/goldmark)
@ -493,7 +493,7 @@ Extensions
- [goldmark-d2](https://github.com/FurqanSoftware/goldmark-d2): Adds support for [D2](https://d2lang.com/) diagrams.
- [goldmark-katex](https://github.com/FurqanSoftware/goldmark-katex): Adds support for [KaTeX](https://katex.org/) math and equations.
- [goldmark-img64](https://github.com/tenkoh/goldmark-img64): Adds support for embedding images into the document as DataURL (base64 encoded).
- [goldmark-enclave](https://github.com/quail-ink/goldmark-enclave): Adds support for embedding youtube/bilibili video, X's [oembed tweet](https://publish.twitter.com/), [tradingview](https://www.tradingview.com/widget/)'s chart, [quail](https://quail.ink)'s widget into the document.
- [goldmark-enclave](https://github.com/quailyquaily/goldmark-enclave): Adds support for embedding youtube/bilibili video, X's [oembed X](https://publish.x.com/), [tradingview chart](https://www.tradingview.com/widget/)'s chart, [quaily widget](https://quaily.com), [spotify embeds](https://developer.spotify.com/documentation/embeds), [dify embed](https://dify.ai/) and html audio into the document.
- [goldmark-wiki-table](https://github.com/movsb/goldmark-wiki-table): Adds support for embedding Wiki Tables.
- [goldmark-tgmd](https://github.com/Mad-Pixels/goldmark-tgmd): A Telegram markdown renderer that can be passed to `goldmark.WithRenderer()`.

View file

@ -358,17 +358,17 @@ func (r *TableHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegistere
}
// TableAttributeFilter defines attribute names which table elements can have.
var TableAttributeFilter = html.GlobalAttributeFilter.Extend(
[]byte("align"), // [Deprecated]
[]byte("bgcolor"), // [Deprecated]
[]byte("border"), // [Deprecated]
[]byte("cellpadding"), // [Deprecated]
[]byte("cellspacing"), // [Deprecated]
[]byte("frame"), // [Deprecated]
[]byte("rules"), // [Deprecated]
[]byte("summary"), // [Deprecated]
[]byte("width"), // [Deprecated]
)
//
// - align: Deprecated
// - bgcolor: Deprecated
// - border: Deprecated
// - cellpadding: Deprecated
// - cellspacing: Deprecated
// - frame: Deprecated
// - rules: Deprecated
// - summary: Deprecated
// - width: Deprecated.
var TableAttributeFilter = html.GlobalAttributeFilter.ExtendString(`align,bgcolor,border,cellpadding,cellspacing,frame,rules,summary,width`) // nolint: lll
func (r *TableHTMLRenderer) renderTable(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
@ -385,13 +385,13 @@ func (r *TableHTMLRenderer) renderTable(
}
// TableHeaderAttributeFilter defines attribute names which <thead> elements can have.
var TableHeaderAttributeFilter = html.GlobalAttributeFilter.Extend(
[]byte("align"), // [Deprecated since HTML4] [Obsolete since HTML5]
[]byte("bgcolor"), // [Not Standardized]
[]byte("char"), // [Deprecated since HTML4] [Obsolete since HTML5]
[]byte("charoff"), // [Deprecated since HTML4] [Obsolete since HTML5]
[]byte("valign"), // [Deprecated since HTML4] [Obsolete since HTML5]
)
//
// - align: Deprecated since HTML4, Obsolete since HTML5
// - bgcolor: Not Standardized
// - char: Deprecated since HTML4, Obsolete since HTML5
// - charoff: Deprecated since HTML4, Obsolete since HTML5
// - valign: Deprecated since HTML4, Obsolete since HTML5.
var TableHeaderAttributeFilter = html.GlobalAttributeFilter.ExtendString(`align,bgcolor,char,charoff,valign`)
func (r *TableHTMLRenderer) renderTableHeader(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
@ -413,13 +413,13 @@ func (r *TableHTMLRenderer) renderTableHeader(
}
// TableRowAttributeFilter defines attribute names which <tr> elements can have.
var TableRowAttributeFilter = html.GlobalAttributeFilter.Extend(
[]byte("align"), // [Obsolete since HTML5]
[]byte("bgcolor"), // [Obsolete since HTML5]
[]byte("char"), // [Obsolete since HTML5]
[]byte("charoff"), // [Obsolete since HTML5]
[]byte("valign"), // [Obsolete since HTML5]
)
//
// - align: Obsolete since HTML5
// - bgcolor: Obsolete since HTML5
// - char: Obsolete since HTML5
// - charoff: Obsolete since HTML5
// - valign: Obsolete since HTML5.
var TableRowAttributeFilter = html.GlobalAttributeFilter.ExtendString(`align,bgcolor,char,charoff,valign`)
func (r *TableHTMLRenderer) renderTableRow(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
@ -439,50 +439,41 @@ func (r *TableHTMLRenderer) renderTableRow(
}
// TableThCellAttributeFilter defines attribute names which table <th> cells can have.
var TableThCellAttributeFilter = html.GlobalAttributeFilter.Extend(
[]byte("abbr"), // [OK] Contains a short abbreviated description of the cell's content [NOT OK in <td>]
[]byte("align"), // [Obsolete since HTML5]
[]byte("axis"), // [Obsolete since HTML5]
[]byte("bgcolor"), // [Not Standardized]
[]byte("char"), // [Obsolete since HTML5]
[]byte("charoff"), // [Obsolete since HTML5]
[]byte("colspan"), // [OK] Number of columns that the cell is to span
[]byte("headers"), // [OK] This attribute contains a list of space-separated
// strings, each corresponding to the id attribute of the <th> elements that apply to this element
[]byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
[]byte("rowspan"), // [OK] Number of rows that the cell is to span
[]byte("scope"), // [OK] This enumerated attribute defines the cells that
// the header (defined in the <th>) element relates to [NOT OK in <td>]
[]byte("valign"), // [Obsolete since HTML5]
[]byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
)
//
// - abbr: [OK] Contains a short abbreviated description of the cell's content [NOT OK in <td>]
// - align: Obsolete since HTML5
// - axis: Obsolete since HTML5
// - bgcolor: Not Standardized
// - char: Obsolete since HTML5
// - charoff: Obsolete since HTML5
// - colspan: [OK] Number of columns that the cell is to span
// - headers: [OK] This attribute contains a list of space-separated strings,
// each corresponding to the id attribute of the <th> elements that apply to this element
// - height: Deprecated since HTML4. Obsolete since HTML5
// - rowspan: [OK] Number of rows that the cell is to span
// - scope: [OK] This enumerated attribute defines the cells that the header
// (defined in the <th>) element relates to [NOT OK in <td>]
// - valign: Obsolete since HTML5
// - width: Deprecated since HTML4. Obsolete since HTML5.
var TableThCellAttributeFilter = html.GlobalAttributeFilter.ExtendString(`abbr,align,axis,bgcolor,char,charoff,colspan,headers,height,rowspan,scope,valign,width`) // nolint:lll
// TableTdCellAttributeFilter defines attribute names which table <td> cells can have.
var TableTdCellAttributeFilter = html.GlobalAttributeFilter.Extend(
[]byte("abbr"), // [Obsolete since HTML5] [OK in <th>]
[]byte("align"), // [Obsolete since HTML5]
[]byte("axis"), // [Obsolete since HTML5]
[]byte("bgcolor"), // [Not Standardized]
[]byte("char"), // [Obsolete since HTML5]
[]byte("charoff"), // [Obsolete since HTML5]
[]byte("colspan"), // [OK] Number of columns that the cell is to span
[]byte("headers"), // [OK] This attribute contains a list of space-separated
// strings, each corresponding to the id attribute of the <th> elements that apply to this element
[]byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
[]byte("rowspan"), // [OK] Number of rows that the cell is to span
[]byte("scope"), // [Obsolete since HTML5] [OK in <th>]
[]byte("valign"), // [Obsolete since HTML5]
[]byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
)
//
// - abbr: Obsolete since HTML5. [OK in <th>]
// - align: Obsolete since HTML5
// - axis: Obsolete since HTML5
// - bgcolor: Not Standardized
// - char: Obsolete since HTML5
// - charoff: Obsolete since HTML5
// - colspan: [OK] Number of columns that the cell is to span
// - headers: [OK] This attribute contains a list of space-separated strings, each corresponding
// to the id attribute of the <th> elements that apply to this element
// - height: Deprecated since HTML4. Obsolete since HTML5
// - rowspan: [OK] Number of rows that the cell is to span
// - scope: Obsolete since HTML5. [OK in <th>]
// - valign: Obsolete since HTML5
// - width: Deprecated since HTML4. Obsolete since HTML5.
var TableTdCellAttributeFilter = html.GlobalAttributeFilter.ExtendString(`abbr,align,axis,bgcolor,char,charoff,colspan,headers,height,rowspan,scope,valign,width`) // nolint: lll
func (r *TableHTMLRenderer) renderTableCell(
w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {

View file

@ -111,7 +111,7 @@ func NewDelimiter(canOpen, canClose bool, length int, char byte, processor Delim
}
// ScanDelimiter scans a delimiter by given DelimiterProcessor.
func ScanDelimiter(line []byte, before rune, min int, processor DelimiterProcessor) *Delimiter {
func ScanDelimiter(line []byte, before rune, minimum int, processor DelimiterProcessor) *Delimiter {
i := 0
c := line[i]
j := i
@ -120,7 +120,7 @@ func ScanDelimiter(line []byte, before rune, min int, processor DelimiterProcess
}
for ; j < len(line) && c == line[j]; j++ {
}
if (j - i) >= min {
if (j - i) >= minimum {
after := rune(' ')
if j != len(line) {
after = util.ToRune(line, j)

View file

@ -295,35 +295,7 @@ func (r *Renderer) writeLines(w util.BufWriter, source []byte, n ast.Node) {
}
// GlobalAttributeFilter defines attribute names which any elements can have.
var GlobalAttributeFilter = util.NewBytesFilter(
[]byte("accesskey"),
[]byte("autocapitalize"),
[]byte("autofocus"),
[]byte("class"),
[]byte("contenteditable"),
[]byte("dir"),
[]byte("draggable"),
[]byte("enterkeyhint"),
[]byte("hidden"),
[]byte("id"),
[]byte("inert"),
[]byte("inputmode"),
[]byte("is"),
[]byte("itemid"),
[]byte("itemprop"),
[]byte("itemref"),
[]byte("itemscope"),
[]byte("itemtype"),
[]byte("lang"),
[]byte("part"),
[]byte("role"),
[]byte("slot"),
[]byte("spellcheck"),
[]byte("style"),
[]byte("tabindex"),
[]byte("title"),
[]byte("translate"),
)
var GlobalAttributeFilter = util.NewBytesFilterString(`accesskey,autocapitalize,autofocus,class,contenteditable,dir,draggable,enterkeyhint,hidden,id,inert,inputmode,is,itemid,itemprop,itemref,itemscope,itemtype,lang,part,role,slot,spellcheck,style,tabindex,title,translate`) // nolint:lll
func (r *Renderer) renderDocument(
w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
@ -353,9 +325,7 @@ func (r *Renderer) renderHeading(
}
// BlockquoteAttributeFilter defines attribute names which blockquote elements can have.
var BlockquoteAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("cite"),
)
var BlockquoteAttributeFilter = GlobalAttributeFilter.ExtendString(`cite`)
func (r *Renderer) renderBlockquote(
w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
@ -429,11 +399,7 @@ func (r *Renderer) renderHTMLBlock(
}
// ListAttributeFilter defines attribute names which list elements can have.
var ListAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("start"),
[]byte("reversed"),
[]byte("type"),
)
var ListAttributeFilter = GlobalAttributeFilter.ExtendString(`start,reversed,type`)
func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*ast.List)
@ -460,9 +426,7 @@ func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, en
}
// ListItemAttributeFilter defines attribute names which list item elements can have.
var ListItemAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("value"),
)
var ListItemAttributeFilter = GlobalAttributeFilter.ExtendString(`value`)
func (r *Renderer) renderListItem(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering {
@ -513,13 +477,7 @@ func (r *Renderer) renderTextBlock(w util.BufWriter, source []byte, n ast.Node,
}
// ThematicAttributeFilter defines attribute names which hr elements can have.
var ThematicAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("align"), // [Deprecated]
[]byte("color"), // [Not Standardized]
[]byte("noshade"), // [Deprecated]
[]byte("size"), // [Deprecated]
[]byte("width"), // [Deprecated]
)
var ThematicAttributeFilter = GlobalAttributeFilter.ExtendString(`align,color,noshade,size,width`)
func (r *Renderer) renderThematicBreak(
w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
@ -539,17 +497,7 @@ func (r *Renderer) renderThematicBreak(
}
// LinkAttributeFilter defines attribute names which link elements can have.
var LinkAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("download"),
// []byte("href"),
[]byte("hreflang"),
[]byte("media"),
[]byte("ping"),
[]byte("referrerpolicy"),
[]byte("rel"),
[]byte("shape"),
[]byte("target"),
)
var LinkAttributeFilter = GlobalAttributeFilter.ExtendString(`download,hreflang,media,ping,referrerpolicy,rel,shape,target`) // nolint:lll
func (r *Renderer) renderAutoLink(
w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
@ -653,22 +601,7 @@ func (r *Renderer) renderLink(w util.BufWriter, source []byte, node ast.Node, en
}
// ImageAttributeFilter defines attribute names which image elements can have.
var ImageAttributeFilter = GlobalAttributeFilter.Extend(
[]byte("align"),
[]byte("border"),
[]byte("crossorigin"),
[]byte("decoding"),
[]byte("height"),
[]byte("importance"),
[]byte("intrinsicsize"),
[]byte("ismap"),
[]byte("loading"),
[]byte("referrerpolicy"),
[]byte("sizes"),
[]byte("srcset"),
[]byte("usemap"),
[]byte("width"),
)
var ImageAttributeFilter = GlobalAttributeFilter.ExtendString(`align,border,crossorigin,decoding,height,importance,intrinsicsize,ismap,loading,referrerpolicy,sizes,srcset,usemap,width`) // nolint: lll
func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -528,12 +528,21 @@ func ToLinkReference(v []byte) string {
return string(ReplaceSpaces(v, ' '))
}
var htmlEscapeTable = [256][]byte{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("&quot;"), nil, nil, nil, []byte("&amp;"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("&lt;"), nil, []byte("&gt;"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil} //nolint:golint,lll
var htmlQuote = []byte("&quot;")
var htmlAmp = []byte("&amp;")
var htmlLess = []byte("&lt;")
var htmlGreater = []byte("&gt;")
var htmlEscapeTable = [256]*[]byte{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &htmlQuote, nil, nil, nil, &htmlAmp, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &htmlLess, nil, &htmlGreater, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil} //nolint:golint,lll
// EscapeHTMLByte returns HTML escaped bytes if the given byte should be escaped,
// otherwise nil.
func EscapeHTMLByte(b byte) []byte {
return htmlEscapeTable[b]
v := htmlEscapeTable[b]
if v != nil {
return *v
}
return nil
}
// EscapeHTML escapes characters that should be escaped in HTML text.
@ -545,7 +554,7 @@ func EscapeHTML(v []byte) []byte {
escaped := htmlEscapeTable[c]
if escaped != nil {
cob.Write(v[n:i])
cob.Write(escaped)
cob.Write(*escaped)
n = i + 1
}
}
@ -911,6 +920,10 @@ type BytesFilter interface {
// Extend copies this filter and adds given bytes to new filter.
Extend(...[]byte) BytesFilter
// ExtendString copies this filter and adds given bytes to new filter.
// Given string must be separated by a comma.
ExtendString(string) BytesFilter
}
type bytesFilter struct {
@ -931,6 +944,27 @@ func NewBytesFilter(elements ...[]byte) BytesFilter {
return s
}
// NewBytesFilterString returns a new BytesFilter.
// Given string must be separated by a comma.
func NewBytesFilterString(elements string) BytesFilter {
s := &bytesFilter{
threshold: 3,
slots: make([][][]byte, 64),
}
start := 0
for i := 0; i < len(elements); i++ {
if elements[i] == ',' {
s.Add(StringToReadOnlyBytes(elements[start:i]))
start = i + 1
}
}
if start < len(elements) {
s.Add(StringToReadOnlyBytes(elements[start:]))
}
return s
}
func (s *bytesFilter) Add(b []byte) {
l := len(b)
m := s.threshold
@ -963,6 +997,28 @@ func (s *bytesFilter) Extend(bs ...[]byte) BytesFilter {
return newFilter
}
func (s *bytesFilter) ExtendString(elements string) BytesFilter {
newFilter := NewBytesFilter().(*bytesFilter)
newFilter.chars = s.chars
newFilter.threshold = s.threshold
for k, v := range s.slots {
newSlot := make([][]byte, len(v))
copy(newSlot, v)
newFilter.slots[k] = v
}
start := 0
for i := 0; i < len(elements); i++ {
if elements[i] == ',' {
newFilter.Add(StringToReadOnlyBytes(elements[start:i]))
start = i + 1
}
}
if start < len(elements) {
newFilter.Add(StringToReadOnlyBytes(elements[start:]))
}
return newFilter
}
func (s *bytesFilter) Contains(b []byte) bool {
l := len(b)
m := s.threshold

View file

@ -330,7 +330,7 @@ func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReade
case reflect.Int64:
return reflect.ValueOf(i64), nil
case reflect.Int:
if int64(int(i64)) != i64 { // Can we fit this inside of an int
if i64 > math.MaxInt { // Can we fit this inside of an int
return emptyValue, fmt.Errorf("%d overflows int", i64)
}
@ -434,7 +434,7 @@ func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.Valu
return fmt.Errorf("%d overflows uint64", i64)
}
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
if i64 < 0 || uint64(i64) > uint64(math.MaxUint) { // Can we fit this inside of an uint
return fmt.Errorf("%d overflows uint", i64)
}
default:
@ -1521,6 +1521,18 @@ func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(_ DecodeContext, vr
return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val}
}
// If BSON value is null and the go value is a pointer, then don't call
// UnmarshalBSONValue. Even if the Go pointer is already initialized (i.e.,
// non-nil), encountering null in BSON will result in the pointer being
// directly set to nil here. Since the pointer is being replaced with nil,
// there is no opportunity (or reason) for the custom UnmarshalBSONValue logic
// to be called.
if vr.Type() == bsontype.Null && val.Kind() == reflect.Ptr {
val.Set(reflect.Zero(val.Type()))
return vr.ReadNull()
}
if val.Kind() == reflect.Ptr && val.IsNil() {
if !val.CanSet() {
return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val}

View file

@ -164,11 +164,15 @@ func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t refl
return reflect.ValueOf(uint64(i64)), nil
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
if i64 < 0 {
return emptyValue, fmt.Errorf("%d overflows uint", i64)
}
v := uint64(i64)
if v > math.MaxUint { // Can we fit this inside of an uint
return emptyValue, fmt.Errorf("%d overflows uint", i64)
}
return reflect.ValueOf(uint(i64)), nil
return reflect.ValueOf(uint(v)), nil
default:
return emptyValue, ValueDecoderError{
Name: "UintDecodeValue",

View file

@ -305,7 +305,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
}
// remove hyphens
uuidNoHyphens := strings.Replace(uuid, "-", "", -1)
uuidNoHyphens := strings.ReplaceAll(uuid, "-", "")
if len(uuidNoHyphens) != 32 {
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens")
}

View file

@ -95,9 +95,9 @@ func (ejv *extJSONValue) parseBinary() (b []byte, subType byte, err error) {
return nil, 0, fmt.Errorf("$binary subType value should be string, but instead is %s", val.t)
}
i, err := strconv.ParseInt(val.v.(string), 16, 64)
i, err := strconv.ParseUint(val.v.(string), 16, 8)
if err != nil {
return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string))
return nil, 0, fmt.Errorf("invalid $binary subType string: %q: %w", val.v.(string), err)
}
subType = byte(i)

View file

@ -628,13 +628,14 @@ func (ejvw *extJSONValueWriter) WriteArrayEnd() error {
func formatDouble(f float64) string {
var s string
if math.IsInf(f, 1) {
switch {
case math.IsInf(f, 1):
s = "Infinity"
} else if math.IsInf(f, -1) {
case math.IsInf(f, -1):
s = "-Infinity"
} else if math.IsNaN(f) {
case math.IsNaN(f):
s = "NaN"
} else {
default:
// Print exactly one decimalType place for integers; otherwise, print as many are necessary to
// perfectly represent it.
s = strconv.FormatFloat(f, 'G', -1, 64)
@ -739,9 +740,7 @@ func (ss sortableString) Less(i, j int) bool {
}
func (ss sortableString) Swap(i, j int) {
oldI := ss[i]
ss[i] = ss[j]
ss[j] = oldI
ss[i], ss[j] = ss[j], ss[i]
}
func sortStringAlphebeticAscending(s string) string {

View file

@ -82,12 +82,13 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) {
return js.scanString()
default:
// check if it's a number
if c == '-' || isDigit(c) {
switch {
case c == '-' || isDigit(c):
return js.scanNumber(c)
} else if c == 't' || c == 'f' || c == 'n' {
case c == 't' || c == 'f' || c == 'n':
// maybe a literal
return js.scanLiteral(c)
} else {
default:
return nil, fmt.Errorf("invalid JSON input. Position: %d. Character: %c", js.pos-1, c)
}
}
@ -174,7 +175,7 @@ func getu4(s []byte) rune {
for _, c := range s[:4] {
switch {
case '0' <= c && c <= '9':
c = c - '0'
c -= '0'
case 'a' <= c && c <= 'f':
c = c - 'a' + 10
case 'A' <= c && c <= 'F':
@ -325,13 +326,14 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) {
c5, err := js.readNextByte()
if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
switch {
case bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)):
js.pos = int(math.Max(0, float64(js.pos-1)))
return &jsonToken{t: jttBool, v: true, p: p}, nil
} else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
case bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)):
js.pos = int(math.Max(0, float64(js.pos-1)))
return &jsonToken{t: jttNull, v: nil, p: p}, nil
} else if bytes.Equal([]byte("fals"), lit) {
case bytes.Equal([]byte("fals"), lit):
if c5 == 'e' {
c5, err = js.readNextByte()
@ -430,12 +432,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
switch {
case isWhiteSpace(c) || errors.Is(err, io.EOF):
s = nssDone
} else if isDigit(c) {
case isDigit(c):
s = nssSawIntegerDigits
b.WriteByte(c)
} else {
default:
s = nssInvalid
}
}
@ -455,12 +458,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
switch {
case isWhiteSpace(c) || errors.Is(err, io.EOF):
s = nssDone
} else if isDigit(c) {
case isDigit(c):
s = nssSawFractionDigits
b.WriteByte(c)
} else {
default:
s = nssInvalid
}
}
@ -490,12 +494,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
if isWhiteSpace(c) || errors.Is(err, io.EOF) {
switch {
case isWhiteSpace(c) || errors.Is(err, io.EOF):
s = nssDone
} else if isDigit(c) {
case isDigit(c):
s = nssSawExponentDigits
b.WriteByte(c)
} else {
default:
s = nssInvalid
}
}

View file

@ -842,7 +842,7 @@ func (vr *valueReader) peekLength() (int32, error) {
}
idx := vr.offset
return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil
return int32(binary.LittleEndian.Uint32(vr.d[idx:])), nil
}
func (vr *valueReader) readLength() (int32, error) { return vr.readi32() }
@ -854,7 +854,7 @@ func (vr *valueReader) readi32() (int32, error) {
idx := vr.offset
vr.offset += 4
return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil
return int32(binary.LittleEndian.Uint32(vr.d[idx:])), nil
}
func (vr *valueReader) readu32() (uint32, error) {
@ -864,7 +864,7 @@ func (vr *valueReader) readu32() (uint32, error) {
idx := vr.offset
vr.offset += 4
return (uint32(vr.d[idx]) | uint32(vr.d[idx+1])<<8 | uint32(vr.d[idx+2])<<16 | uint32(vr.d[idx+3])<<24), nil
return binary.LittleEndian.Uint32(vr.d[idx:]), nil
}
func (vr *valueReader) readi64() (int64, error) {
@ -874,8 +874,7 @@ func (vr *valueReader) readi64() (int64, error) {
idx := vr.offset
vr.offset += 8
return int64(vr.d[idx]) | int64(vr.d[idx+1])<<8 | int64(vr.d[idx+2])<<16 | int64(vr.d[idx+3])<<24 |
int64(vr.d[idx+4])<<32 | int64(vr.d[idx+5])<<40 | int64(vr.d[idx+6])<<48 | int64(vr.d[idx+7])<<56, nil
return int64(binary.LittleEndian.Uint64(vr.d[idx:])), nil
}
func (vr *valueReader) readu64() (uint64, error) {
@ -885,6 +884,5 @@ func (vr *valueReader) readu64() (uint64, error) {
idx := vr.offset
vr.offset += 8
return uint64(vr.d[idx]) | uint64(vr.d[idx+1])<<8 | uint64(vr.d[idx+2])<<16 | uint64(vr.d[idx+3])<<24 |
uint64(vr.d[idx+4])<<32 | uint64(vr.d[idx+5])<<40 | uint64(vr.d[idx+6])<<48 | uint64(vr.d[idx+7])<<56, nil
return binary.LittleEndian.Uint64(vr.d[idx:]), nil
}

View file

@ -598,7 +598,7 @@ func (vw *valueWriter) writeLength() error {
return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))}
}
frame := &vw.stack[vw.frame]
length = length - int(frame.start)
length -= int(frame.start)
start := frame.start
_ = vw.buf[start+3] // BCE

View file

@ -107,10 +107,13 @@
// The name may be empty in order to specify options without overriding the default field name. The following options can
// be used to configure behavior:
//
// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if
// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array,
// slice, map, or string.
// NOTE: It is recommended that this tag be used for all slice and map fields.
// 1. omitempty: If the "omitempty" struct tag is specified on a field, the field will not be marshaled if it is set to
// an "empty" value. Numbers, booleans, and strings are considered empty if their value is equal to the zero value for
// the type (i.e. 0 for numbers, false for booleans, and "" for strings). Slices, maps, and arrays are considered
// empty if they are of length zero. Interfaces and pointers are considered empty if their value is nil. By default,
// structs are only considered empty if the struct type implements [bsoncodec.Zeroer] and the IsZero
// method returns true. Struct types that do not implement [bsoncodec.Zeroer] are never considered empty and will be
// marshaled as embedded documents. NOTE: It is recommended that this tag be used for all slice and map fields.
//
// 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of
// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For

View file

@ -70,7 +70,6 @@ func (d Decimal128) String() string {
// Bits: 1*sign 2*ignored 14*exponent 111*significand.
// Implicit 0b100 prefix in significand.
exp = int(d.h >> 47 & (1<<14 - 1))
//high = 4<<47 | d.h&(1<<47-1)
// Spec says all of these values are out of range.
high, low = 0, 0
} else {
@ -152,13 +151,12 @@ func (d Decimal128) BigInt() (*big.Int, int, error) {
// Bits: 1*sign 2*ignored 14*exponent 111*significand.
// Implicit 0b100 prefix in significand.
exp = int(high >> 47 & (1<<14 - 1))
//high = 4<<47 | d.h&(1<<47-1)
// Spec says all of these values are out of range.
high, low = 0, 0
} else {
// Bits: 1*sign 14*exponent 113*significand
exp = int(high >> 49 & (1<<14 - 1))
high = high & (1<<49 - 1)
high &= (1<<49 - 1)
}
exp += MinDecimal128Exp
@ -352,7 +350,7 @@ var (
// ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value.
func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) {
//copy
// copy
bi = new(big.Int).Set(bi)
q := new(big.Int)

View file

@ -88,8 +88,12 @@ func (rv RawValue) UnmarshalWithRegistry(r *bsoncodec.Registry, val interface{})
return dec.DecodeValue(bsoncodec.DecodeContext{Registry: r}, vr, rval)
}
// UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses the provided DecodeContext
// instead of the one attached or the default registry.
// UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses
// the provided DecodeContext instead of the one attached or the default
// registry.
//
// Deprecated: Use [RawValue.UnmarshalWithRegistry] with a custom registry to customize
// unmarshal behavior instead.
func (rv RawValue) UnmarshalWithContext(dc *bsoncodec.DecodeContext, val interface{}) error {
if dc == nil {
return ErrNilContext

View file

@ -10,15 +10,27 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec"
)
// DefaultRegistry is the default bsoncodec.Registry. It contains the default codecs and the
// primitive codecs.
// DefaultRegistry is the default bsoncodec.Registry. It contains the default
// codecs and the primitive codecs.
//
// Deprecated: Use [NewRegistry] to construct a new default registry. To use a
// custom registry when marshaling or unmarshaling, use the "SetRegistry" method
// on an [Encoder] or [Decoder] instead:
//
// dec, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
// if err != nil {
// panic(err)
// }
// dec.SetRegistry(reg)
//
// See [Encoder] and [Decoder] for more examples.
var DefaultRegistry = NewRegistry()
// NewRegistryBuilder creates a new RegistryBuilder configured with the default encoders and
// decoders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the
// PrimitiveCodecs type in this package.
//
// Deprecated: Use NewRegistry instead.
// Deprecated: Use [NewRegistry] instead.
func NewRegistryBuilder() *bsoncodec.RegistryBuilder {
rb := bsoncodec.NewRegistryBuilder()
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)

View file

@ -41,6 +41,9 @@ type ValueUnmarshaler interface {
// Unmarshal parses the BSON-encoded data and stores the result in the value
// pointed to by val. If val is nil or not a pointer, Unmarshal returns
// InvalidUnmarshalError.
//
// When unmarshaling BSON, if the BSON value is null and the Go value is a
// pointer, the pointer is set to nil without calling UnmarshalBSONValue.
func Unmarshal(data []byte, val interface{}) error {
return UnmarshalWithRegistry(DefaultRegistry, data, val)
}

View file

@ -8,6 +8,7 @@ package bsoncore // import "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
import (
"bytes"
"encoding/binary"
"fmt"
"math"
"strconv"
@ -706,17 +707,16 @@ func ReserveLength(dst []byte) (int32, []byte) {
// UpdateLength updates the length at index with length and returns the []byte.
func UpdateLength(dst []byte, index, length int32) []byte {
dst[index] = byte(length)
dst[index+1] = byte(length >> 8)
dst[index+2] = byte(length >> 16)
dst[index+3] = byte(length >> 24)
binary.LittleEndian.PutUint32(dst[index:], uint32(length))
return dst
}
func appendLength(dst []byte, l int32) []byte { return appendi32(dst, l) }
func appendi32(dst []byte, i32 int32) []byte {
return append(dst, byte(i32), byte(i32>>8), byte(i32>>16), byte(i32>>24))
b := []byte{0, 0, 0, 0}
binary.LittleEndian.PutUint32(b, uint32(i32))
return append(dst, b...)
}
// ReadLength reads an int32 length from src and returns the length and the remaining bytes. If
@ -734,27 +734,26 @@ func readi32(src []byte) (int32, []byte, bool) {
if len(src) < 4 {
return 0, src, false
}
return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24), src[4:], true
return int32(binary.LittleEndian.Uint32(src)), src[4:], true
}
func appendi64(dst []byte, i64 int64) []byte {
return append(dst,
byte(i64), byte(i64>>8), byte(i64>>16), byte(i64>>24),
byte(i64>>32), byte(i64>>40), byte(i64>>48), byte(i64>>56),
)
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
binary.LittleEndian.PutUint64(b, uint64(i64))
return append(dst, b...)
}
func readi64(src []byte) (int64, []byte, bool) {
if len(src) < 8 {
return 0, src, false
}
i64 := (int64(src[0]) | int64(src[1])<<8 | int64(src[2])<<16 | int64(src[3])<<24 |
int64(src[4])<<32 | int64(src[5])<<40 | int64(src[6])<<48 | int64(src[7])<<56)
return i64, src[8:], true
return int64(binary.LittleEndian.Uint64(src)), src[8:], true
}
func appendu32(dst []byte, u32 uint32) []byte {
return append(dst, byte(u32), byte(u32>>8), byte(u32>>16), byte(u32>>24))
b := []byte{0, 0, 0, 0}
binary.LittleEndian.PutUint32(b, u32)
return append(dst, b...)
}
func readu32(src []byte) (uint32, []byte, bool) {
@ -762,23 +761,20 @@ func readu32(src []byte) (uint32, []byte, bool) {
return 0, src, false
}
return (uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24), src[4:], true
return binary.LittleEndian.Uint32(src), src[4:], true
}
func appendu64(dst []byte, u64 uint64) []byte {
return append(dst,
byte(u64), byte(u64>>8), byte(u64>>16), byte(u64>>24),
byte(u64>>32), byte(u64>>40), byte(u64>>48), byte(u64>>56),
)
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
binary.LittleEndian.PutUint64(b, u64)
return append(dst, b...)
}
func readu64(src []byte) (uint64, []byte, bool) {
if len(src) < 8 {
return 0, src, false
}
u64 := (uint64(src[0]) | uint64(src[1])<<8 | uint64(src[2])<<16 | uint64(src[3])<<24 |
uint64(src[4])<<32 | uint64(src[5])<<40 | uint64(src[6])<<48 | uint64(src[7])<<56)
return u64, src[8:], true
return binary.LittleEndian.Uint64(src), src[8:], true
}
// keep in sync with readcstringbytes

View file

@ -4,10 +4,18 @@
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Package bsoncore contains functions that can be used to encode and decode BSON
// elements and values to or from a slice of bytes. These functions are aimed at
// allowing low level manipulation of BSON and can be used to build a higher
// level BSON library.
// Package bsoncore is intended for internal use only. It is made available to
// facilitate use cases that require access to internal MongoDB driver
// functionality and state. The API of this package is not stable and there is
// no backward compatibility guarantee.
//
// WARNING: THIS PACKAGE IS EXPERIMENTAL AND MAY BE MODIFIED OR REMOVED WITHOUT
// NOTICE! USE WITH EXTREME CAUTION!
//
// Package bsoncore contains functions that can be used to encode and decode
// BSON elements and values to or from a slice of bytes. These functions are
// aimed at allowing low level manipulation of BSON and can be used to build a
// higher level BSON library.
//
// The Read* functions within this package return the values of the element and
// a boolean indicating if the values are valid. A boolean was used instead of
@ -15,15 +23,12 @@
// enough bytes. This library attempts to do no validation, it will only return
// false if there are not enough bytes for an item to be read. For example, the
// ReadDocument function checks the length, if that length is larger than the
// number of bytes available, it will return false, if there are enough bytes, it
// will return those bytes and true. It is the consumers responsibility to
// number of bytes available, it will return false, if there are enough bytes,
// it will return those bytes and true. It is the consumers responsibility to
// validate those bytes.
//
// The Append* functions within this package will append the type value to the
// given dst slice. If the slice has enough capacity, it will not grow the
// slice. The Append*Element functions within this package operate in the same
// way, but additionally append the BSON type and the key before the value.
//
// Warning: Package bsoncore is unstable and there is no backward compatibility
// guarantee. It is experimental and subject to change.
package bsoncore

View file

@ -51,7 +51,7 @@ func (e Element) KeyErr() (string, error) {
// KeyBytesErr returns the key for this element as a []byte, returning an error if the element is
// not valid.
func (e Element) KeyBytesErr() ([]byte, error) {
if len(e) <= 0 {
if len(e) == 0 {
return nil, ErrElementMissingType
}
idx := bytes.IndexByte(e[1:], 0x00)
@ -99,7 +99,7 @@ func (e Element) Value() Value {
// ValueErr returns the value for this element, returning an error if the element is not valid.
func (e Element) ValueErr() (Value, error) {
if len(e) <= 0 {
if len(e) == 0 {
return Value{}, ErrElementMissingType
}
idx := bytes.IndexByte(e[1:], 0x00)
@ -116,7 +116,7 @@ func (e Element) ValueErr() (Value, error) {
// String implements the fmt.String interface. The output will be in extended JSON format.
func (e Element) String() string {
if len(e) <= 0 {
if len(e) == 0 {
return ""
}
t := bsontype.Type(e[0])
@ -135,7 +135,7 @@ func (e Element) String() string {
// DebugString outputs a human readable version of RawElement. It will attempt to stringify the
// valid components of the element even if the entire element is not valid.
func (e Element) DebugString() string {
if len(e) <= 0 {
if len(e) == 0 {
return "<malformed>"
}
t := bsontype.Type(e[0])

View file

@ -924,13 +924,14 @@ func escapeString(s string) string {
func formatDouble(f float64) string {
var s string
if math.IsInf(f, 1) {
switch {
case math.IsInf(f, 1):
s = "Infinity"
} else if math.IsInf(f, -1) {
case math.IsInf(f, -1):
s = "-Infinity"
} else if math.IsNaN(f) {
case math.IsNaN(f):
s = "NaN"
} else {
default:
// Print exactly one decimalType place for integers; otherwise, print as many are necessary to
// perfectly represent it.
s = strconv.FormatFloat(f, 'G', -1, 64)
@ -953,9 +954,7 @@ func (ss sortableString) Less(i, j int) bool {
}
func (ss sortableString) Swap(i, j int) {
oldI := ss[i]
ss[i] = ss[j]
ss[j] = oldI
ss[i], ss[j] = ss[j], ss[i]
}
func sortStringAlphebeticAscending(s string) string {

View file

@ -667,12 +667,14 @@ func gnuArg(inst *Inst, pc uint64, symname SymLookup, x Arg, usedPrefixes *bool)
}
}
case Imm:
if s, base := symname(uint64(x)); s != "" {
suffix := ""
if uint64(x) != base {
suffix = fmt.Sprintf("%+d", uint64(x)-base)
if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
if s, base := symname(uint64(x)); s != "" {
suffix := ""
if uint64(x) != base {
suffix = fmt.Sprintf("%+d", uint64(x)-base)
}
return fmt.Sprintf("$%s%s", s, suffix)
}
return fmt.Sprintf("$%s%s", s, suffix)
}
if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(x))

View file

@ -341,12 +341,14 @@ func IntelSyntax(inst Inst, pc uint64, symname SymLookup) string {
func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string {
switch a := arg.(type) {
case Imm:
if s, base := symname(uint64(a)); s != "" {
suffix := ""
if uint64(a) != base {
suffix = fmt.Sprintf("%+d", uint64(a)-base)
if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
if s, base := symname(uint64(a)); s != "" {
suffix := ""
if uint64(a) != base {
suffix = fmt.Sprintf("%+d", uint64(a)-base)
}
return fmt.Sprintf("$%s%s", s, suffix)
}
return fmt.Sprintf("$%s%s", s, suffix)
}
if inst.Mode == 32 {
return fmt.Sprintf("%#x", uint32(a))

View file

@ -116,12 +116,23 @@ func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg
return fmt.Sprintf("%#x", addr)
case Imm:
if s, base := symname(uint64(a)); s != "" {
suffix := ""
if uint64(a) != base {
suffix = fmt.Sprintf("%+d", uint64(a)-base)
if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 {
// Only try to convert an immediate to a symbol in certain
// special circumstances. See issue 72942.
//
// On 64-bit, symbol addresses always hit the Mem case below.
// Particularly, we use LEAQ to materialize the address of
// a global or function.
//
// On 32-bit, we sometimes use MOVL. Still try to symbolize
// those immediates.
if s, base := symname(uint64(a)); s != "" {
suffix := ""
if uint64(a) != base {
suffix = fmt.Sprintf("%+d", uint64(a)-base)
}
return fmt.Sprintf("$%s%s(SB)", s, suffix)
}
return fmt.Sprintf("$%s%s(SB)", s, suffix)
}
if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(a))

View file

@ -288,7 +288,7 @@ func (tf *tokenRefresher) Token() (*Token, error) {
if tf.refreshToken != tk.RefreshToken {
tf.refreshToken = tk.RefreshToken
}
return tk, err
return tk, nil
}
// reuseTokenSource is a TokenSource that holds a single token in memory
@ -356,11 +356,15 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client {
if src == nil {
return internal.ContextClient(ctx)
}
cc := internal.ContextClient(ctx)
return &http.Client{
Transport: &Transport{
Base: internal.ContextClient(ctx).Transport,
Base: cc.Transport,
Source: ReuseTokenSource(nil, src),
},
CheckRedirect: cc.CheckRedirect,
Jar: cc.Jar,
Timeout: cc.Timeout,
}
}

View file

@ -169,7 +169,7 @@ func tokenFromInternal(t *internal.Token) *Token {
// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
// with an error..
// with an error.
func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get())
if err != nil {

22
vendor/modules.txt vendored
View file

@ -420,8 +420,8 @@ github.com/gin-contrib/cors
# github.com/gin-contrib/gzip v1.2.3
## explicit; go 1.23.0
github.com/gin-contrib/gzip
# github.com/gin-contrib/sessions v1.0.2
## explicit; go 1.20
# github.com/gin-contrib/sessions v1.0.3
## explicit; go 1.23.0
github.com/gin-contrib/sessions
github.com/gin-contrib/sessions/memstore
# github.com/gin-contrib/sse v1.0.0
@ -580,8 +580,8 @@ github.com/gorilla/handlers
# github.com/gorilla/securecookie v1.1.2
## explicit; go 1.20
github.com/gorilla/securecookie
# github.com/gorilla/sessions v1.2.2
## explicit; go 1.20
# github.com/gorilla/sessions v1.4.0
## explicit; go 1.23
github.com/gorilla/sessions
# github.com/gorilla/websocket v1.5.3
## explicit; go 1.12
@ -833,11 +833,11 @@ github.com/stretchr/testify/suite
# github.com/subosito/gotenv v1.6.0
## explicit; go 1.18
github.com/subosito/gotenv
# github.com/tdewolff/minify/v2 v2.23.0
# github.com/tdewolff/minify/v2 v2.23.1
## explicit; go 1.18.0
github.com/tdewolff/minify/v2
github.com/tdewolff/minify/v2/html
# github.com/tdewolff/parse/v2 v2.7.22
# github.com/tdewolff/parse/v2 v2.7.23
## explicit; go 1.13
github.com/tdewolff/parse/v2
github.com/tdewolff/parse/v2/buffer
@ -960,8 +960,8 @@ github.com/vmihailenco/tagparser/v2/internal/parser
# github.com/wagslane/go-password-validator v0.3.0
## explicit; go 1.16
github.com/wagslane/go-password-validator
# github.com/yuin/goldmark v1.7.8
## explicit; go 1.19
# github.com/yuin/goldmark v1.7.10
## explicit; go 1.22
github.com/yuin/goldmark
github.com/yuin/goldmark/ast
github.com/yuin/goldmark/extension
@ -971,7 +971,7 @@ github.com/yuin/goldmark/renderer
github.com/yuin/goldmark/renderer/html
github.com/yuin/goldmark/text
github.com/yuin/goldmark/util
# go.mongodb.org/mongo-driver v1.14.0
# go.mongodb.org/mongo-driver v1.17.3
## explicit; go 1.18
go.mongodb.org/mongo-driver/bson
go.mongodb.org/mongo-driver/bson/bsoncodec
@ -1066,7 +1066,7 @@ go.uber.org/automaxprocs/maxprocs
# go.uber.org/multierr v1.11.0
## explicit; go 1.19
go.uber.org/multierr
# golang.org/x/arch v0.15.0
# golang.org/x/arch v0.16.0
## explicit; go 1.23.0
golang.org/x/arch/x86/x86asm
# golang.org/x/crypto v0.37.0
@ -1123,7 +1123,7 @@ golang.org/x/net/ipv4
golang.org/x/net/ipv6
golang.org/x/net/publicsuffix
golang.org/x/net/trace
# golang.org/x/oauth2 v0.27.0
# golang.org/x/oauth2 v0.29.0
## explicit; go 1.23.0
golang.org/x/oauth2
golang.org/x/oauth2/internal

View file

@ -17,6 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
WHAT SHOULD GO IN THIS FILE?
This script is loaded in the document head, and deferred + async,
so it's *usually* run after the user is already looking at the page.
Put stuff in here that doesn't shift the layout, and it doesn't really
matter whether it loads immediately. So, progressive enhancement stuff.
*/
const Photoswipe = require("photoswipe/dist/umd/photoswipe.umd.min.js");
const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js");
const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default;
@ -165,89 +174,6 @@ lightbox.on('uiRegister', function() {
lightbox.init();
function dynamicSpoiler(className, updateFunc) {
Array.from(document.getElementsByClassName(className)).forEach((spoiler) => {
const update = updateFunc(spoiler);
if (update) {
update();
spoiler.addEventListener("toggle", update);
}
});
}
dynamicSpoiler("text-spoiler", (details) => {
const summary = details.children[0];
const button = details.querySelector(".button");
// Use button *instead of summary*
// to toggle post visibility.
summary.tabIndex = "-1";
button.tabIndex = "0";
button.setAttribute("aria-role", "button");
button.onclick = (e) => {
e.preventDefault();
return details.hasAttribute("open")
? details.removeAttribute("open")
: details.setAttribute("open", "");
};
// Let enter also trigger the button
// (for those using keyboard to navigate).
button.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
button.click();
}
});
// Change button text depending on
// whether spoiler is open or closed rn.
return () => {
button.textContent = details.open
? "Show less"
: "Show more";
};
});
dynamicSpoiler("media-spoiler", (details) => {
const summary = details.children[0];
const button = details.querySelector(".eye.button");
const video = details.querySelector(".plyr-video");
const loopingAuto = !reduceMotion.matches && video != null && video.classList.contains("gifv");
// Use button *instead of summary*
// to toggle media visibility.
summary.tabIndex = "-1";
button.tabIndex = "0";
button.setAttribute("aria-role", "button");
button.onclick = (e) => {
e.preventDefault();
return details.hasAttribute("open")
? details.removeAttribute("open")
: details.setAttribute("open", "");
};
// Let enter also trigger the button
// (for those using keyboard to navigate).
button.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
button.click();
}
});
return () => {
if (details.open) {
button.setAttribute("aria-label", "Hide media");
} else {
button.setAttribute("aria-label", "Show media");
if (video && !loopingAuto) {
video.pause();
}
}
};
});
Array.from(document.getElementsByClassName("plyr-video")).forEach((video) => {
const loopingAuto = !reduceMotion.matches && video.classList.contains("gifv");
let player = new Plyr(video, {
@ -315,30 +241,6 @@ function inLightbox(element) {
lightbox.pswp.currSlide.data.attachmentId;
}
// Define + reuse one DateTimeFormat (cheaper).
const dateTimeFormat = Intl.DateTimeFormat(
undefined,
{
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
},
);
// Reformat time text to browser locale.
Array.from(document.getElementsByTagName('time')).forEach(timeTag => {
const datetime = timeTag.getAttribute('datetime');
const currentText = timeTag.textContent.trim();
// Only format if current text contains precise time.
if (currentText.match(/\d{2}:\d{2}/)) {
const date = new Date(datetime);
timeTag.textContent = dateTimeFormat.format(date);
}
});
// When clicking anywhere that's not an open
// stats-info-more-content details dropdown,
// close that open dropdown.

View file

@ -17,8 +17,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
WHAT SHOULD GO IN THIS FILE?
This script is loaded just before the end of the HTML body, so
put stuff in here that should be run *before* the user sees the page.
So, stuff that shifts the layout or causes elements to jump around.
*/
import { decode } from "blurhash";
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
// Generate a blurhash canvas for each image for
// each blurhash container and put it in the summary.
Array.from(document.getElementsByClassName('blurhash-container')).forEach(blurhashContainer => {
@ -144,3 +154,110 @@ Array.from(document.getElementsByTagName('img')).forEach(img => {
}
});
});
// Change the spoiler / content warning boxes from generic
// "toggle visibility" to show/hide depending on state,
// and add keyboard functionality to spoiler buttons.
function dynamicSpoiler(className, updateFunc) {
Array.from(document.getElementsByClassName(className)).forEach((spoiler) => {
const update = updateFunc(spoiler);
if (update) {
update();
spoiler.addEventListener("toggle", update);
}
});
}
dynamicSpoiler("text-spoiler", (details) => {
const summary = details.children[0];
const button = details.querySelector(".button");
// Use button *instead of summary*
// to toggle post visibility.
summary.tabIndex = "-1";
button.tabIndex = "0";
button.setAttribute("aria-role", "button");
button.onclick = (e) => {
e.preventDefault();
return details.hasAttribute("open")
? details.removeAttribute("open")
: details.setAttribute("open", "");
};
// Let enter also trigger the button
// (for those using keyboard to navigate).
button.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
button.click();
}
});
// Change button text depending on
// whether spoiler is open or closed rn.
return () => {
button.textContent = details.open
? "Show less"
: "Show more";
};
});
dynamicSpoiler("media-spoiler", (details) => {
const summary = details.children[0];
const button = details.querySelector(".eye.button");
const video = details.querySelector(".plyr-video");
const loopingAuto = !reduceMotion.matches && video != null && video.classList.contains("gifv");
// Use button *instead of summary*
// to toggle media visibility.
summary.tabIndex = "-1";
button.tabIndex = "0";
button.setAttribute("aria-role", "button");
button.onclick = (e) => {
e.preventDefault();
return details.hasAttribute("open")
? details.removeAttribute("open")
: details.setAttribute("open", "");
};
// Let enter also trigger the button
// (for those using keyboard to navigate).
button.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
button.click();
}
});
return () => {
if (details.open) {
button.setAttribute("aria-label", "Hide media");
} else {
button.setAttribute("aria-label", "Show media");
if (video && !loopingAuto) {
video.pause();
}
}
};
});
// Reformat time text to browser locale.
// Define + reuse one DateTimeFormat (cheaper).
const dateTimeFormat = Intl.DateTimeFormat(
undefined,
{
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
},
);
Array.from(document.getElementsByTagName('time')).forEach(timeTag => {
const datetime = timeTag.getAttribute('datetime');
const currentText = timeTag.textContent.trim();
// Only format if current text contains precise time.
if (currentText.match(/\d{2}:\d{2}/)) {
const date = new Date(datetime);
timeTag.textContent = dateTimeFormat.format(date);
}
});

View file

@ -64,9 +64,9 @@ skulk({
}]
],
},
blurhash: {
entryFile: "blurhash",
outputFile: "blurhash.js",
frontend_prerender: {
entryFile: "frontend_prerender",
outputFile: "frontend_prerender.js",
preset: ["js"],
prodCfg: prodCfg,
transform: [