Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 67 additions & 10 deletions src/main/java/com/github/packageurl/PackageURL.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public PackageURL(final String type, final String namespace, final String name,
this.type = toLowerCase(validateType(type));
this.namespace = validateNamespace(namespace);
this.name = validateName(name);
this.version = validateVersion(version);
this.version = validateVersion(type, version);
this.qualifiers = parseQualifiers(qualifiers);
this.subpath = validatePath(subpath, true);
verifyTypeConstraints(this.type, this.namespace, this.name);
Expand Down Expand Up @@ -307,13 +307,25 @@ private String validateNamespace(final String[] values) throws MalformedPackageU
final String tempNamespace = validatePath(values, false);
String retVal;
switch (type) {
case StandardTypes.APK:
case StandardTypes.BITBUCKET:
case StandardTypes.DEBIAN:
case StandardTypes.COMPOSER:
case StandardTypes.DEB:
case StandardTypes.GITHUB:
case StandardTypes.GOLANG:
case StandardTypes.HEX:
case StandardTypes.LUAROCKS:
case StandardTypes.QPKG:
case StandardTypes.RPM:
retVal = tempNamespace != null ? toLowerCase(tempNamespace) : null;
break;
case StandardTypes.MLFLOW:
case StandardTypes.OCI:
if (tempNamespace != null) {
throw new MalformedPackageURLException("The PackageURL specified contains a namespace which is not allowed for type: " + type);
}
retVal = null;
break;
default:
retVal = tempNamespace;
break;
Expand All @@ -327,12 +339,21 @@ private String validateName(final String value) throws MalformedPackageURLExcept
}
String temp;
switch (type) {
case StandardTypes.APK:
case StandardTypes.BITBUCKET:
case StandardTypes.DEBIAN:
case StandardTypes.BITNAMI:
case StandardTypes.COMPOSER:
case StandardTypes.DEB:
case StandardTypes.GITHUB:
case StandardTypes.GOLANG:
case StandardTypes.HEX:
case StandardTypes.LUAROCKS:
case StandardTypes.OCI:
temp = toLowerCase(value);
break;
case StandardTypes.PUB:
temp = toLowerCase(value).replaceAll("[^a-z0-9_]", "_");
break;
case StandardTypes.PYPI:
temp = toLowerCase(value).replace('_', '-');
break;
Expand All @@ -343,14 +364,26 @@ private String validateName(final String value) throws MalformedPackageURLExcept
return temp;
}

private String validateVersion(final String value) {
return value;
private String validateVersion(final String type, final String value) {
if (value == null) {
return null;
}

switch (type) {
case StandardTypes.HUGGINGFACE:
case StandardTypes.LUAROCKS:
case StandardTypes.OCI:
return toLowerCase(value);
default:
return value;
}
}

private Map<String, String> validateQualifiers(final Map<String, String> values) throws MalformedPackageURLException {
if (values == null || values.isEmpty()) {
return null;
}

for (Map.Entry<String, String> entry : values.entrySet()) {
validateKey(entry.getKey());
final String value = entry.getValue();
Expand Down Expand Up @@ -652,7 +685,7 @@ private void parse(final String purl) throws MalformedPackageURLException {
// version is optional - check for existence
index = remainder.lastIndexOf('@');
if (index >= start) {
this.version = validateVersion(percentDecode(remainder.substring(index + 1)));
this.version = validateVersion(this.type, percentDecode(remainder.substring(index + 1)));
remainder = remainder.substring(0, index);
}

Expand Down Expand Up @@ -820,24 +853,48 @@ public int hashCode() {
*
* @since 1.0.0
*/
public static class StandardTypes {
public static final class StandardTypes {
public static final String ALPM = "alpm";
public static final String APK = "apk";
public static final String BITBUCKET = "bitbucket";
public static final String BITNAMI = "bitnami";
public static final String CARGO = "cargo";
public static final String COCOAPODS = "cocoapods";
public static final String COMPOSER = "composer";
public static final String DEBIAN = "deb";
public static final String CONAN = "conan";
public static final String CONDA = "conda";
public static final String CPAN = "cpan";
public static final String CRAN = "cran";
public static final String DEB = "deb";
public static final String DOCKER = "docker";
public static final String GEM = "gem";
public static final String GENERIC = "generic";
public static final String GITHUB = "github";
public static final String GOLANG = "golang";
public static final String HACKAGE = "hackage";
public static final String HEX = "hex";
public static final String HUGGINGFACE = "huggingface";
public static final String LUAROCKS = "luarocks";
public static final String MAVEN = "maven";
public static final String MLFLOW = "mlflow";
public static final String NIX = "nix";
public static final String NPM = "npm";
public static final String NUGET = "nuget";
public static final String OCI = "oci";
public static final String PUB = "pub";
public static final String PYPI = "pypi";
public static final String QPKG = "qpkg";
public static final String RPM = "rpm";
public static final String NIXPKGS = "nixpkgs";
public static final String HACKAGE = "hackage";
public static final String SWID = "swid";
public static final String SWIFT = "swift";
@Deprecated
public static final String DEBIAN = "deb";
@Deprecated
public static final String NIXPKGS = "nix";

private StandardTypes() {

}
}

}
21 changes: 18 additions & 3 deletions src/test/java/com/github/packageurl/PackageURLTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,23 +322,38 @@ public void testConstructorWithEmptyKey() throws MalformedPackageURLException {

@Test
public void testStandardTypes() {
Assert.assertEquals("alpm", PackageURL.StandardTypes.ALPM);
Assert.assertEquals("apk", PackageURL.StandardTypes.APK);
Assert.assertEquals("bitbucket", PackageURL.StandardTypes.BITBUCKET);
Assert.assertEquals("bitnami", PackageURL.StandardTypes.BITNAMI);
Assert.assertEquals("cocoapods", PackageURL.StandardTypes.COCOAPODS);
Assert.assertEquals("cargo", PackageURL.StandardTypes.CARGO);
Assert.assertEquals("composer", PackageURL.StandardTypes.COMPOSER);
Assert.assertEquals("deb", PackageURL.StandardTypes.DEBIAN);
Assert.assertEquals("conan", PackageURL.StandardTypes.CONAN);
Assert.assertEquals("conda", PackageURL.StandardTypes.CONDA);
Assert.assertEquals("cpan", PackageURL.StandardTypes.CPAN);
Assert.assertEquals("cran", PackageURL.StandardTypes.CRAN);
Assert.assertEquals("deb", PackageURL.StandardTypes.DEB);
Assert.assertEquals("docker", PackageURL.StandardTypes.DOCKER);
Assert.assertEquals("gem", PackageURL.StandardTypes.GEM);
Assert.assertEquals("generic", PackageURL.StandardTypes.GENERIC);
Assert.assertEquals("github", PackageURL.StandardTypes.GITHUB);
Assert.assertEquals("golang", PackageURL.StandardTypes.GOLANG);
Assert.assertEquals("hackage", PackageURL.StandardTypes.HACKAGE);
Assert.assertEquals("hex", PackageURL.StandardTypes.HEX);
Assert.assertEquals("huggingface", PackageURL.StandardTypes.HUGGINGFACE);
Assert.assertEquals("luarocks", PackageURL.StandardTypes.LUAROCKS);
Assert.assertEquals("maven", PackageURL.StandardTypes.MAVEN);
Assert.assertEquals("mlflow", PackageURL.StandardTypes.MLFLOW);
Assert.assertEquals("npm", PackageURL.StandardTypes.NPM);
Assert.assertEquals("nuget", PackageURL.StandardTypes.NUGET);
Assert.assertEquals("qpkg", PackageURL.StandardTypes.QPKG);
Assert.assertEquals("oci", PackageURL.StandardTypes.OCI);
Assert.assertEquals("pub", PackageURL.StandardTypes.PUB);
Assert.assertEquals("pypi", PackageURL.StandardTypes.PYPI);
Assert.assertEquals("rpm", PackageURL.StandardTypes.RPM);
Assert.assertEquals("nixpkgs", PackageURL.StandardTypes.NIXPKGS);
Assert.assertEquals("hackage", PackageURL.StandardTypes.HACKAGE);
Assert.assertEquals("swid", PackageURL.StandardTypes.SWID);
Assert.assertEquals("swift", PackageURL.StandardTypes.SWIFT);
}

@Test
Expand Down