mirror of
https://github.com/AlistGo/alist.git
synced 2025-04-23 05:44:04 +08:00
* feat(github): support GPG verification * chore
This commit is contained in:
parent
79bef0be9e
commit
cdc41595bc
@ -3,7 +3,6 @@ package github
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -12,12 +11,14 @@ import (
|
||||
"sync"
|
||||
"text/template"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/errs"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -33,6 +34,7 @@ type Github struct {
|
||||
moveMsgTmpl *template.Template
|
||||
isOnBranch bool
|
||||
commitMutex sync.Mutex
|
||||
pgpEntity *openpgp.Entity
|
||||
}
|
||||
|
||||
func (d *Github) Config() driver.Config {
|
||||
@ -102,6 +104,26 @@ func (d *Github) Init(ctx context.Context) error {
|
||||
_, err = d.getBranchHead()
|
||||
d.isOnBranch = err == nil
|
||||
}
|
||||
if d.GPGPrivateKey != "" {
|
||||
if d.CommitterName == "" || d.AuthorName == "" {
|
||||
user, e := d.getAuthenticatedUser()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if d.CommitterName == "" {
|
||||
d.CommitterName = user.Name
|
||||
d.CommitterEmail = user.Email
|
||||
}
|
||||
if d.AuthorName == "" {
|
||||
d.AuthorName = user.Name
|
||||
d.AuthorEmail = user.Email
|
||||
}
|
||||
}
|
||||
d.pgpEntity, err = loadPrivateKey(d.GPGPrivateKey, d.GPGKeyPassphrase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -174,10 +196,39 @@ func (d *Github) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
||||
if parent.Entries == nil {
|
||||
return errs.NotFolder
|
||||
}
|
||||
// if parent folder contains .gitkeep only, mark it and delete .gitkeep later
|
||||
gitKeepSha := ""
|
||||
subDirSha, err := d.newTree("", []interface{}{
|
||||
map[string]string{
|
||||
"path": ".gitkeep",
|
||||
"mode": "100644",
|
||||
"type": "blob",
|
||||
"content": "",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newTree := make([]interface{}, 0, 2)
|
||||
newTree = append(newTree, TreeObjReq{
|
||||
Path: dirName,
|
||||
Mode: "040000",
|
||||
Type: "tree",
|
||||
Sha: subDirSha,
|
||||
})
|
||||
if len(parent.Entries) == 1 && parent.Entries[0].Name == ".gitkeep" {
|
||||
gitKeepSha = parent.Entries[0].Sha
|
||||
newTree = append(newTree, TreeObjReq{
|
||||
Path: ".gitkeep",
|
||||
Mode: "100644",
|
||||
Type: "blob",
|
||||
Sha: nil,
|
||||
})
|
||||
}
|
||||
newSha, err := d.newTree(parent.Sha, newTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootSha, err := d.renewParentTrees(parentDir.GetPath(), parent.Sha, newSha, "/")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commitMessage, err := getMessage(d.mkdirMsgTmpl, &MessageTemplateVars{
|
||||
@ -190,13 +241,7 @@ func (d *Github) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = d.createGitKeep(stdpath.Join(parentDir.GetPath(), dirName), commitMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
if gitKeepSha != "" {
|
||||
err = d.delete(stdpath.Join(parentDir.GetPath(), ".gitkeep"), gitKeepSha, commitMessage)
|
||||
}
|
||||
return err
|
||||
return d.commit(commitMessage, rootSha)
|
||||
}
|
||||
|
||||
func (d *Github) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
@ -639,24 +684,6 @@ func (d *Github) get(path string) (*Object, error) {
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (d *Github) createGitKeep(path, message string) error {
|
||||
body := map[string]interface{}{
|
||||
"message": message,
|
||||
"content": "",
|
||||
"branch": d.Ref,
|
||||
}
|
||||
d.addCommitterAndAuthor(&body)
|
||||
|
||||
res, err := d.client.R().SetBody(body).Put(d.getContentApiUrl(stdpath.Join(path, ".gitkeep")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode() != 200 && res.StatusCode() != 201 {
|
||||
return toErr(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Github) putBlob(ctx context.Context, s model.FileStreamer, up driver.UpdateProgress) (string, error) {
|
||||
beforeContent := "{\"encoding\":\"base64\",\"content\":\""
|
||||
afterContent := "\"}"
|
||||
@ -717,23 +744,6 @@ func (d *Github) putBlob(ctx context.Context, s model.FileStreamer, up driver.Up
|
||||
return resp.Sha, nil
|
||||
}
|
||||
|
||||
func (d *Github) delete(path, sha, message string) error {
|
||||
body := map[string]interface{}{
|
||||
"message": message,
|
||||
"sha": sha,
|
||||
"branch": d.Ref,
|
||||
}
|
||||
d.addCommitterAndAuthor(&body)
|
||||
res, err := d.client.R().SetBody(body).Delete(d.getContentApiUrl(path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode() != 200 {
|
||||
return toErr(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Github) renewParentTrees(path, prevSha, curSha, until string) (string, error) {
|
||||
for path != until {
|
||||
path = stdpath.Dir(path)
|
||||
@ -795,11 +805,11 @@ func (d *Github) getTreeDirectly(path string) (*TreeResp, string, error) {
|
||||
}
|
||||
|
||||
func (d *Github) newTree(baseSha string, tree []interface{}) (string, error) {
|
||||
res, err := d.client.R().
|
||||
SetBody(&TreeReq{
|
||||
BaseTree: baseSha,
|
||||
Trees: tree,
|
||||
}).
|
||||
body := &TreeReq{Trees: tree}
|
||||
if baseSha != "" {
|
||||
body.BaseTree = baseSha
|
||||
}
|
||||
res, err := d.client.R().SetBody(body).
|
||||
Post(fmt.Sprintf("https://api.github.com/repos/%s/%s/git/trees", d.Owner, d.Repo))
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -822,6 +832,13 @@ func (d *Github) commit(message, treeSha string) error {
|
||||
"parents": []string{oldCommit},
|
||||
}
|
||||
d.addCommitterAndAuthor(&body)
|
||||
if d.pgpEntity != nil {
|
||||
signature, e := signCommit(&body, d.pgpEntity)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
body["signature"] = signature
|
||||
}
|
||||
res, err := d.client.R().SetBody(body).Post(fmt.Sprintf("https://api.github.com/repos/%s/%s/git/commits", d.Owner, d.Repo))
|
||||
if err != nil {
|
||||
return err
|
||||
@ -925,6 +942,21 @@ func (d *Github) getRepo() (*RepoResp, error) {
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (d *Github) getAuthenticatedUser() (*UserResp, error) {
|
||||
res, err := d.client.R().Get("https://api.github.com/user")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.StatusCode() != 200 {
|
||||
return nil, toErr(res)
|
||||
}
|
||||
resp := &UserResp{}
|
||||
if err = utils.Json.Unmarshal(res.Body(), resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (d *Github) addCommitterAndAuthor(m *map[string]interface{}) {
|
||||
if d.CommitterName != "" {
|
||||
committer := map[string]string{
|
||||
|
@ -7,21 +7,23 @@ import (
|
||||
|
||||
type Addition struct {
|
||||
driver.RootPath
|
||||
Token string `json:"token" type:"string"`
|
||||
Owner string `json:"owner" type:"string" required:"true"`
|
||||
Repo string `json:"repo" type:"string" required:"true"`
|
||||
Ref string `json:"ref" type:"string" help:"A branch, a tag or a commit SHA, main branch by default."`
|
||||
GitHubProxy string `json:"gh_proxy" type:"string" help:"GitHub proxy, e.g. https://ghproxy.net/raw.githubusercontent.com or https://gh-proxy.com/raw.githubusercontent.com"`
|
||||
CommitterName string `json:"committer_name" type:"string"`
|
||||
CommitterEmail string `json:"committer_email" type:"string"`
|
||||
AuthorName string `json:"author_name" type:"string"`
|
||||
AuthorEmail string `json:"author_email" type:"string"`
|
||||
MkdirCommitMsg string `json:"mkdir_commit_message" type:"text" default:"{{.UserName}} mkdir {{.ObjPath}}"`
|
||||
DeleteCommitMsg string `json:"delete_commit_message" type:"text" default:"{{.UserName}} remove {{.ObjPath}}"`
|
||||
PutCommitMsg string `json:"put_commit_message" type:"text" default:"{{.UserName}} upload {{.ObjPath}}"`
|
||||
RenameCommitMsg string `json:"rename_commit_message" type:"text" default:"{{.UserName}} rename {{.ObjPath}} to {{.TargetName}}"`
|
||||
CopyCommitMsg string `json:"copy_commit_message" type:"text" default:"{{.UserName}} copy {{.ObjPath}} to {{.TargetPath}}"`
|
||||
MoveCommitMsg string `json:"move_commit_message" type:"text" default:"{{.UserName}} move {{.ObjPath}} to {{.TargetPath}}"`
|
||||
Token string `json:"token" type:"string" required:"true"`
|
||||
Owner string `json:"owner" type:"string" required:"true"`
|
||||
Repo string `json:"repo" type:"string" required:"true"`
|
||||
Ref string `json:"ref" type:"string" help:"A branch, a tag or a commit SHA, main branch by default."`
|
||||
GitHubProxy string `json:"gh_proxy" type:"string" help:"GitHub proxy, e.g. https://ghproxy.net/raw.githubusercontent.com or https://gh-proxy.com/raw.githubusercontent.com"`
|
||||
GPGPrivateKey string `json:"gpg_private_key" type:"text"`
|
||||
GPGKeyPassphrase string `json:"gpg_key_passphrase" type:"string"`
|
||||
CommitterName string `json:"committer_name" type:"string"`
|
||||
CommitterEmail string `json:"committer_email" type:"string"`
|
||||
AuthorName string `json:"author_name" type:"string"`
|
||||
AuthorEmail string `json:"author_email" type:"string"`
|
||||
MkdirCommitMsg string `json:"mkdir_commit_message" type:"text" default:"{{.UserName}} mkdir {{.ObjPath}}"`
|
||||
DeleteCommitMsg string `json:"delete_commit_message" type:"text" default:"{{.UserName}} remove {{.ObjPath}}"`
|
||||
PutCommitMsg string `json:"put_commit_message" type:"text" default:"{{.UserName}} upload {{.ObjPath}}"`
|
||||
RenameCommitMsg string `json:"rename_commit_message" type:"text" default:"{{.UserName}} rename {{.ObjPath}} to {{.TargetName}}"`
|
||||
CopyCommitMsg string `json:"copy_commit_message" type:"text" default:"{{.UserName}} copy {{.ObjPath}} to {{.TargetPath}}"`
|
||||
MoveCommitMsg string `json:"move_commit_message" type:"text" default:"{{.UserName}} move {{.ObjPath}} to {{.TargetPath}}"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
|
@ -79,7 +79,7 @@ type TreeResp struct {
|
||||
}
|
||||
|
||||
type TreeReq struct {
|
||||
BaseTree string `json:"base_tree"`
|
||||
BaseTree interface{} `json:"base_tree,omitempty"`
|
||||
Trees []interface{} `json:"tree"`
|
||||
}
|
||||
|
||||
@ -100,3 +100,8 @@ type UpdateRefReq struct {
|
||||
type RepoResp struct {
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
}
|
||||
|
||||
type UserResp struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
@ -1,14 +1,20 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type MessageTemplateVars struct {
|
||||
@ -97,3 +103,65 @@ func getUsername(ctx context.Context) string {
|
||||
}
|
||||
return user.Username
|
||||
}
|
||||
|
||||
func loadPrivateKey(key, passphrase string) (*openpgp.Entity, error) {
|
||||
entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(entityList) < 1 {
|
||||
return nil, fmt.Errorf("no keys found in key ring")
|
||||
}
|
||||
entity := entityList[0]
|
||||
|
||||
pass := []byte(passphrase)
|
||||
if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
|
||||
if err = entity.PrivateKey.Decrypt(pass); err != nil {
|
||||
return nil, fmt.Errorf("password incorrect: %+v", err)
|
||||
}
|
||||
}
|
||||
for _, subKey := range entity.Subkeys {
|
||||
if subKey.PrivateKey != nil && subKey.PrivateKey.Encrypted {
|
||||
if err = subKey.PrivateKey.Decrypt(pass); err != nil {
|
||||
return nil, fmt.Errorf("password incorrect: %+v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func signCommit(m *map[string]interface{}, entity *openpgp.Entity) (string, error) {
|
||||
var commit strings.Builder
|
||||
commit.WriteString(fmt.Sprintf("tree %s\n", (*m)["tree"].(string)))
|
||||
parents := (*m)["parents"].([]string)
|
||||
for _, p := range parents {
|
||||
commit.WriteString(fmt.Sprintf("parent %s\n", p))
|
||||
}
|
||||
now := time.Now()
|
||||
_, offset := now.Zone()
|
||||
hour := offset / 3600
|
||||
author := (*m)["author"].(map[string]string)
|
||||
commit.WriteString(fmt.Sprintf("author %s <%s> %d %+03d00\n", author["name"], author["email"], now.Unix(), hour))
|
||||
author["date"] = now.Format(time.RFC3339)
|
||||
committer := (*m)["committer"].(map[string]string)
|
||||
commit.WriteString(fmt.Sprintf("committer %s <%s> %d %+03d00\n", committer["name"], committer["email"], now.Unix(), hour))
|
||||
committer["date"] = now.Format(time.RFC3339)
|
||||
commit.WriteString(fmt.Sprintf("\n%s", (*m)["message"].(string)))
|
||||
data := commit.String()
|
||||
|
||||
var sigBuffer bytes.Buffer
|
||||
err := openpgp.DetachSign(&sigBuffer, entity, strings.NewReader(data), nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("signing failed: %v", err)
|
||||
}
|
||||
var armoredSig bytes.Buffer
|
||||
armorWriter, err := armor.Encode(&armoredSig, "PGP SIGNATURE", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err = io.Copy(armorWriter, &sigBuffer); err != nil {
|
||||
return "", err
|
||||
}
|
||||
_ = armorWriter.Close()
|
||||
return armoredSig.String(), nil
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -7,6 +7,7 @@ toolchain go1.23.1
|
||||
require (
|
||||
github.com/KirCute/ftpserverlib-pasvportmap v1.25.0
|
||||
github.com/KirCute/sftpd-alist v0.0.12
|
||||
github.com/ProtonMail/go-crypto v1.0.0
|
||||
github.com/SheltonZhu/115driver v1.0.34
|
||||
github.com/Xhofe/go-cache v0.0.0-20240804043513-b1a71927bc21
|
||||
github.com/Xhofe/rateg v0.0.0-20230728072201-251a4e1adad4
|
||||
@ -90,6 +91,7 @@ require (
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||
|
15
go.sum
15
go.sum
@ -28,6 +28,8 @@ github.com/KirCute/sftpd-alist v0.0.12 h1:GNVM5QLbQLAfXP4wGUlXFA2IO6fVek0n0IsGnO
|
||||
github.com/KirCute/sftpd-alist v0.0.12/go.mod h1:2wNK7yyW2XfjyJq10OY6xB4COLac64hOwfV6clDJn6s=
|
||||
github.com/Max-Sum/base32768 v0.0.0-20230304063302-18e6ce5945fd h1:nzE1YQBdx1bq9IlZinHa+HVffy+NmVRoKr+wHN8fpLE=
|
||||
github.com/Max-Sum/base32768 v0.0.0-20230304063302-18e6ce5945fd/go.mod h1:C8yoIfvESpM3GD07OCHU7fqI7lhwyZ2Td1rbNbTAhnc=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM=
|
||||
github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
|
||||
@ -118,6 +120,7 @@ github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
|
||||
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@ -147,6 +150,9 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
||||
github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e h1:GLC8iDDcbt1H8+RkNao2nRGjyNTIo81e1rAJT9/uWYA=
|
||||
github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e/go.mod h1:ln9Whp+wVY/FTbn2SK0ag+SKD2fC0yQCF/Lqowc1LmU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
@ -643,6 +649,8 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
@ -706,8 +714,10 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
@ -764,6 +774,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -779,7 +791,9 @@ golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXct
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
@ -797,6 +811,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
|
Loading…
x
Reference in New Issue
Block a user