aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--integrations/api_packages_pypi_test.go6
-rw-r--r--routers/api/packages/pypi/pypi.go12
-rw-r--r--routers/api/packages/pypi/pypi_test.go39
3 files changed, 50 insertions, 7 deletions
diff --git a/integrations/api_packages_pypi_test.go b/integrations/api_packages_pypi_test.go
index cbb4202073..a04ee127d8 100644
--- a/integrations/api_packages_pypi_test.go
+++ b/integrations/api_packages_pypi_test.go
@@ -28,7 +28,7 @@ func TestPackagePyPI(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
packageName := "test-package"
- packageVersion := "1.0.1+r1234"
+ packageVersion := "1!1.0.1+r1234"
packageAuthor := "KN4CK3R"
packageDescription := "Test Description"
@@ -71,7 +71,7 @@ func TestPackagePyPI(t *testing.T) {
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err)
- assert.NotNil(t, pd.SemVer)
+ assert.Nil(t, pd.SemVer)
assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
assert.Equal(t, packageName, pd.Package.Name)
assert.Equal(t, packageVersion, pd.Version.Version)
@@ -99,7 +99,7 @@ func TestPackagePyPI(t *testing.T) {
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err)
- assert.NotNil(t, pd.SemVer)
+ assert.Nil(t, pd.SemVer)
assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
assert.Equal(t, packageName, pd.Package.Name)
assert.Equal(t, packageVersion, pd.Version.Version)
diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go
index 558ddd06f0..9fdba1172c 100644
--- a/routers/api/packages/pypi/pypi.go
+++ b/routers/api/packages/pypi/pypi.go
@@ -22,9 +22,9 @@ import (
packages_service "code.gitea.io/gitea/services/packages"
)
-// https://www.python.org/dev/peps/pep-0503/#normalized-names
+// https://peps.python.org/pep-0426/#name
var normalizer = strings.NewReplacer(".", "-", "_", "-")
-var nameMatcher = regexp.MustCompile(`\A[a-zA-Z0-9\.\-_]+\z`)
+var nameMatcher = regexp.MustCompile(`\A(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\.\-_]*[a-zA-Z0-9])\z`)
// https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
var versionMatcher = regexp.MustCompile(`\Av?` +
@@ -130,7 +130,7 @@ func UploadPackageFile(ctx *context.Context) {
packageName := normalizer.Replace(ctx.Req.FormValue("name"))
packageVersion := ctx.Req.FormValue("version")
- if !nameMatcher.MatchString(packageName) || !versionMatcher.MatchString(packageVersion) {
+ if !isValidNameAndVersion(packageName, packageVersion) {
apiError(ctx, http.StatusBadRequest, "invalid name or version")
return
}
@@ -148,7 +148,7 @@ func UploadPackageFile(ctx *context.Context) {
Name: packageName,
Version: packageVersion,
},
- SemverCompatible: true,
+ SemverCompatible: false,
Creator: ctx.Doer,
Metadata: &pypi_module.Metadata{
Author: ctx.Req.FormValue("author"),
@@ -179,3 +179,7 @@ func UploadPackageFile(ctx *context.Context) {
ctx.Status(http.StatusCreated)
}
+
+func isValidNameAndVersion(packageName, packageVersion string) bool {
+ return nameMatcher.MatchString(packageName) && versionMatcher.MatchString(packageVersion)
+}
diff --git a/routers/api/packages/pypi/pypi_test.go b/routers/api/packages/pypi/pypi_test.go
new file mode 100644
index 0000000000..56e327a347
--- /dev/null
+++ b/routers/api/packages/pypi/pypi_test.go
@@ -0,0 +1,39 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package pypi
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestIsValidNameAndVersion(t *testing.T) {
+ // The test cases below were created from the following Python PEPs:
+ // https://peps.python.org/pep-0426/#name
+ // https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
+
+ // Valid Cases
+ assert.True(t, isValidNameAndVersion("A", "1.0.1"))
+ assert.True(t, isValidNameAndVersion("Test.Name.1234", "1.0.1"))
+ assert.True(t, isValidNameAndVersion("test_name", "1.0.1"))
+ assert.True(t, isValidNameAndVersion("test-name", "1.0.1"))
+ assert.True(t, isValidNameAndVersion("test-name", "v1.0.1"))
+ assert.True(t, isValidNameAndVersion("test-name", "2012.4"))
+ assert.True(t, isValidNameAndVersion("test-name", "1.0.1-alpha"))
+ assert.True(t, isValidNameAndVersion("test-name", "1.0.1a1"))
+ assert.True(t, isValidNameAndVersion("test-name", "1.0b2.r345.dev456"))
+ assert.True(t, isValidNameAndVersion("test-name", "1!1.0.1"))
+ assert.True(t, isValidNameAndVersion("test-name", "1.0.1+local.1"))
+
+ // Invalid Cases
+ assert.False(t, isValidNameAndVersion(".test-name", "1.0.1"))
+ assert.False(t, isValidNameAndVersion("test!name", "1.0.1"))
+ assert.False(t, isValidNameAndVersion("-test-name", "1.0.1"))
+ assert.False(t, isValidNameAndVersion("test-name-", "1.0.1"))
+ assert.False(t, isValidNameAndVersion("test-name", "a1.0.1"))
+ assert.False(t, isValidNameAndVersion("test-name", "1.0.1aa"))
+ assert.False(t, isValidNameAndVersion("test-name", "1.0.0-alpha.beta"))
+}