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/coreos/go-oidc/v3 v3.12.0
github.com/gin-contrib/cors v1.7.4 github.com/gin-contrib/cors v1.7.4
github.com/gin-contrib/gzip v1.2.3 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/gin-gonic/gin v1.10.0
github.com/go-playground/form/v4 v4.2.1 github.com/go-playground/form/v4 v4.2.1
github.com/go-swagger/go-swagger v0.31.0 github.com/go-swagger/go-swagger v0.31.0
@ -62,7 +62,7 @@ require (
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.20.1 github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0 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/technologize/otel-go-contrib v1.1.1
github.com/temoto/robotstxt v1.1.2 github.com/temoto/robotstxt v1.1.2
github.com/tetratelabs/wazero v1.9.0 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/dialect/sqlitedialect v1.2.11
github.com/uptrace/bun/extra/bunotel v1.2.11 github.com/uptrace/bun/extra/bunotel v1.2.11
github.com/wagslane/go-password-validator v0.3.0 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 v1.35.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc 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 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/crypto v0.37.0
golang.org/x/image v0.24.0 golang.org/x/image v0.24.0
golang.org/x/net v0.38.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/sys v0.32.0
golang.org/x/text v0.24.0 golang.org/x/text v0.24.0
gopkg.in/mcuadros/go-syslog.v2 v2.3.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/css v1.0.1 // indirect
github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/securecookie v1.1.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/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // 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/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // 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/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // 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/uptrace/opentelemetry-go-extra/otelsql v0.3.2 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // 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/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.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/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/mod v0.24.0 // indirect golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.13.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/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 h1:dAhT722RuEG330ce2agAs75z7yB+NKvX/ZM1r8w0u2U=
github.com/gin-contrib/gzip v1.2.3/go.mod h1:ad72i4Bzmaypk8M762gNXa2wkxxjbz0icRNnuLJ9a/c= 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.3 h1:AZ4j0AalLsGqdrKNbbrKcXx9OJZqViirvNGsJTxcQps=
github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs= 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 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= 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/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 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= 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.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= 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 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= 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/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 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= 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.1 h1:r6sKQrumHzskWZRdhiRa+pZhn7CdBMojACNP9fuKpXQ=
github.com/tdewolff/minify/v2 v2.23.0/go.mod h1:ll/rxPfOGIgN9G4JXg+3jMtPTPEnEJB3nGtEG08sHl8= github.com/tdewolff/minify/v2 v2.23.1/go.mod h1:RkUGjklq6uIsBoOdzY3ll35HKKQ2aFqLQhnanBHhDyU=
github.com/tdewolff/parse/v2 v2.7.22 h1:ROVbrjtp5RoXi22YSZaOks5DaOcXBJ3PZO5hyyQ9Bbs= github.com/tdewolff/parse/v2 v2.7.23 h1:sCW2PNTCM1yVldh5YK/8wrpRI9rSbloUZWjAydlN2IA=
github.com/tdewolff/parse/v2 v2.7.22/go.mod h1:I7TXO37t3aSG9SlPUBefAhgIF8nt7yYUwVGgETIoBcA= 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 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/technologize/otel-go-contrib v1.1.1 h1:wZH9aSPNWZWIkEh3vfaKfMb15AJ80jJ1aVj/4GZdqIw= 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 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= 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.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.10 h1:S+LrtBjRmqMac2UdtB6yyCEJm+UILZ2fefI4p7o0QpI=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= 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 h1:QbfrBqNKgAFSSK89fYf547vxDQuz8p6iJUzzAMrusNk=
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.37.0-concurrency-workaround/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= 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.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= 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 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= 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/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 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= 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-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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 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.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 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-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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/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 var errWithCode gtserror.WithCode
if domainPerm != nil { if !util.IsNil(domainPerm) {
// Permission already exists, update it. // Permission already exists, update it.
apiDomainPerm, errWithCode = p.DomainPermissionUpdate( apiDomainPerm, errWithCode = p.DomainPermissionUpdate(
ctx, ctx,
@ -394,15 +394,21 @@ func (p *Processor) DomainPermissionGet(
err = gtserror.New("unrecognized permission type") err = gtserror.New("unrecognized permission type")
} }
if err != nil { if err != nil && errors.Is(err, db.ErrNoEntries) {
if errors.Is(err, db.ErrNoEntries) { err = gtserror.Newf(
err = fmt.Errorf("no domain %s exists with id %s", permissionType.String(), id) "db error getting domain %s with id %s: %w",
return nil, gtserror.NewErrorNotFound(err, err.Error()) permissionType.String(), id, err,
} )
err = gtserror.Newf("error getting domain %s with id %s: %w", permissionType.String(), id, err)
return nil, gtserror.NewErrorInternalError(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) return p.apiDomainPerm(ctx, domainPerm, export)
} }

View file

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

View file

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

View file

@ -67,9 +67,9 @@ const (
cssSettings = distPathPrefix + "/settings-style.css" cssSettings = distPathPrefix + "/settings-style.css"
cssTag = distPathPrefix + "/tag.css" cssTag = distPathPrefix + "/tag.css"
jsFrontend = distPathPrefix + "/frontend.js" // Progressive enhancement frontend JS. jsFrontend = distPathPrefix + "/frontend.js" // Progressive enhancement frontend JS.
jsBlurhash = distPathPrefix + "/blurhash.js" // Blurhash rendering JS. jsFrontendPrerender = distPathPrefix + "/frontend_prerender.js" // Frontend JS that should run before page renders.
jsSettings = distPathPrefix + "/settings.js" // Settings panel React application. jsSettings = distPathPrefix + "/settings.js" // Settings panel React application.
) )
type Module struct { 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 package sessions
import ( import (
"log" "log/slog"
"net/http" "net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -11,7 +11,7 @@ import (
const ( const (
DefaultKey = "github.com/gin-contrib/sessions" DefaultKey = "github.com/gin-contrib/sessions"
errorFormat = "[sessions] ERROR! %s\n" errorFormat = "[sessions] ERROR!"
) )
type Store interface { type Store interface {
@ -131,7 +131,10 @@ func (s *session) Session() *sessions.Session {
var err error var err error
s.session, err = s.store.Get(s.request, s.name) s.session, err = s.store.Get(s.request, s.name)
if err != nil { if err != nil {
log.Printf(errorFormat, err) slog.Error(errorFormat,
"err", err,
)
return nil
} }
} }
return s.session 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are 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) ![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) [![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{}`. 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. And finally we call `session.Save()` to save the session in the response.
More examples are available [on the Gorilla More examples are available at [package documentation](https://pkg.go.dev/github.com/gorilla/sessions).
website](https://www.gorillatoolkit.org/pkg/sessions).
## Store Implementations ## 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/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/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB
- [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL - [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/EnumApps/clustersqlstore](https://github.com/EnumApps/clustersqlstore) - MySQL Cluster
- [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL - [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL
- [github.com/boj/redistore](https://github.com/boj/redistore) - Redis - [github.com/boj/redistore](https://github.com/boj/redistore) - Redis

View file

@ -1,5 +1,6 @@
//go:build !go1.11 // Copyright 2012 The Gorilla Authors. All rights reserved.
// +build !go1.11 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sessions package sessions
@ -8,13 +9,15 @@ import "net/http"
// newCookieFromOptions returns an http.Cookie with the options set. // newCookieFromOptions returns an http.Cookie with the options set.
func newCookieFromOptions(name, value string, options *Options) *http.Cookie { func newCookieFromOptions(name, value string, options *Options) *http.Cookie {
return &http.Cookie{ return &http.Cookie{
Name: name, Name: name,
Value: value, Value: value,
Path: options.Path, Path: options.Path,
Domain: options.Domain, Domain: options.Domain,
MaxAge: options.MaxAge, MaxAge: options.MaxAge,
Secure: options.Secure, Secure: options.Secure,
HttpOnly: options.HttpOnly, 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 // Copyright 2012 The Gorilla Authors. All rights reserved.
// +build !go1.11 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sessions package sessions
import "net/http"
// Options stores configuration for a session or session store. // Options stores configuration for a session or session store.
// //
// Fields are a subset of http.Cookie fields. // Fields are a subset of http.Cookie fields.
@ -13,7 +16,9 @@ type Options struct {
// deleted after the browser session ends. // deleted after the browser session ends.
// MaxAge<0 means delete cookie immediately. // MaxAge<0 means delete cookie immediately.
// MaxAge>0 means Max-Age attribute present and given in seconds. // MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int MaxAge int
Secure bool Secure bool
HttpOnly 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" "github.com/gorilla/securecookie"
) )
const (
// File name prefix for session files.
sessionFilePrefix = "session_"
)
// Store is an interface for custom session stores. // Store is an interface for custom session stores.
// //
// See CookieStore and FilesystemStore for examples. // See CookieStore and FilesystemStore for examples.
@ -49,8 +54,10 @@ func NewCookieStore(keyPairs ...[]byte) *CookieStore {
cs := &CookieStore{ cs := &CookieStore{
Codecs: securecookie.CodecsFromPairs(keyPairs...), Codecs: securecookie.CodecsFromPairs(keyPairs...),
Options: &Options{ Options: &Options{
Path: "/", Path: "/",
MaxAge: 86400 * 30, MaxAge: 86400 * 30,
SameSite: http.SameSiteNoneMode,
Secure: true,
}, },
} }
@ -257,7 +264,7 @@ func (s *FilesystemStore) save(session *Session) error {
if err != nil { if err != nil {
return err return err
} }
filename := filepath.Join(s.path, "session_"+session.ID) filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID))
fileMutex.Lock() fileMutex.Lock()
defer fileMutex.Unlock() defer fileMutex.Unlock()
return os.WriteFile(filename, []byte(encoded), 0600) 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. // load reads a file and decodes its content into session.Values.
func (s *FilesystemStore) load(session *Session) error { 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() fileMutex.RLock()
defer fileMutex.RUnlock() defer fileMutex.RUnlock()
fdata, err := os.ReadFile(filepath.Clean(filename)) fdata, err := os.ReadFile(filepath.Clean(filename))
@ -281,7 +288,7 @@ func (s *FilesystemStore) load(session *Session) error {
// delete session file // delete session file
func (s *FilesystemStore) erase(session *Session) error { 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() fileMutex.RLock()
defer fileMutex.RUnlock() defer fileMutex.RUnlock()

View file

@ -162,7 +162,16 @@ func (l *Lexer) Next() (TokenType, []byte) {
for { for {
c = l.r.Peek(0) 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) c = l.r.Peek(1)
isEndTag := c == '/' && l.r.Peek(2) != '>' && (l.r.Peek(2) != 0 || l.r.PeekErr(2) == nil) 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 != '?' { 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) l.r.Move(1)
return CommentToken, l.shiftBogusComment() 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 { } else if c == 0 && l.r.Err() != nil {
if 0 < l.r.Pos() { if 0 < l.r.Pos() {
l.text = l.r.Shift() l.text = l.r.Shift()

View file

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

View file

@ -1,4 +1,4 @@
.PHONY: test fuzz lint .PHONY: test fuzz lint gen
lint: lint:
golangci-lint run -c .golangci.yml ./... golangci-lint run -c .golangci.yml ./...
@ -10,4 +10,7 @@ cov: test
go tool cover -html=profile.out go tool cover -html=profile.out
fuzz: 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://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://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) [![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-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-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-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-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()`. - [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. // TableAttributeFilter defines attribute names which table elements can have.
var TableAttributeFilter = html.GlobalAttributeFilter.Extend( //
[]byte("align"), // [Deprecated] // - align: Deprecated
[]byte("bgcolor"), // [Deprecated] // - bgcolor: Deprecated
[]byte("border"), // [Deprecated] // - border: Deprecated
[]byte("cellpadding"), // [Deprecated] // - cellpadding: Deprecated
[]byte("cellspacing"), // [Deprecated] // - cellspacing: Deprecated
[]byte("frame"), // [Deprecated] // - frame: Deprecated
[]byte("rules"), // [Deprecated] // - rules: Deprecated
[]byte("summary"), // [Deprecated] // - summary: Deprecated
[]byte("width"), // [Deprecated] // - width: Deprecated.
) var TableAttributeFilter = html.GlobalAttributeFilter.ExtendString(`align,bgcolor,border,cellpadding,cellspacing,frame,rules,summary,width`) // nolint: lll
func (r *TableHTMLRenderer) renderTable( func (r *TableHTMLRenderer) renderTable(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) { 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. // TableHeaderAttributeFilter defines attribute names which <thead> elements can have.
var TableHeaderAttributeFilter = html.GlobalAttributeFilter.Extend( //
[]byte("align"), // [Deprecated since HTML4] [Obsolete since HTML5] // - align: Deprecated since HTML4, Obsolete since HTML5
[]byte("bgcolor"), // [Not Standardized] // - bgcolor: Not Standardized
[]byte("char"), // [Deprecated since HTML4] [Obsolete since HTML5] // - char: Deprecated since HTML4, Obsolete since HTML5
[]byte("charoff"), // [Deprecated since HTML4] [Obsolete since HTML5] // - charoff: Deprecated since HTML4, Obsolete since HTML5
[]byte("valign"), // [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( func (r *TableHTMLRenderer) renderTableHeader(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) { 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. // TableRowAttributeFilter defines attribute names which <tr> elements can have.
var TableRowAttributeFilter = html.GlobalAttributeFilter.Extend( //
[]byte("align"), // [Obsolete since HTML5] // - align: Obsolete since HTML5
[]byte("bgcolor"), // [Obsolete since HTML5] // - bgcolor: Obsolete since HTML5
[]byte("char"), // [Obsolete since HTML5] // - char: Obsolete since HTML5
[]byte("charoff"), // [Obsolete since HTML5] // - charoff: Obsolete since HTML5
[]byte("valign"), // [Obsolete since HTML5] // - valign: Obsolete since HTML5.
) var TableRowAttributeFilter = html.GlobalAttributeFilter.ExtendString(`align,bgcolor,char,charoff,valign`)
func (r *TableHTMLRenderer) renderTableRow( func (r *TableHTMLRenderer) renderTableRow(
w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) { 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. // 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>] // - abbr: [OK] Contains a short abbreviated description of the cell's content [NOT OK in <td>]
// - align: Obsolete since HTML5
[]byte("align"), // [Obsolete since HTML5] // - axis: Obsolete since HTML5
[]byte("axis"), // [Obsolete since HTML5] // - bgcolor: Not Standardized
[]byte("bgcolor"), // [Not Standardized] // - char: Obsolete since HTML5
[]byte("char"), // [Obsolete since HTML5] // - charoff: Obsolete since HTML5
[]byte("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,
[]byte("colspan"), // [OK] Number of columns that the cell is to span // each corresponding to the id attribute of the <th> elements that apply to this element
[]byte("headers"), // [OK] This attribute contains a list of space-separated // - height: Deprecated since HTML4. Obsolete since HTML5
// strings, each corresponding to the id attribute of the <th> elements that apply to this element // - rowspan: [OK] Number of rows that the cell is to span
// - scope: [OK] This enumerated attribute defines the cells that the header
[]byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5] // (defined in the <th>) element relates to [NOT OK in <td>]
// - valign: Obsolete since HTML5
[]byte("rowspan"), // [OK] Number of rows that the cell is to span // - width: Deprecated since HTML4. Obsolete since HTML5.
[]byte("scope"), // [OK] This enumerated attribute defines the cells that var TableThCellAttributeFilter = html.GlobalAttributeFilter.ExtendString(`abbr,align,axis,bgcolor,char,charoff,colspan,headers,height,rowspan,scope,valign,width`) // nolint:lll
// 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]
)
// TableTdCellAttributeFilter defines attribute names which table <td> cells can have. // TableTdCellAttributeFilter defines attribute names which table <td> cells can have.
var TableTdCellAttributeFilter = html.GlobalAttributeFilter.Extend( //
[]byte("abbr"), // [Obsolete since HTML5] [OK in <th>] // - abbr: Obsolete since HTML5. [OK in <th>]
[]byte("align"), // [Obsolete since HTML5] // - align: Obsolete since HTML5
[]byte("axis"), // [Obsolete since HTML5] // - axis: Obsolete since HTML5
[]byte("bgcolor"), // [Not Standardized] // - bgcolor: Not Standardized
[]byte("char"), // [Obsolete since HTML5] // - char: Obsolete since HTML5
[]byte("charoff"), // [Obsolete since HTML5] // - charoff: Obsolete since HTML5
// - colspan: [OK] Number of columns that the cell is to span
[]byte("colspan"), // [OK] Number of columns that the cell is to span // - headers: [OK] This attribute contains a list of space-separated strings, each corresponding
[]byte("headers"), // [OK] This attribute contains a list of space-separated // to the id attribute of the <th> elements that apply to this element
// 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
[]byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5] // - scope: Obsolete since HTML5. [OK in <th>]
// - valign: Obsolete since HTML5
[]byte("rowspan"), // [OK] Number of rows that the cell is to span // - 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
[]byte("scope"), // [Obsolete since HTML5] [OK in <th>]
[]byte("valign"), // [Obsolete since HTML5]
[]byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
)
func (r *TableHTMLRenderer) renderTableCell( func (r *TableHTMLRenderer) renderTableCell(
w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { 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. // 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 i := 0
c := line[i] c := line[i]
j := 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++ { for ; j < len(line) && c == line[j]; j++ {
} }
if (j - i) >= min { if (j - i) >= minimum {
after := rune(' ') after := rune(' ')
if j != len(line) { if j != len(line) {
after = util.ToRune(line, j) 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. // GlobalAttributeFilter defines attribute names which any elements can have.
var GlobalAttributeFilter = util.NewBytesFilter( 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
[]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"),
)
func (r *Renderer) renderDocument( func (r *Renderer) renderDocument(
w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { 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. // BlockquoteAttributeFilter defines attribute names which blockquote elements can have.
var BlockquoteAttributeFilter = GlobalAttributeFilter.Extend( var BlockquoteAttributeFilter = GlobalAttributeFilter.ExtendString(`cite`)
[]byte("cite"),
)
func (r *Renderer) renderBlockquote( func (r *Renderer) renderBlockquote(
w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { 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. // ListAttributeFilter defines attribute names which list elements can have.
var ListAttributeFilter = GlobalAttributeFilter.Extend( var ListAttributeFilter = GlobalAttributeFilter.ExtendString(`start,reversed,type`)
[]byte("start"),
[]byte("reversed"),
[]byte("type"),
)
func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*ast.List) 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. // ListItemAttributeFilter defines attribute names which list item elements can have.
var ListItemAttributeFilter = GlobalAttributeFilter.Extend( var ListItemAttributeFilter = GlobalAttributeFilter.ExtendString(`value`)
[]byte("value"),
)
func (r *Renderer) renderListItem(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { func (r *Renderer) renderListItem(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering { 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. // ThematicAttributeFilter defines attribute names which hr elements can have.
var ThematicAttributeFilter = GlobalAttributeFilter.Extend( var ThematicAttributeFilter = GlobalAttributeFilter.ExtendString(`align,color,noshade,size,width`)
[]byte("align"), // [Deprecated]
[]byte("color"), // [Not Standardized]
[]byte("noshade"), // [Deprecated]
[]byte("size"), // [Deprecated]
[]byte("width"), // [Deprecated]
)
func (r *Renderer) renderThematicBreak( func (r *Renderer) renderThematicBreak(
w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { 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. // LinkAttributeFilter defines attribute names which link elements can have.
var LinkAttributeFilter = GlobalAttributeFilter.Extend( var LinkAttributeFilter = GlobalAttributeFilter.ExtendString(`download,hreflang,media,ping,referrerpolicy,rel,shape,target`) // nolint:lll
[]byte("download"),
// []byte("href"),
[]byte("hreflang"),
[]byte("media"),
[]byte("ping"),
[]byte("referrerpolicy"),
[]byte("rel"),
[]byte("shape"),
[]byte("target"),
)
func (r *Renderer) renderAutoLink( func (r *Renderer) renderAutoLink(
w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { 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. // ImageAttributeFilter defines attribute names which image elements can have.
var ImageAttributeFilter = GlobalAttributeFilter.Extend( var ImageAttributeFilter = GlobalAttributeFilter.ExtendString(`align,border,crossorigin,decoding,height,importance,intrinsicsize,ismap,loading,referrerpolicy,sizes,srcset,usemap,width`) // nolint: lll
[]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"),
)
func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering { 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, ' ')) 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, // EscapeHTMLByte returns HTML escaped bytes if the given byte should be escaped,
// otherwise nil. // otherwise nil.
func EscapeHTMLByte(b byte) []byte { 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. // EscapeHTML escapes characters that should be escaped in HTML text.
@ -545,7 +554,7 @@ func EscapeHTML(v []byte) []byte {
escaped := htmlEscapeTable[c] escaped := htmlEscapeTable[c]
if escaped != nil { if escaped != nil {
cob.Write(v[n:i]) cob.Write(v[n:i])
cob.Write(escaped) cob.Write(*escaped)
n = i + 1 n = i + 1
} }
} }
@ -911,6 +920,10 @@ type BytesFilter interface {
// Extend copies this filter and adds given bytes to new filter. // Extend copies this filter and adds given bytes to new filter.
Extend(...[]byte) BytesFilter 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 { type bytesFilter struct {
@ -931,6 +944,27 @@ func NewBytesFilter(elements ...[]byte) BytesFilter {
return s 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) { func (s *bytesFilter) Add(b []byte) {
l := len(b) l := len(b)
m := s.threshold m := s.threshold
@ -963,6 +997,28 @@ func (s *bytesFilter) Extend(bs ...[]byte) BytesFilter {
return newFilter 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 { func (s *bytesFilter) Contains(b []byte) bool {
l := len(b) l := len(b)
m := s.threshold m := s.threshold

View file

@ -330,7 +330,7 @@ func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReade
case reflect.Int64: case reflect.Int64:
return reflect.ValueOf(i64), nil return reflect.ValueOf(i64), nil
case reflect.Int: 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) 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) return fmt.Errorf("%d overflows uint64", i64)
} }
case reflect.Uint: 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) return fmt.Errorf("%d overflows uint", i64)
} }
default: default:
@ -1521,6 +1521,18 @@ func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(_ DecodeContext, vr
return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} 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.Kind() == reflect.Ptr && val.IsNil() {
if !val.CanSet() { if !val.CanSet() {
return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} 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 return reflect.ValueOf(uint64(i64)), nil
case reflect.Uint: 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 emptyValue, fmt.Errorf("%d overflows uint", i64)
} }
return reflect.ValueOf(uint(i64)), nil return reflect.ValueOf(uint(v)), nil
default: default:
return emptyValue, ValueDecoderError{ return emptyValue, ValueDecoderError{
Name: "UintDecodeValue", Name: "UintDecodeValue",

View file

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

View file

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

View file

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

View file

@ -842,7 +842,7 @@ func (vr *valueReader) peekLength() (int32, error) {
} }
idx := vr.offset 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() } func (vr *valueReader) readLength() (int32, error) { return vr.readi32() }
@ -854,7 +854,7 @@ func (vr *valueReader) readi32() (int32, error) {
idx := vr.offset idx := vr.offset
vr.offset += 4 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) { func (vr *valueReader) readu32() (uint32, error) {
@ -864,7 +864,7 @@ func (vr *valueReader) readu32() (uint32, error) {
idx := vr.offset idx := vr.offset
vr.offset += 4 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) { func (vr *valueReader) readi64() (int64, error) {
@ -874,8 +874,7 @@ func (vr *valueReader) readi64() (int64, error) {
idx := vr.offset idx := vr.offset
vr.offset += 8 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 | return int64(binary.LittleEndian.Uint64(vr.d[idx:])), nil
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
} }
func (vr *valueReader) readu64() (uint64, error) { func (vr *valueReader) readu64() (uint64, error) {
@ -885,6 +884,5 @@ func (vr *valueReader) readu64() (uint64, error) {
idx := vr.offset idx := vr.offset
vr.offset += 8 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 | return binary.LittleEndian.Uint64(vr.d[idx:]), nil
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
} }

View file

@ -598,7 +598,7 @@ func (vw *valueWriter) writeLength() error {
return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))} return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))}
} }
frame := &vw.stack[vw.frame] frame := &vw.stack[vw.frame]
length = length - int(frame.start) length -= int(frame.start)
start := frame.start start := frame.start
_ = vw.buf[start+3] // BCE _ = 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 // 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: // 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 // 1. omitempty: If the "omitempty" struct tag is specified on a field, the field will not be marshaled if it is set to
// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, // an "empty" value. Numbers, booleans, and strings are considered empty if their value is equal to the zero value for
// slice, map, or string. // the type (i.e. 0 for numbers, false for booleans, and "" for strings). Slices, maps, and arrays are considered
// NOTE: It is recommended that this tag be used for all slice and map fields. // 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 // 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 // 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. // Bits: 1*sign 2*ignored 14*exponent 111*significand.
// Implicit 0b100 prefix in significand. // Implicit 0b100 prefix in significand.
exp = int(d.h >> 47 & (1<<14 - 1)) 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. // Spec says all of these values are out of range.
high, low = 0, 0 high, low = 0, 0
} else { } else {
@ -152,13 +151,12 @@ func (d Decimal128) BigInt() (*big.Int, int, error) {
// Bits: 1*sign 2*ignored 14*exponent 111*significand. // Bits: 1*sign 2*ignored 14*exponent 111*significand.
// Implicit 0b100 prefix in significand. // Implicit 0b100 prefix in significand.
exp = int(high >> 47 & (1<<14 - 1)) 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. // Spec says all of these values are out of range.
high, low = 0, 0 high, low = 0, 0
} else { } else {
// Bits: 1*sign 14*exponent 113*significand // Bits: 1*sign 14*exponent 113*significand
exp = int(high >> 49 & (1<<14 - 1)) exp = int(high >> 49 & (1<<14 - 1))
high = high & (1<<49 - 1) high &= (1<<49 - 1)
} }
exp += MinDecimal128Exp exp += MinDecimal128Exp
@ -352,7 +350,7 @@ var (
// ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value. // ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value.
func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) { func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) {
//copy // copy
bi = new(big.Int).Set(bi) bi = new(big.Int).Set(bi)
q := new(big.Int) 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) return dec.DecodeValue(bsoncodec.DecodeContext{Registry: r}, vr, rval)
} }
// UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses the provided DecodeContext // UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses
// instead of the one attached or the default registry. // 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 { func (rv RawValue) UnmarshalWithContext(dc *bsoncodec.DecodeContext, val interface{}) error {
if dc == nil { if dc == nil {
return ErrNilContext return ErrNilContext

View file

@ -10,15 +10,27 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
) )
// DefaultRegistry is the default bsoncodec.Registry. It contains the default codecs and the // DefaultRegistry is the default bsoncodec.Registry. It contains the default
// primitive codecs. // 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() var DefaultRegistry = NewRegistry()
// NewRegistryBuilder creates a new RegistryBuilder configured with the default encoders and // NewRegistryBuilder creates a new RegistryBuilder configured with the default encoders and
// decoders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the // decoders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the
// PrimitiveCodecs type in this package. // PrimitiveCodecs type in this package.
// //
// Deprecated: Use NewRegistry instead. // Deprecated: Use [NewRegistry] instead.
func NewRegistryBuilder() *bsoncodec.RegistryBuilder { func NewRegistryBuilder() *bsoncodec.RegistryBuilder {
rb := bsoncodec.NewRegistryBuilder() rb := bsoncodec.NewRegistryBuilder()
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) 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 // 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 // pointed to by val. If val is nil or not a pointer, Unmarshal returns
// InvalidUnmarshalError. // 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 { func Unmarshal(data []byte, val interface{}) error {
return UnmarshalWithRegistry(DefaultRegistry, data, val) return UnmarshalWithRegistry(DefaultRegistry, data, val)
} }

View file

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

View file

@ -4,10 +4,18 @@
// not use this file except in compliance with the License. You may obtain // 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 // 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 // Package bsoncore is intended for internal use only. It is made available to
// elements and values to or from a slice of bytes. These functions are aimed at // facilitate use cases that require access to internal MongoDB driver
// allowing low level manipulation of BSON and can be used to build a higher // functionality and state. The API of this package is not stable and there is
// level BSON library. // 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 // 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 // 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 // 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 // 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 // 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 // number of bytes available, it will return false, if there are enough bytes,
// will return those bytes and true. It is the consumers responsibility to // it will return those bytes and true. It is the consumers responsibility to
// validate those bytes. // validate those bytes.
// //
// The Append* functions within this package will append the type value to the // 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 // 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 // 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. // 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 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 // KeyBytesErr returns the key for this element as a []byte, returning an error if the element is
// not valid. // not valid.
func (e Element) KeyBytesErr() ([]byte, error) { func (e Element) KeyBytesErr() ([]byte, error) {
if len(e) <= 0 { if len(e) == 0 {
return nil, ErrElementMissingType return nil, ErrElementMissingType
} }
idx := bytes.IndexByte(e[1:], 0x00) 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. // ValueErr returns the value for this element, returning an error if the element is not valid.
func (e Element) ValueErr() (Value, error) { func (e Element) ValueErr() (Value, error) {
if len(e) <= 0 { if len(e) == 0 {
return Value{}, ErrElementMissingType return Value{}, ErrElementMissingType
} }
idx := bytes.IndexByte(e[1:], 0x00) 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. // String implements the fmt.String interface. The output will be in extended JSON format.
func (e Element) String() string { func (e Element) String() string {
if len(e) <= 0 { if len(e) == 0 {
return "" return ""
} }
t := bsontype.Type(e[0]) 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 // 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. // valid components of the element even if the entire element is not valid.
func (e Element) DebugString() string { func (e Element) DebugString() string {
if len(e) <= 0 { if len(e) == 0 {
return "<malformed>" return "<malformed>"
} }
t := bsontype.Type(e[0]) t := bsontype.Type(e[0])

View file

@ -924,13 +924,14 @@ func escapeString(s string) string {
func formatDouble(f float64) string { func formatDouble(f float64) string {
var s string var s string
if math.IsInf(f, 1) { switch {
case math.IsInf(f, 1):
s = "Infinity" s = "Infinity"
} else if math.IsInf(f, -1) { case math.IsInf(f, -1):
s = "-Infinity" s = "-Infinity"
} else if math.IsNaN(f) { case math.IsNaN(f):
s = "NaN" s = "NaN"
} else { default:
// Print exactly one decimalType place for integers; otherwise, print as many are necessary to // Print exactly one decimalType place for integers; otherwise, print as many are necessary to
// perfectly represent it. // perfectly represent it.
s = strconv.FormatFloat(f, 'G', -1, 64) 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) { func (ss sortableString) Swap(i, j int) {
oldI := ss[i] ss[i], ss[j] = ss[j], ss[i]
ss[i] = ss[j]
ss[j] = oldI
} }
func sortStringAlphebeticAscending(s string) string { 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: case Imm:
if s, base := symname(uint64(x)); s != "" { if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
suffix := "" if s, base := symname(uint64(x)); s != "" {
if uint64(x) != base { suffix := ""
suffix = fmt.Sprintf("%+d", uint64(x)-base) 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 { if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(x)) 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 { func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string {
switch a := arg.(type) { switch a := arg.(type) {
case Imm: case Imm:
if s, base := symname(uint64(a)); s != "" { if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
suffix := "" if s, base := symname(uint64(a)); s != "" {
if uint64(a) != base { suffix := ""
suffix = fmt.Sprintf("%+d", uint64(a)-base) 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 { if inst.Mode == 32 {
return fmt.Sprintf("%#x", uint32(a)) 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) return fmt.Sprintf("%#x", addr)
case Imm: case Imm:
if s, base := symname(uint64(a)); s != "" { if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 {
suffix := "" // Only try to convert an immediate to a symbol in certain
if uint64(a) != base { // special circumstances. See issue 72942.
suffix = fmt.Sprintf("%+d", uint64(a)-base) //
// 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 { if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(a)) return fmt.Sprintf("$%#x", uint32(a))

View file

@ -288,7 +288,7 @@ func (tf *tokenRefresher) Token() (*Token, error) {
if tf.refreshToken != tk.RefreshToken { if tf.refreshToken != tk.RefreshToken {
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 // 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 { if src == nil {
return internal.ContextClient(ctx) return internal.ContextClient(ctx)
} }
cc := internal.ContextClient(ctx)
return &http.Client{ return &http.Client{
Transport: &Transport{ Transport: &Transport{
Base: internal.ContextClient(ctx).Transport, Base: cc.Transport,
Source: ReuseTokenSource(nil, src), 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. // 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 // 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) { 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()) tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get())
if err != nil { 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 # github.com/gin-contrib/gzip v1.2.3
## explicit; go 1.23.0 ## explicit; go 1.23.0
github.com/gin-contrib/gzip github.com/gin-contrib/gzip
# github.com/gin-contrib/sessions v1.0.2 # github.com/gin-contrib/sessions v1.0.3
## explicit; go 1.20 ## explicit; go 1.23.0
github.com/gin-contrib/sessions github.com/gin-contrib/sessions
github.com/gin-contrib/sessions/memstore github.com/gin-contrib/sessions/memstore
# github.com/gin-contrib/sse v1.0.0 # github.com/gin-contrib/sse v1.0.0
@ -580,8 +580,8 @@ github.com/gorilla/handlers
# github.com/gorilla/securecookie v1.1.2 # github.com/gorilla/securecookie v1.1.2
## explicit; go 1.20 ## explicit; go 1.20
github.com/gorilla/securecookie github.com/gorilla/securecookie
# github.com/gorilla/sessions v1.2.2 # github.com/gorilla/sessions v1.4.0
## explicit; go 1.20 ## explicit; go 1.23
github.com/gorilla/sessions github.com/gorilla/sessions
# github.com/gorilla/websocket v1.5.3 # github.com/gorilla/websocket v1.5.3
## explicit; go 1.12 ## explicit; go 1.12
@ -833,11 +833,11 @@ github.com/stretchr/testify/suite
# github.com/subosito/gotenv v1.6.0 # github.com/subosito/gotenv v1.6.0
## explicit; go 1.18 ## explicit; go 1.18
github.com/subosito/gotenv 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 ## explicit; go 1.18.0
github.com/tdewolff/minify/v2 github.com/tdewolff/minify/v2
github.com/tdewolff/minify/v2/html 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 ## explicit; go 1.13
github.com/tdewolff/parse/v2 github.com/tdewolff/parse/v2
github.com/tdewolff/parse/v2/buffer 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 # github.com/wagslane/go-password-validator v0.3.0
## explicit; go 1.16 ## explicit; go 1.16
github.com/wagslane/go-password-validator github.com/wagslane/go-password-validator
# github.com/yuin/goldmark v1.7.8 # github.com/yuin/goldmark v1.7.10
## explicit; go 1.19 ## explicit; go 1.22
github.com/yuin/goldmark github.com/yuin/goldmark
github.com/yuin/goldmark/ast github.com/yuin/goldmark/ast
github.com/yuin/goldmark/extension github.com/yuin/goldmark/extension
@ -971,7 +971,7 @@ github.com/yuin/goldmark/renderer
github.com/yuin/goldmark/renderer/html github.com/yuin/goldmark/renderer/html
github.com/yuin/goldmark/text github.com/yuin/goldmark/text
github.com/yuin/goldmark/util 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 ## explicit; go 1.18
go.mongodb.org/mongo-driver/bson go.mongodb.org/mongo-driver/bson
go.mongodb.org/mongo-driver/bson/bsoncodec go.mongodb.org/mongo-driver/bson/bsoncodec
@ -1066,7 +1066,7 @@ go.uber.org/automaxprocs/maxprocs
# go.uber.org/multierr v1.11.0 # go.uber.org/multierr v1.11.0
## explicit; go 1.19 ## explicit; go 1.19
go.uber.org/multierr go.uber.org/multierr
# golang.org/x/arch v0.15.0 # golang.org/x/arch v0.16.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/arch/x86/x86asm golang.org/x/arch/x86/x86asm
# golang.org/x/crypto v0.37.0 # 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/ipv6
golang.org/x/net/publicsuffix golang.org/x/net/publicsuffix
golang.org/x/net/trace golang.org/x/net/trace
# golang.org/x/oauth2 v0.27.0 # golang.org/x/oauth2 v0.29.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/internal golang.org/x/oauth2/internal

View file

@ -17,6 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. 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 Photoswipe = require("photoswipe/dist/umd/photoswipe.umd.min.js");
const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js"); const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js");
const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default; const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default;
@ -165,89 +174,6 @@ lightbox.on('uiRegister', function() {
lightbox.init(); 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) => { Array.from(document.getElementsByClassName("plyr-video")).forEach((video) => {
const loopingAuto = !reduceMotion.matches && video.classList.contains("gifv"); const loopingAuto = !reduceMotion.matches && video.classList.contains("gifv");
let player = new Plyr(video, { let player = new Plyr(video, {
@ -315,30 +241,6 @@ function inLightbox(element) {
lightbox.pswp.currSlide.data.attachmentId; 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 // When clicking anywhere that's not an open
// stats-info-more-content details dropdown, // stats-info-more-content details dropdown,
// close that open dropdown. // close that open dropdown.

View file

@ -17,8 +17,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. 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"; import { decode } from "blurhash";
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
// Generate a blurhash canvas for each image for // Generate a blurhash canvas for each image for
// each blurhash container and put it in the summary. // each blurhash container and put it in the summary.
Array.from(document.getElementsByClassName('blurhash-container')).forEach(blurhashContainer => { 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: { frontend_prerender: {
entryFile: "blurhash", entryFile: "frontend_prerender",
outputFile: "blurhash.js", outputFile: "frontend_prerender.js",
preset: ["js"], preset: ["js"],
prodCfg: prodCfg, prodCfg: prodCfg,
transform: [ transform: [