Skip to content

Commit 5fb64f4

Browse files
committed
Fix percent encoding and pass original tests
1 parent 8fd00fe commit 5fb64f4

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

src/main/java/com/github/packageurl/PackageURL.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,11 @@ private String canonicalize(boolean coordinatesOnly) {
471471
}
472472
purl.append("/");
473473
if (namespace != null) {
474-
purl.append(encodePath(namespace));
474+
purl.append(encodePath(namespace, ":"));
475475
purl.append("/");
476476
}
477477
if (name != null) {
478-
purl.append(percentEncode(name));
478+
purl.append(percentEncode(name, ":"));
479479
}
480480
if (version != null) {
481481
purl.append("@").append(percentEncode(version));
@@ -486,36 +486,44 @@ private String canonicalize(boolean coordinatesOnly) {
486486
qualifiers.entrySet().stream().forEachOrdered(entry -> {
487487
purl.append(toLowerCase(entry.getKey()));
488488
purl.append("=");
489-
purl.append(percentEncode(entry.getValue()));
489+
purl.append(percentEncode(entry.getValue(), ":/"));
490490
purl.append("&");
491491
});
492492
purl.setLength(purl.length() - 1);
493493
}
494494
if (subpath != null) {
495-
purl.append("#").append(encodePath(subpath));
495+
purl.append("#").append(encodePath(subpath, "?#+&="));
496496
}
497497
}
498498
return purl.toString();
499499
}
500500

501+
private String percentEncode(final String input, final Charset charset, final String charsToExclude) {
502+
return uriEncode(input, charset, charsToExclude);
503+
}
504+
505+
private String percentEncode(final String input, final String charsToExclude) {
506+
return percentEncode(input, StandardCharsets.UTF_8, charsToExclude);
507+
}
508+
501509
/**
502510
* Encodes the input in conformance with RFC 3986.
503511
*
504512
* @param input the String to encode
505513
* @return an encoded String
506514
*/
507515
private String percentEncode(final String input) {
508-
return uriEncode(input, StandardCharsets.UTF_8);
516+
return percentEncode(input, StandardCharsets.UTF_8, null);
509517
}
510518

511-
private static String uriEncode(String source, Charset charset) {
512-
if (source == null || source.isEmpty()) {
519+
private static String uriEncode(String source, Charset charset, String chars) {
520+
if (source == null || source.length() == 0) {
513521
return source;
514522
}
515523

516524
StringBuilder builder = new StringBuilder();
517525
for (byte b : source.getBytes(charset)) {
518-
if (isUnreserved(b)) {
526+
if (isUnreserved(b) || chars != null && chars.indexOf(b) != -1) {
519527
builder.append((char) b);
520528
}
521529
else {

src/test/resources/test-suite-data.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@
8585
},
8686
{
8787
"description": "docker uses qualifiers and hash image id as versions",
88-
"purl": "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io",
89-
"canonical_purl": "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io",
88+
"purl": "pkg:docker/customer/dockerimage@sha256%3A244fd47e07d1004f0aed9c?repository_url=gcr.io",
89+
"canonical_purl": "pkg:docker/customer/dockerimage@sha256%3A244fd47e07d1004f0aed9c?repository_url=gcr.io",
9090
"type": "docker",
9191
"namespace": "customer",
9292
"name": "dockerimage",

0 commit comments

Comments
 (0)