Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
wxiaoguang committed Nov 7, 2024
1 parent e07ddcb commit 84ff353
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 97 deletions.
51 changes: 34 additions & 17 deletions modules/packages/arch/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"regexp"
"strconv"
"strings"
"sync"

"code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/util"
Expand All @@ -36,14 +37,32 @@ const (
RepositoryVersion = "_repository"
)

var (
reName = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$`)
reVer = regexp.MustCompile(`^[a-zA-Z0-9:_.+]+-+[0-9]+$`)
reOptDep = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?(:.*)?$`)
rePkgVer = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?$`)
type GlobalVarType struct {
reName *regexp.Regexp
reVer *regexp.Regexp
reOptDep *regexp.Regexp
rePkgVer *regexp.Regexp

maxMagicLength = 0
magics = map[string]struct {
maxMagicLength int
magics map[string]struct {
magic []byte
archiver func() archiver.Reader
}

ArchPkgOrSig *regexp.Regexp
ArchDBOrSig *regexp.Regexp
}

var GlobalVar = sync.OnceValue[*GlobalVarType](func() *GlobalVarType {
v := GlobalVarType{
reName: regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$`),
reVer: regexp.MustCompile(`^[a-zA-Z0-9:_.+]+-+[0-9]+$`),
reOptDep: regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?(:.*)?$`),
rePkgVer: regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?$`),
ArchPkgOrSig: regexp.MustCompile(`^.*\.pkg\.tar\.\w+(\.sig)*$`),
ArchDBOrSig: regexp.MustCompile(`^.*.db(\.tar\.gz)*(\.sig)*$`),
}
v.magics = map[string]struct {
magic []byte
archiver func() archiver.Reader
}{
Expand All @@ -66,15 +85,11 @@ var (
},
},
}
)

func init() {
for _, i := range magics {
if nLen := len(i.magic); nLen > maxMagicLength {
maxMagicLength = nLen
}
for _, i := range v.magics {
v.maxMagicLength = max(v.maxMagicLength, len(i.magic))
}
}
return &v
})

type Package struct {
Name string `json:"name"`
Expand Down Expand Up @@ -124,7 +139,7 @@ func ParsePackage(r *packages.HashedBuffer) (*Package, error) {
return nil, err
}

header := make([]byte, maxMagicLength)
header := make([]byte, GlobalVar().maxMagicLength)
_, err = r.Read(header)
if err != nil {
return nil, err
Expand All @@ -136,7 +151,7 @@ func ParsePackage(r *packages.HashedBuffer) (*Package, error) {

var tarball archiver.Reader
var tarballType string
for tarType, info := range magics {
for tarType, info := range GlobalVar().magics {
if bytes.Equal(header[:len(info.magic)], info.magic) {
tarballType = tarType
tarball = info.archiver()
Expand Down Expand Up @@ -272,6 +287,8 @@ func ParsePackageInfo(compressType string, r io.Reader) (*Package, error) {

// ValidatePackageSpec Arch package validation according to PKGBUILD specification.
func ValidatePackageSpec(p *Package) error {
gv := GlobalVar()
reName, reVer, reOptDep, rePkgVer := gv.reName, gv.reVer, gv.reOptDep, gv.rePkgVer
if !reName.MatchString(p.Name) {
return util.NewInvalidArgumentErrorf("invalid package name")
}
Expand Down
64 changes: 4 additions & 60 deletions routers/api/packages/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,66 +137,10 @@ func CommonRoutes() *web.Router {
})
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/arch", func() {
r.Group("/repository.key", func() {
r.Head("", arch.GetRepositoryKey)
r.Get("", arch.GetRepositoryKey)
})

r.Methods("HEAD,GET,PUT,DELETE", "*", func(ctx *context.Context) {
pathGroups := strings.Split(strings.Trim(ctx.PathParam("*"), "/"), "/")
groupLen := len(pathGroups)
isGetHead := ctx.Req.Method == "HEAD" || ctx.Req.Method == "GET"
isPut := ctx.Req.Method == "PUT"
isDelete := ctx.Req.Method == "DELETE"
if isGetHead {
if groupLen < 2 {
ctx.Status(http.StatusNotFound)
return
}
if groupLen == 2 {
ctx.SetPathParam("group", "")
ctx.SetPathParam("arch", pathGroups[0])
ctx.SetPathParam("file", pathGroups[1])
} else {
ctx.SetPathParam("group", strings.Join(pathGroups[:groupLen-2], "/"))
ctx.SetPathParam("arch", pathGroups[groupLen-2])
ctx.SetPathParam("file", pathGroups[groupLen-1])
}
arch.GetPackageOrDB(ctx)
return
} else if isPut {
ctx.SetPathParam("group", strings.Join(pathGroups, "/"))
reqPackageAccess(perm.AccessModeWrite)(ctx)
if ctx.Written() {
return
}
arch.PushPackage(ctx)
return
} else if isDelete {
if groupLen < 3 {
ctx.Status(http.StatusBadRequest)
return
}
if groupLen == 3 {
ctx.SetPathParam("group", "")
ctx.SetPathParam("package", pathGroups[0])
ctx.SetPathParam("version", pathGroups[1])
ctx.SetPathParam("arch", pathGroups[2])
} else {
ctx.SetPathParam("group", strings.Join(pathGroups[:groupLen-3], "/"))
ctx.SetPathParam("package", pathGroups[groupLen-3])
ctx.SetPathParam("version", pathGroups[groupLen-2])
ctx.SetPathParam("arch", pathGroups[groupLen-1])
}
reqPackageAccess(perm.AccessModeWrite)(ctx)
if ctx.Written() {
return
}
arch.RemovePackage(ctx)
return
}
ctx.Status(http.StatusNotFound)
})
r.Methods("HEAD,GET", "/repository.key", arch.GetRepositoryKey)
r.Methods("HEAD,GET", "*", arch.GetPackageOrDB)
r.Methods("PUT", "*", reqPackageAccess(perm.AccessModeWrite), arch.PushPackage)
r.Methods("DELETE", "*", reqPackageAccess(perm.AccessModeWrite), arch.RemovePackage)
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/cargo", func() {
r.Group("/api/v1/crates", func() {
Expand Down
45 changes: 25 additions & 20 deletions routers/api/packages/arch/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"io"
"net/http"
"path/filepath"
"regexp"
"strings"

packages_model "code.gitea.io/gitea/models/packages"
Expand All @@ -24,11 +23,6 @@ import (
arch_service "code.gitea.io/gitea/services/packages/arch"
)

var (
archPkgOrSig = regexp.MustCompile(`^.*\.pkg\.tar\.\w+(\.sig)*$`)
archDBOrSig = regexp.MustCompile(`^.*.db(\.tar\.gz)*(\.sig)*$`)
)

func apiError(ctx *context.Context, status int, obj any) {
helper.LogAndProcessError(ctx, status, obj, func(message string) {
ctx.PlainText(status, message)
Expand All @@ -53,7 +47,7 @@ func refreshLocker(ctx *context.Context, group string) (globallock.ReleaseFunc,
}

func PushPackage(ctx *context.Context) {
group := ctx.PathParam("group")
group := ctx.PathParam("*")
releaser, err := refreshLocker(ctx, group)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
Expand Down Expand Up @@ -175,13 +169,18 @@ func PushPackage(ctx *context.Context) {
}

func GetPackageOrDB(ctx *context.Context) {
var (
file = ctx.PathParam("file")
group = ctx.PathParam("group")
arch = ctx.PathParam("arch")
)
pathFields := strings.Split(strings.Trim(ctx.PathParam("*"), "/"), "/")
pathFieldsLen := len(pathFields)
if pathFieldsLen < 2 {
ctx.Status(http.StatusBadRequest)
return
}

group := strings.Join(pathFields[:pathFieldsLen-2], "/")
arch := pathFields[pathFieldsLen-2]
file := pathFields[pathFieldsLen-1]

if archPkgOrSig.MatchString(file) {
if arch_module.GlobalVar().ArchPkgOrSig.MatchString(file) {
pkg, u, pf, err := arch_service.GetPackageFile(ctx, group, file, ctx.Package.Owner.ID)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
Expand All @@ -195,7 +194,7 @@ func GetPackageOrDB(ctx *context.Context) {
return
}

if archDBOrSig.MatchString(file) {
if arch_module.GlobalVar().ArchDBOrSig.MatchString(file) {
pkg, u, pf, err := arch_service.GetPackageDBFile(ctx, group, arch, ctx.Package.Owner.ID,
strings.HasSuffix(file, ".sig"))
if err != nil {
Expand All @@ -215,12 +214,18 @@ func GetPackageOrDB(ctx *context.Context) {
}

func RemovePackage(ctx *context.Context) {
var (
group = ctx.PathParam("group")
pkg = ctx.PathParam("package")
ver = ctx.PathParam("version")
pkgArch = ctx.PathParam("arch")
)
pathFields := strings.Split(strings.Trim(ctx.PathParam("*"), "/"), "/")
pathFieldsLen := len(pathFields)
if pathFieldsLen < 3 {
ctx.Status(http.StatusBadRequest)
return
}

group := strings.Join(pathFields[:pathFieldsLen-3], "/")
pkg := pathFields[pathFieldsLen-3]
ver := pathFields[pathFieldsLen-2]
pkgArch := pathFields[pathFieldsLen-1]

releaser, err := refreshLocker(ctx, group)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
Expand Down

0 comments on commit 84ff353

Please sign in to comment.