| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | AA | AB | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | component / category | order | issue/PR | nbr | URL | notes | current core spec rule(s)/language | questions | issue/PR comments/files | spec update status | comments re proposed spec update | URL value | |||||||||||||||||
2 | scheme | 1 | *NA | *NA | https://github.com/package-url/purl-spec/blob/master/test-suite-data.json#L242-L265 | JMH 2025-02-12: the scheme PR https://github.com/package-url/purl-spec/pull/361 has been merged. | "Rules for each purl component" / "scheme": - "Since a purl never contains a URL Authority, its scheme must not be suffixed with double slash as in 'pkg://' and should use instead 'pkg:'. Otherwise this would be an invalid URI per rfc3986 at https://tools.ietf.org/html/rfc3986#section-3.3: . . . It is therefore incorrect to use such '://' scheme suffix as the URL would no longer be valid otherwise. In its canonical form, a purl must NOT use such '://' scheme suffix but only ':' as a scheme suffix. - purl parsers must accept URLs such as 'pkg://' and must ignore the '//'." [The above spec section also says pkg://gem/ruby-advisory-db-check@0.12.4 "is an acceptable purl but is an invalid URI/URL per rfc3986:" The section below anticipates that the type might have a leading '/', in which case it must be stripped:] "How to parse a purl string in its components" - Split the remainder once from left on ':' - The left side lowercased is the scheme - The right side is the remainder - Strip the remainder from leading and trailing '/' - Split this once from left on '/' - The left side lowercased is the type - The right side is the remainder | Must 'pkg://[type]' and 'pkg:///[type]' - be rejected as invalid, or - treated as invalid but normalized by ignoring ["deleting"?] them, or - handled in some other manner? How about even more '/' following 'pkg:'? | We already have three tests for /, // and /// between scheme and type -- see https://github.com/package-url/purl-spec/blob/master/test-suite-data.json#L230-L265, e.g., "description": "double slash // after scheme is not significant", "purl": "pkg://maven/org.apache.commons/io", "canonical_purl": "pkg:maven/org.apache.commons/io", | JMH 2024-12-23: I've submitted several commits last week and today updating the scheme-related portions of the core spec: - added a new test "invalid encoded colon : between scheme and type" - updated the scheme-related portions of PURL-SPECIFICATION.rst to: - address questions raised by open issues/PRs - rewrite to convert "must not" language to the affirmative - make more concise - added an FAQ document (faq.rst) to more completely answer scheme-related questions raised in issues/PRs and otherwise clarify the language | If pkg:// is invalid but '//' is ignored ["deleted"?], - clarify that "ignored" means normalizing by deleting, and - clarify how to handle any number of '/' that immediately follow 'pkg:' BTW, does this also mean that a type must not start with 1+ '/'? I think it does, and perhaps we should state that clearly in the spec., including whether to reject as invalid or normalize by deleting. (The latter approach would be consistent with normalizing by ignoring ["deleting"?] a leading '/' (or multiple '/', I think, but we'll make this clear) from the 'pkg:' looking toward the type et al.) ===== 2024-12-05 13:07:44 Thursday. JMH to update to make clear that any number of slashes '/' between the scheme and the type must be normalized by removing, will provide specific updated language. | https://github.com/package-url/purl-spec/blob/master/test-suite-data.json#L242-L265 | |||||||||||||||||
3 | scheme | 1 | PR | 361 | https://github.com/package-url/purl-spec/pull/361 | 2024-12-24 JMH: The 'scheme' PR I updated yesterday (PR 361) was originally planned to also introduce our implementation of RFC 2119/8174. This plan was changed to use a stand-alone PR, which I created yesterday (PR 373) narrowly focused on introducing RFC 2119/8174 and changing the relevant terms to uppercase as needed. However, after seeing a number of good points raised by matt-phylum in his PR 373 comments, it's apparent that implementing RFC 2119/8174 needs to be done on a component-by-component basis. (See also the entry in this gSheet for the component/category "RFC 2119/8174".) JMH 2025-02-12: the scheme PR https://github.com/package-url/purl-spec/pull/361 has been merged. | "Rules for each purl component": . . . - scheme: . . . - The scheme is followed by a ':' separator - For example these two purls are strictly equivalent and the first is in canonical form. The second purl with a '//' is an acceptable purl but is an invalid URI/URL per rfc3986: pkg:gem/ruby-advisory-db-check@0.12.4 pkg://gem/ruby-advisory-db-check@0.12.4 . . . "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere - the ':' scheme and type separator does not need to and must NOT be encoded. It is unambiguous unencoded everywhere . . . | Must the colon ':' separator between scheme and type be percent-encoded? | JMH 2024-12-23: I've submitted several commits last week and today updating the scheme-related portions of the core spec: - added a new test "invalid encoded colon : between scheme and type" - updated the scheme-related portions of PURL-SPECIFICATION.rst to: - address questions raised by open issues/PRs - rewrite to convert "must not" language to the affirmative - make more concise - added an FAQ document (faq.rst) to more completely answer scheme-related questions raised in issues/PRs and otherwise clarify the language | https://github.com/package-url/purl-spec/pull/361 | |||||||||||||||||||
4 | scheme | 1 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's, pombredanne's and johnmhoran's comments re the 'scheme' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896762006 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896968169 - https://github.com/package-url/purl-spec/pull/373#discussion_r1897441665 JMH 2025-02-12: the scheme PR https://github.com/package-url/purl-spec/pull/361 has been merged. | matt-phylum's 2024-12-24 PR 373 comment ("A canonical PURL does not use pkg://, but PURLs MAY use pkg:, pkg:/, pkg://. . . .") -- already addressed in my 2024-12-23 push to PR 361. | https://github.com/package-url/purl-spec/pull/373 | |||||||||||||||||||||
5 | type | 2 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | 2024-12-24 JMH: see matt-phylum's detailed substantive comments in PR 373 (https://github.com/package-url/purl-spec/pull/373), some of which involve the 'type' component and need to be included in this upcoming updating PR. JMH 2025-02-19: the type PR https://github.com/package-url/purl-spec/pull/383 has been merged. | - "How to parse a purl string in its components" -- "Strip the remainder from leading and trailing '/'" | JMH. My current update thinking is to (1) change the next-to-last bullet in the following in the "Rules for each ``purl`` component" section: • type: • The package type is composed only of ASCII letters and numbers, '.', '+' and '-' (period, plus, and dash) • The type cannot start with a number • The type cannot contain spaces • The type must NOT be percent-encoded • The type is case insensitive. The canonical form is lowercase to "The type MUST be unencoded" (2) change the first line in the following in the "How to parse a purl string in its components" section: • Strip the remainder from leading and trailing '/' • Split this once from left on '/' • The left side lowercased is the type • The right side is the remainder to "Strip all leading and trailing '/' characters from the remainder" | https://github.com/package-url/purl-spec/issues/35 | ||||||||||||||||||||
6 | type | 2 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's comment re the 'type' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896778259 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896782759 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896818053 JMH 2025-02-19: the type PR https://github.com/package-url/purl-spec/pull/383 has been merged. | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
7 | namespace | 3 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | - namespace -- "Leading and trailing slashes '/' are not significant and should be stripped in the canonical form." - "How to build purl string from its components" -- "Strip the namespace from leading and trailing '/'" | - Does this apply to 1+ slashes? -- "How to build purl string from its components" -- "Strip the namespace from leading and trailing '/'" - Must single quote/apostrophe ''' be percent-encoded in namespace? | JMH: The example in this comment includes an apostrophe/single quote ''' in the namespace component: With character encoding, the Wikipedia article cites RFC 3986 in reference to the reserved and unreserved characters, I'm assuming that all reserved characters should be encoded (unless explicitly used as a purl delimiter) and none of the unreserved characters should be encoded. That is, when a reserved character has no special meaning to purl, it should still be encoded (e.g. the Maven GAV o'doyle:rules!:1.0 shoud be pkg:maven/o%27doyle/rules%21@1.0 and not pkg:maven/o'doyle/rules!@1.0). - also applies to '!' in name. | https://github.com/package-url/purl-spec/issues/35 | ||||||||||||||||||||
8 | namespace | 3 | Issue | 204 | https://github.com/package-url/purl-spec/issues/204 | Title: "Drop the notion of namespace from PackageURL" One comment suggests that '/' in a namespace should be percent-encoded. JMH: the core spec is clear -- see the "current core spec rule(s)/language" column. | "Rules for each purl component": . . . - namespace: . . . - Each namespace segment must be a percent-encoded string - When percent-decoded, a segment: - must not contain a '/' . . . "Character encoding": . . . - the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere . . . | The author proposes that namespace be removed as a component and combined with the name component No encoding-related issues are raised by the author, but a comment suggests the ':' in a namespace with multiple segments should be percent-encoded. | This issue does not involve a need to update or clarify the core spec re any encoding issues or lack of clarity. | https://github.com/package-url/purl-spec/issues/204 | |||||||||||||||||||
9 | namespace | 3 | PR | 176 | https://github.com/package-url/purl-spec/pull/176 | See the "questions" and "issue/PR comments/files" columns for the range of questions posed in this PR. | "Rules for each purl component": . . . - namespace: - The optional namespace contains zero or more segments, separated by slash '/' - Leading and trailing slashes '/' are not significant and should be stripped in the canonical form. They are not part of the namespace - Each namespace segment must be a percent-encoded string - When percent-decoded, a segment: - must not contain a '/' . . . . "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere . . . . | Must '/' in a namespace be percent-encoded? ===== Plus from comments: - does golang even have a namespace? swift? - do they have name components that include '/' and thus must be encoded? - must the core spec and type be updated to accommodate these golang and evidently swift characteristics? - is pkg:golang/github.com%2Fquic-go%2Fquic-go@0.40.0 a valid PURL with no namespace? Is it not equivalent to pkg:golang/github.com/quic-go/quic-go@0.40.0? | The author maxhbr writes "I think it is not clear from the text in the README and the examples whether a / in the namespace needs to be escaped." The core spec language seems clear on this -- '/' as a separator in a namespace must not be encoded, a namespace segment must be encoded, and a decoded namespace segment must not contain a '/'. However, matt-phylum and sschuberth agree that "pkg:golang/github.com%2Fquic-go%2Fquic-go@0.40.0 is a valid PURL with no namespace. It is not equivalent to pkg:golang/github.com/quic-go/quic-go@0.40.0." Commenters also raise numerous other issues including whether golang even has a namespace concept. | The core spec -- particularly the "Character encoding" section -- is clear as currently written: - the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere . . . . ===== Given the extensive comments about namespaces in golang and the question of whether golang and swift even have a 'namespace' concept (see sschuberth's comment at https://github.com/package-url/purl-spec/pull/176#issuecomment-2429913910), PR 176 itself needs some expert attention to (1) vet whether the proposed pkg:golang/github.com/gorilla/context@234fd47e07d1004f0aed9c (for the core spec) and pkg:swift/github.com/Alamofire/Alamofire@5.4.3 (for the README) are valid golang and swift PURLs, and (2) suggest to the commenters that their non-encoding-related issues need to be raised in separate new issues or PRs. | https://github.com/package-url/purl-spec/pull/176 | ||||||||||||||||||
10 | namespace | 3 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's and pombredanne's comments re the 'namespace' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896747698 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896914775 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896946780 | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
11 | namespace | 3 | PR | 52 to 367 | https://github.com/package-url/purl-spec/pull/367 | 2024-12-10 JMH: - "test: ensure namespace allows multiple segments #367" - tagged "PURL namespace component" and "Ecma specification". - PR 52 closed and converted into ##364, 365, 366, 367 and 368. JMH: this PR was merged on 2025-02-05. | "Rules for each purl component": . . . - namespace: - The optional namespace contains zero or more segments, separated by slash '/' - Leading and trailing slashes '/' are not significant and should be stripped in the canonical form. They are not part of the namespace - Each namespace segment must be a percent-encoded string - When percent-decoded, a segment: - must not contain a '/' . . . . "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere . . . . | Is a namespace with multiple segments valid? | Proposed test: { "description": "ensure namespace allows multiple segments", "purl": "pkg:bintray/apache/couchdb/couchdb-mac@2.3.0", "canonical_purl": "pkg:bintray/apache/couchdb/couchdb-mac@2.3.0", "type": "bintray", "namespace": "apache/couchdb", "name": "couchdb-mac", "version": "2.3.0", "qualifiers": null, "subpath": null, "is_invalid": false } | The core spec is clear: a namespace with multiple segments is valid. No change is needed to the core spec, but the proposed test is a great idea. | https://github.com/package-url/purl-spec/pull/367 | ||||||||||||||||||
12 | name | 4 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | Issue 35 raises a few name-focused questions (among the many questions and components it touches). In addition, I see that the master branch test-suite-data.json has a number of tests that are invalid but defined as "is_invalid": false, including lines 566-577 (unencoded '::' in name): { "description": "cpan module name are case sensitive", "purl": "pkg:cpan/URI::PackageURL@2.11", "canonical_purl": "pkg:cpan/URI::PackageURL@2.11", "type": "cpan", "namespace": null, "name": "URI::PackageURL", "version": "2.11", "qualifiers": null, "subpath": null, "is_invalid": false }, | "Rules for each purl component": . . . name: . . . A name must be a percent-encoded string - "How to build purl string from its components" -- "Strip the name from leading and trailing '/'" | Must ':' in a name be percent-encoded? - Does this apply to 1+ slashes? -- "How to build purl string from its components" -- "Strip the name from leading and trailing '/'" Must space ' ' in a name be percent-encoded? Must '!' in a name be percent-encoded? | JMH: The example in this comment includes an apostrophe/single quote ''' in the namespace component and '!' in name: With character encoding, the Wikipedia article cites RFC 3986 in reference to the reserved and unreserved characters, I'm assuming that all reserved characters should be encoded (unless explicitly used as a purl delimiter) and none of the unreserved characters should be encoded. That is, when a reserved character has no special meaning to purl, it should still be encoded (e.g. the Maven GAV o'doyle:rules!:1.0 shoud be pkg:maven/o%27doyle/rules%21@1.0 and not pkg:maven/o'doyle/rules!@1.0). - also applies to apostrophe/single quote ''' in namespace. | https://github.com/package-url/purl-spec/issues/35 | |||||||||||||||||||
13 | name | 4 | PR | 317 | https://github.com/package-url/purl-spec/pull/317 | 2025-01-27 JMH: Given pombredanne's 2025-01-27 comment re lowercasing the canonical PURL for the proposed 'bazel' type, we may want to consider updating the 'Rules for each purl component' section of PURL-SPECIFICATION.rst to clarify the casing of the canonical 'name' component, much as we do for 'type' and for the 'qualifiers' key. See https://github.com/package-url/purl-spec/pull/317#discussion_r1930506051 . | https://github.com/package-url/purl-spec/pull/317 | ||||||||||||||||||||||
14 | name | 4 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's and pombredanne's comments re the 'name' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896747698 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896914775 | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
15 | version | 5 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | "Rules for each purl component" / "version": - A version must be a percent-encoded string | Must space ' ' in a version be percent-encoded? | https://github.com/package-url/purl-spec/issues/35 | |||||||||||||||||||||
16 | version | 5 | Issue | 39 | https://github.com/package-url/purl-spec/issues/39 | "may need to be encoded elsewhere" and "It is unambiguous [sic] unencoded everywhere" seem to contradict one another. Percent-encoded ':' is %3A -- does not appear in the current https://github.com/package-url/purl-spec/blob/master/test-suite-data.json BTW, gernot-h wrote the following (and pombredanne gave :+1:) -- Regarding the confusion about the two statements regarding ":", what about rephrasing the first statement to: From: the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere To: the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. Some of them need to be encoded elsewhere as specified in the rules below. | "Rules for each purl component" / "version": - A version must be a percent-encoded string "Character encoding": - the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere - the ':' scheme and type separator does not need to and must NOT be encoded. It is unambiguous unencoded everywhere | Must ':' in a version be percent-encoded? | stevespringett notes that the test suite includes an example of an unencoded ':' in a version value and proposes changing the "canonical_purl" value from pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io to pkg:docker/customer/dockerimage@sha256%3A244fd47e07d1004f0aed9c?repository_url=gcr.io See test suite test "description": "docker uses qualifiers and hash image id as versions". | Update to make clear that ':' -- add other characters as required -- must be encoded as part of a version value. Update/add tests as needed to clearly illustrate. In addition, as gernot-h suggested and pombredanne gave :+1:, we could also change the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere to the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. Some of them need to be encoded elsewhere as specified in the rules below. [This last change adds some clarity re other encoding requirements but does not address the apparently conflicting provisions.] | https://github.com/package-url/purl-spec/issues/39 | ||||||||||||||||||
17 | version | 5 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's comment re the 'versions' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896815269 | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
18 | version | 5 | PR | 52 to 364 | https://github.com/package-url/purl-spec/pull/364 | JMH: The validate endpoint and purl-validate UI report as valid. This sentence creates ambiguity and needs clarification: "It is unambiguous unencoded everywhere". 2024-12-10 JMH: - "test: character encoding #364" - tagged "Ecma specification", "PURL encoding" and PURL version component". 2024-12-10 JMH: jeremylong has converted PR 52 into separate PRs: #364, #365, #366, #367, and #368. JMH 2025-02-05: PR 364 was merged today. | "Rules for each purl component" / "version": - A version must be a percent-encoded string "Character encoding": - the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere - the ':' scheme and type separator does not need to and must NOT be encoded. It is unambiguous unencoded everywhere | Must ':' in a version (e.g., 'dockerimage@sha256:244f...') be percent-encoded? ===== JMH: check comments for additional characters. | The author changed "purl": "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io", "canonical_purl": "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io", to "purl": "pkg:docker/customer/dockerimage@sha256%3A244fd47e07d1004f0aed9c?repository_url=gcr.io", "canonical_purl": "pkg:docker/customer/dockerimage@sha256%3A244fd47e07d1004f0aed9c?repository_url=gcr.io", stevespringett -- This hasn't been clarified yet and is a subject of discussion in #39 which needs to be clarified before merge. | If the ':' in the version must be encoded, clarify that in this example ':' is not being used as a "separator" as that term is used in the core spec. If this is not the case, clarify the core spec depending on what we decide the rules are. The current rules are confusing and inconsistent. Add/update tests as needed to clarify. | https://github.com/package-url/purl-spec/pull/364 | ||||||||||||||||||
19 | qualifiers | 6 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | "Rules for each purl component" / "qualifiers": - A value must be a percent-encoded string | Must space ' ' in a qualifiers value be percent-encoded? Must '+' in a qualifiers value be percent-encoded? | https://github.com/package-url/purl-spec/issues/35 | |||||||||||||||||||||
20 | qualifiers | 6 | Issue | 39 | https://github.com/package-url/purl-spec/issues/39 | The author notes that the test-suite-data.json references canonical_purl representations like repository_url=repo.spring.io/release -- an unencoded '/' in a qualifiers value. Percent-encoded '/' is %2F -- does not appear in the current https://github.com/package-url/purl-spec/blob/master/test-suite-data.json This issue 39 is also a modest example of an issue/PR that expanded beyond its original focus -- began with questions about ':' and '/' and was expanded to a discussion of other topics ('+' and ' ' [space]). | "Rules for each purl component" / "qualifiers": - A value must be a percent-encoded string "Character encoding": - the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere | Must '/' in a qualifiers value be percent-encoded? | stevespringett notes that the test suite includes an example of an unencoded '/' in a qualifiers value and proposes changing the "canonical_purl" value from pkg:Maven/org.apache.xmlgraphics/batik-anim@1.9.1?repositorY_url=repo.spring.io/release&classifier=sources to pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?classifier=sources&repository_url=repo.spring.io%2Frelease See test suite tests "description": "maven often uses qualifiers" and "description": "maven pom reference" | Update to make clear that '/' -- add other characters as required -- must be encoded as part of a qualifiers value. Update/add tests as needed to clearly illustrate. We could also make the change gernot-h suggested and pombredanne gave :+1:. | https://github.com/package-url/purl-spec/issues/39 | ||||||||||||||||||
21 | qualifiers | 6 | Issue | 73 | https://github.com/package-url/purl-spec/issues/73 | - andrewstein: seeks clarification re how a checksum qualifier should be encoded, including a ":' inside the checksum string itself. - matt-phylum: asserts on 2023-08-01 that the spec makes clear that such a ":" need not be encoded but encoding variations are expected and even an encoded internal ":" would be valid. - No further comments or indication of the status. JMH: It seems clear that in a qualifiers value, the ':' between the algoritm name and value must be encoded. For example, checksum=sha1:ad9503c3e994a4f611a4892f2e67ac82df727086 should be encoded as checksum=sha1%3Aad9503c3e994a4f611a4892f2e67ac82df727086 | "Rules for each purl component" - qualifiers: . . . - For each pair of key = value . . . A value must be a percent-encoded string . . . . "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere . . . "Known qualifiers key/value pairs": . . . - checksum is a qualifier for one or more checksums stored as a comma-separated list. Each item in the value is in form of lowercase_algorithm:hex_encoded_lowercase_value such as sha1:ad9503c3e994a4f611a4892f2e67ac82df727086. For example (with checksums truncated for brevity) checksum=sha1:ad9503c3e994a4f,sha256:41bf9088b3a1e6c1ef1d | Must ':' in a qualifiers value be percent-encoded? | [JMH: I'll add the following to a qualifiers-specific PR] "Rules for each purl component": . . . - qualifiers: . . . - For each pair of key = value . . . - A value must be a percent-encoded string. This applies to all characters in the value including '/' and ':'. . . . "Known qualifiers key/value pairs": . . . - checksum is a qualifier for one or more checksums stored as a comma-separated list. Each item in the value is in form of lowercase_algorithm:hex_encoded_lowercase_value such as sha1:ad9503c3e994a4f611a4892f2e67ac82df727086. For example (with checksums truncated for brevity) checksum=sha1%3Aad9503c3e994a4f,sha256:41bf9088b3a1e6c1ef1d [JMH: If my interpretation is correct, many test objects in test-suite-data.json will need to be corrected.] | https://github.com/package-url/purl-spec/issues/73 | |||||||||||||||||||
22 | qualifiers | 6 | PR | 150 | https://github.com/package-url/purl-spec/pull/150 | The author focuses on the qualifiers value but his change includes one encoding of the '/' in a subpath value as well. The subpath should have been tackled in a separate PR. I treat them separately in this sheet. [JMH: Neither the "/" nor the ":" is mentioned in the qualifiers definition, suggesting that both must be encoded when part of a qualifiers value.] | "Rules for each purl component": . . . - qualifiers: . . . - For each pair of key = value . . . - A value must be a percent-encoded string "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - "the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere" | Must '/' in a qualifiers value be percent-encoded? | stevespringett noted that the test suite does not have repository_url encoded | [JMH: I'll add this to a qualifiers-specific gDoc] "Rules for each purl component": . . . - qualifiers: . . . - For each pair of key = value . . . - A value must be a percent-encoded string. This applies to all characters in the value including '/' and ':'. [JMH: If my interpretation is correct, many test objects in test-suite-data.json will need to be corrected.] | https://github.com/package-url/purl-spec/pull/150 | ||||||||||||||||||
23 | qualifiers | 6 | PR | 184 | https://github.com/package-url/purl-spec/pull/184 | JMH: sschuberth merged this on 2024-11-21. The change that was approved -- a README example -- changing an encoded '/' in a qualifiers value to unencoded -- looks incorrect to me but several commenters seem to conclude that '/' in a qualifiers value is not percent-encoded. This sentence in the spec creates ambiguity and needs clarification: "It is unambiguous unencoded everywhere". | "Rules for each purl component" / "qualifiers": . . . A value must be a percent-encoded string . . . "Character encoding": the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere . . . It is OK to percent-encode purl components otherwise except for the type. . . . . | Must '/' in a qualifiers value be percent-encoded? | From the README: Some `purl` examples . . . pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io%2Frelease changed to pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io/release | Update: "Rules for each purl component" / "qualifiers": . . . A value must be a percent-encoded string, including all characters, symbols and punctuation marks, e.g., '/', '-', '_' and ':'. [This ^ assumes '/' must be percent-encoded -- clarify as needed including clear statements re normalization if applicable.] | https://github.com/package-url/purl-spec/pull/184 | ||||||||||||||||||
24 | qualifiers | 6 | PR | 207 | https://github.com/package-url/purl-spec/pull/207 | JMH: at first blush the test seems wrong: - the download_url qualifiers value with '/' should be shown in canonical form as encoded '/' and with the input containing unencoded '/' should be "is_invalid": true - the checksum qualifiers value with sha1: and sha56: for the input "purl" should show the canoncial with the ':' encoded and should be "is_invalid": true consistent with its sibling qualifiers value. | 7 of the 9 core spec references are 'checksums', 2 are 'checksum'. "Rules for each purl component": . . . - qualifiers: . . . - For each pair of key = value . . . - A value must be a percent-encoded string "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . the '#', '?', '@' and ':' characters must NOT be encoded when used as separators. They may need to be encoded elsewhere . . . - "the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere" . . . "Known qualifiers key/value pairs": . . . - checksum is a qualifier for one or more checksums stored as a comma-separated list. Each item in the value is in form of lowercase_algorithm:hex_encoded_lowercase_value such as sha1:ad9503c3e994a4f611a4892f2e67ac82df727086. For example (with checksums truncated for brevity) checksum=sha1:ad9503c3e994a4f,sha256:41bf9088b3a1e6c1ef1d | Is it 'checksum' or 'checksums'? ===== Plus from apparent errors in the proposed test object: Must '/' in a qualifiers value be percent-encoded? Must ':' in a qualifiers value be percent-encoded? | [Philippe seems to have defined a mutli-step gating item before we can correct the mis-use of the plural form 'checksums' -- see https://github.com/package-url/purl-spec/pull/209#pullrequestreview-2452291675] Correct all 'checksums' to 'checksum' in the core spec -- it's correct in the master PURL-TYPES.rst and does not appear in any form in the master test-suite-data.json, unknown atm whether it appears in 1 or more test files attached to open PRs. [JMH: I'll add the following to a qualifiers-specific PR] "Rules for each purl component": . . . - qualifiers: . . . - For each pair of key = value . . . - A value must be a percent-encoded string. This applies to all characters in the value including '/' and ':'. . . . "Known qualifiers key/value pairs": . . . - checksum is a qualifier for one or more checksums stored as a comma-separated list. Each item in the value is in form of lowercase_algorithm:hex_encoded_lowercase_value such as sha1:ad9503c3e994a4f611a4892f2e67ac82df727086. For example (with checksums truncated for brevity) checksum=sha1%3Aad9503c3e994a4f,sha256:41bf9088b3a1e6c1ef1d [JMH: If my interpretation is correct, many test objects in test-suite-data.json will need to be corrected.] | williamboman opened two PRs on 2022-12-10 related to the 'checksum' qualifiers key and values: PR 207 -- https://github.com/package-url/purl-spec/pull/207 PR 209 -- https://github.com/package-url/purl-spec/pull/209 PR 207 adds a test object that has the correct singular key 'checksum', but two encoding errors in the canonical_purl value: - the ':' following 'sha1' and 'sha256' in the 'checksum' comma-separated value list must be but are not percent-encoded - the multiple '/' in the 'download_url' value must be but are not percent-encoded. PR 209 sought to correct the use of both 'checksum' and 'checksums' in the core spec as the key name by clarifying in two core spec locations that only the singular 'checksum' is correct. - pombredanne also wrote in PR 209 on 2024-11-21 that there are a number of steps to take "before pushing further changes." What sort of gating item is he referring to? No word from the author since he opened PR 209 on 2022-12-10. | https://github.com/package-url/purl-spec/pull/207 | ||||||||||||||||||
25 | qualifiers | 6 | PR | 261 | https://github.com/package-url/purl-spec/pull/261 | Title: "define handling of plus and space" - modifies core spec "Rules for each purl component"/"qualifiers" - modifies core spec "Character encoding" - the ' ' character must be encoded as `%20` everywhere, never '+' - the '+' character should be encoded as `%2B` in qualifiers to avoid problems with certain parsers - modifies type spec - adds 2 golang test objects | 2025-01-27 JMH: Consider in particular the author's (matt-phylum) detailed research re different encoding approaches by various PURL spec implementations and his detailed proposal. | https://github.com/package-url/purl-spec/pull/261 | |||||||||||||||||||||
26 | qualifiers | 6 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's comments re the 'qualifiers' component. - https://github.com/package-url/purl-spec/pull/373#discussion_r1896799433 - https://github.com/package-url/purl-spec/pull/373#discussion_r1896818679 | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
27 | subpath | 7 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | JMH 2025-02-19: the subpath PR https://github.com/package-url/purl-spec/pull/394 has been merged. | - subpath -- "Leading and trailing slashes '/' are not significant and should be stripped in the canonical form" - "How to build purl string from its components" -- "Strip the subpath from leading and trailing '/'" - "How to parse a purl string in its components" -- "Strip the right side from leading and trailing '/'" | Do we need to clarify that this covers 1+ leading and trailing slashes, not just the first of a group? | https://github.com/package-url/purl-spec/issues/35 | ||||||||||||||||||||
28 | subpath | 7 | PR | 150 | https://github.com/package-url/purl-spec/pull/150 | The author focuses on the qualifiers value but his change includes one encoding of the '/' in a subpath value as well. The subpath should have been tackled in a separate PR. I treat them separately in this sheet. 2024-12-16 JMH: It appears the author has removed the proposed subpath change, which had encoded the subpath '/' characters (incorrectly as I understand the spec). I still intend to address the proposed clarification for subpath slashes -- no encoding. JMH 2025-02-19: the subpath PR https://github.com/package-url/purl-spec/pull/394 has been merged. | "Rules for each purl component": . . . - subpath: . . . - The subpath contains zero or more segments, separated by slash '/' . . . - Each subpath segment must be a percent-encoded string - When percent-decoded, a segment … must not contain a '/' …. "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - "the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere" | Must '/' in a subpath value be percent-encoded? | Updated not needed -- the current spec is clear: "Character encoding": . . . Use these rules for percent-encoding and decoding purl components: . . . - "the '/' used as type/namespace/name and subpath segments separator does not need to and must NOT be percent-encoded. It is unambiguous unencoded everywhere" | https://github.com/package-url/purl-spec/pull/150 | |||||||||||||||||||
29 | subpath | 7 | PR | 52 to 368 | https://github.com/package-url/purl-spec/pull/368 | JMH: The validate endpoint and purl-validate UI report as valid. These look valid to me. 2024-12-10 JMH: - "test: unencoded subpath cannot contain . or .. #368" - tagged "PURL subpath component", "PURL encoding" and "Ecma specification". ===== 2024-12-10 JMH: jeremylong has converted PR 52 into separate PRs: #364, #365, #366, #367, and #368. JMH 2025-02-19: the subpath PR https://github.com/package-url/purl-spec/pull/394 has been merged. | "Rules for each purl component" / "subpath" When percent-decoded, a segment . . . must not be any of '..' or '.' . . . . "How to build purl string from its components": If the subpath is not empty and not composed only of empty, '.' and '..' segments . . . Discard empty, '.' and '..' segments . . . . "How to parse a purl string in its components": To parse a purl string in its components: - Split the purl string once from right on '#' . . . - Discard any '.' or '..' segment from that split . . . . | Are '.' or '..' in subpath rejected as invalid, or treated as incorrect and normalized by removing them? | "description": "invalid subpath - unencoded subpath cannot contain ..", "purl": "pkg:GOLANG/google.golang.org/genproto@abcdedf#/googleapis/%2E%2E/api/annotations/", "canonical_purl": "pkg:golang/google.golang.org/genproto@abcdedf#googleapis/api/annotations", . . . "is_invalid": true "description": "invalid subpath - unencoded subpath cannot contain .", "purl": "pkg:GOLANG/google.golang.org/genproto@abcdedf#/googleapis/%2E/api/annotations/", "canonical_purl": "pkg:golang/google.golang.org/genproto@abcdedf#googleapis/api/annotations", . . . "is_invalid": true | Clarify: a subpath segment that contains only '.', '..', '...' etc. is invalid -- or is there a better word? -- and must be normalized by removing that segment. Update and add tests to illustrate. | https://github.com/package-url/purl-spec/pull/368 | ||||||||||||||||||
30 | between scheme and type | 8 | PR | 52 to 365 | https://github.com/package-url/purl-spec/pull/365 | 2024-12-10 JMH: - "test: correct test description for leading slashes #365" - tagged "PURL miscellaneous slashes" and "Ecma specification". JMH: just a copy-paste correction, raises no encoding issues. | https://github.com/package-url/purl-spec/pull/365 | ||||||||||||||||||||||
31 | between version value and qualifiers separator '?' | 9 | PR | 52 to 366 | https://github.com/package-url/purl-spec/pull/366 | 2024-12-10 JMH: - "test: improve test code coverage #366" - tagged "PURL miscellaneous slashes" and "Ecma specification". ===== 2024-12-10 JMH: jeremylong has converted PR 52 into separate PRs: #364, #365, #366, #367, and #368. | The core spec does not address the case of a '/' between version and the '?' qualifiers separator. | Is '/' between version and qualifiers separator '?' valid? Is it normalized by removing? | stevespringett -- The spec states that leading and trailing / is not significant on namespace and subpath only. This may be an invalid test case. Need clarification @pombredanne "description": "slash / between version and qualifiers separator is not significant", "purl": "pkg:maven/org.apache.commons/io@2.6/?scope=test", "canonical_purl": "pkg:maven/org.apache.commons/io@2.6?scope=test", . . . "is_invalid": false jeremylong -- This was added as part of code coverage in the java implementation. If this is invalid - then the How to parse may contain unnecessary steps. The step after Split the remainder once from left on ':' is Strip the remainder from leading and trailing '/'. Trying to figure out what other type of URL would end up with a trailing '/' at this point in parsing. | Add a rule that clearly states that all extraneous '/' not otherwise expressly addressed in the spec to be ignored and normalized by removing. Add test examples. | https://github.com/package-url/purl-spec/pull/366 | ||||||||||||||||||
32 | namespace, name, version, qualifiers and subpath | 10 | PR | 273 | https://github.com/package-url/purl-spec/pull/273 | - 2023-11-20 matt-phylum: "This PR adds a simple test that percent signs are correctly encoded and decoded in all parts of a PURL." - No comments. The test: "purl": "pkg:generic/100%25/100%25@100%25?repository_url=https://example.com/100%2525/#100%25", "canonical_purl": "pkg:generic/100%25/100%25@100%25?repository_url=https://example.com/100%2525/#100%25", 2024-12-11 JMH: the purl-validate UI seems to get this 100% correct: all 5 are decoded to 100%. My understanding is that the 'canonical_purl' value is meant to include percent-encoded characters etc. and other normalizing steps required by the core spec. If that's correct, the single proposed test object looks correct to me and this PR could be approved (needs 2 approvals) and merged as is, no apparent need to clarify or correct the core spec. | namespace "Each namespace segment must be a percent-encoded string" name "A name must be a percent-encoded string" version "A version must be a percent-encoded string" qualifiers "For each pair of key = value . . . A value must be a percent-encoded string" subpath "Each subpath segment must be a percent-encoded string" | Is the proposed test object correct and if so is this ready to get 2 approvals and be merged? JMH: I think the answer is Yes. The sole focus of this PR is a test -- perhaps this is not part of the core spec updating? | { "description": "percent signs are properly encoded and decoded", "purl": "pkg:generic/100%25/100%25@100%25?repository_url=https://example.com/100%2525/#100%25", "canonical_purl": "pkg:generic/100%25/100%25@100%25?repository_url=https://example.com/100%2525/#100%25", "type": "generic", "namespace": "100%", "name": "100%", "version": "100%", "qualifiers": { "repository_url": "https://example.com/100%25/" }, "subpath": "100%", "is_invalid": false } | https://github.com/package-url/purl-spec/pull/273 | |||||||||||||||||||
33 | miscellaneous encoding and other | 11 | Issue | 35 | https://github.com/package-url/purl-spec/issues/35 | This issue addresses what should be multiple separate issues (at least some of which have already been addressed). See "issue/PR comments/files" column. 2024-12-13 JMH todo: identify which of the encoding-related topics raised in the issue have already been addressed, address remainder here. 2024012-16 JMH: See row 8 -- a placeholder to address the name component encoding questions/issues. JMH See also dev log list of numerous characters etc. raised in this single issue -- add to each component as needed and note here when done. | See the "issue/PR comments/files" column. | checksum qualifier - how must an algorithm name be expressed? - should the canonical form of checksum list be deduped and/or sorted? '/' - When parsing, should "strip leading and trailing /" include runs of slashes or just a single slash? encoding - re RFC 3986's reference to the reserved and unreserved characters, must all reserved characters be encoded (unless explicitly used as a purl delimiter)? - must none of the unreserved characters be encoded? spaces - must space be encoded in name? version? qualifiers value? '+' - must '+' be encoded in qualifiers value? ''' [single quote/apostrophe] - must single quote be encoded in namespace? '!' - must '!' be encoded in name? The meaning of "lowercase" transformation needs clarification re how different languages handle Need to change "left" and "right" to "start" and "end" to handle "non-LTR scripts or strings with bidirectional markers" | 2024-12-17 JMH: Since the following topic from issue 35 does not neatly fit into any of the component categories, we might treat this as a miscellaneous/througout-the-PURL update/PR: In the "Character encoding" section, replace this: For clarity and simplicity a purl is always an ASCII string. To ensure that there is no ambiguity when parsing a purl, separator characters and non-ASCII characters must be UTF-encoded and then percent-encoded as defined at: https://en.wikipedia.org/wiki/Percent-encoding with this: For clarity and simplicity, a PURL is always an ASCII string. To ensure that there is no ambiguity when parsing a PURL, in keeping with RFC 3986 (https://tools.ietf.org/html/rfc3986 -- see also https://en.wikipedia.org/wiki/Percent-encoding), - unless explicitly used as a PURL delimiter/separator, all 18 reserved ASCII characters (including ':', '/', '@', '?' and '#') MUST be percent-encoded, - none of the 66 unreserved ASCII characters SHOULD be percent-encoded, - all other ASCII characters MUST be percent-encoded (e.g., space ' ', encoded as `%20`), and - all non-ASCII characters MUST be UTF-8-encoded and then percent-encoded | 2024-12-12 JMH: I suggest we - examine the core spec and determine what still needs to be addressed - use the character-encoding and "errant" slashes topics to ensure all are addressed in the relevant component/category PRs - address what remains and then close this issue | https://github.com/package-url/purl-spec/issues/35 | ||||||||||||||||||
34 | throughout the PURL | 12 | Issue | 58 | https://github.com/package-url/purl-spec/issues/58 | See also PR 261 "define handling of plus and space" (involves encoding for qualifiers -- space ' ' and plus sign '+'. | When must '+' be encoded? When must ' ' be encoded? ===== Raised by commenter: When must QueryEscape be used? When must PathEscape be used? When must '@' be encoded? | https://github.com/package-url/purl-spec/issues/58 | |||||||||||||||||||||
35 | throughout the PURL | 12 | PR | 248 | https://github.com/package-url/purl-spec/pull/248 | Title: "Extend test suite with a range of additional invalid Package URLs" 2024-12-14 JMH: The 14 proposed new test objects cover: - type - namespace - qualifiers - subpath - name (as an example for non-unicode characters) ==> see "issue/PR comments/files" column JMH: The components addressed in this PR need to be addressed separately. atm I expect I'll address each as part of the core spec update process first, and only when that's finished will we determine what needs to be done with this PR 248 itself. Note: the only changed file is test-suite-data.json -- are we handling that as part of the core spec updating? | See the test objects in the test-suite-data.json file. | Broad set of test objects: - "qualifiers with empty values are ignored" - "qualifiers with empty values and missing = are ignored" - "subpath containing '.' are invalid" - "subpath containing '..' are invalid" - "subpath with percent encoded / are invalid" - "key must be unique within the keys of the qualifiers string" - "qualifier keys must not start with numbers" - "qualifier keys must not be percent encoded" - "The package type is composed only of ASCII letters and numbers, '.', '+' and '-'" [matt-phylum: "Isn't this valid...?" - "The type cannot start with a number" - "The type cannot contain spaces" - "A namespace segment must not be empty" - "A namespace segment must not contain a percent-encoded '/'" - "Non-unicode characters must be percent encoded" | This will be addressed in separate PRs, component/category by component/category. | 2024-12-14 JMH: matt-phylum commented that this test is valid, but it looks invalid (because the type has an impermissible character '@'): { "description": "The package type is composed only of ASCII letters and numbers, '.', '+' and '-'", "purl": "pkg:n@m/test", "canonical_purl": "pkg:n@m/test", "type": null, "namespace": null, "name": null, "version": null, "qualifiers": null, "subpath": null, "is_invalid": true }, JMH: This proposed test looks incorrect -- the 'purl' namespace segments do not contain an encoded or unencoded '/' -- did the author intend %2F rather than %25? "description": "A namespace segment must not contain a percent-encoded '/'", "purl": "pkg:npm/some/%25/org/pkg", "canonical_purl": "pkg:npm/some/%25/org/pkg", "type": null, "namespace": null, "name": null, "version": null, "qualifiers": null, "subpath": null, "is_invalid": true }, | https://github.com/package-url/purl-spec/pull/248 | ||||||||||||||||||
36 | RFC 2119/8174 | 13 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-24 JMH: The 'scheme' PR I updated yesterday (PR 361) was also originally planned to introduce our implementation of RFC 2119/8174. We decided instead to use a stand-alone PR (this PR 373) narrowly focused on introducing RFC 2119/8174 and changing the relevant terms to uppercase as needed. However, after seeing a number of valuable points raised by matt-phylum in his comments, it's apparent that implementing RFC 2119/8174 needs to be done on a component-by-component basis. I'll create a list below of the points raised in the PR 373 comments that we'll address component-by-component: - issue 35 re the 'type' component - [more to follow] | See https://github.com/package-url/purl-spec/pull/373. | https://github.com/package-url/purl-spec/pull/373 | |||||||||||||||||||||
37 | tests | 14 | PR | 373 | https://github.com/package-url/purl-spec/pull/373 | 2024-12-25 JMH: See matt-phylum's comments re the description of . . . . . . when a test MUST report an error - https://github.com/package-url/purl-spec/pull/373#discussion_r1896819081 . . . when a PURL implementation MUST return the value specified by the test - https://github.com/package-url/purl-spec/pull/373#discussion_r1896821554 | https://github.com/package-url/purl-spec/pull/373 | ||||||||||||||||||||||
38 | |||||||||||||||||||||||||||||
39 | |||||||||||||||||||||||||||||
40 | |||||||||||||||||||||||||||||
41 | |||||||||||||||||||||||||||||
42 | |||||||||||||||||||||||||||||
43 | |||||||||||||||||||||||||||||
44 | |||||||||||||||||||||||||||||
45 | |||||||||||||||||||||||||||||
46 | |||||||||||||||||||||||||||||
47 | |||||||||||||||||||||||||||||
48 | |||||||||||||||||||||||||||||
49 | |||||||||||||||||||||||||||||
50 | |||||||||||||||||||||||||||||
51 | |||||||||||||||||||||||||||||
52 | |||||||||||||||||||||||||||||
53 | |||||||||||||||||||||||||||||
54 | |||||||||||||||||||||||||||||
55 | |||||||||||||||||||||||||||||
56 | |||||||||||||||||||||||||||||
57 | |||||||||||||||||||||||||||||
58 | |||||||||||||||||||||||||||||
59 | |||||||||||||||||||||||||||||
60 | |||||||||||||||||||||||||||||
61 | |||||||||||||||||||||||||||||
62 | |||||||||||||||||||||||||||||
63 | |||||||||||||||||||||||||||||
64 | |||||||||||||||||||||||||||||
65 | |||||||||||||||||||||||||||||
66 | |||||||||||||||||||||||||||||
67 | |||||||||||||||||||||||||||||
68 | |||||||||||||||||||||||||||||
69 | |||||||||||||||||||||||||||||
70 | |||||||||||||||||||||||||||||
71 | |||||||||||||||||||||||||||||
72 | |||||||||||||||||||||||||||||
73 | |||||||||||||||||||||||||||||
74 | |||||||||||||||||||||||||||||
75 | |||||||||||||||||||||||||||||
76 | |||||||||||||||||||||||||||||
77 | |||||||||||||||||||||||||||||
78 | |||||||||||||||||||||||||||||
79 | |||||||||||||||||||||||||||||
80 | |||||||||||||||||||||||||||||
81 | |||||||||||||||||||||||||||||
82 | |||||||||||||||||||||||||||||
83 | |||||||||||||||||||||||||||||
84 | |||||||||||||||||||||||||||||
85 | |||||||||||||||||||||||||||||
86 | |||||||||||||||||||||||||||||
87 | |||||||||||||||||||||||||||||
88 | |||||||||||||||||||||||||||||
89 | |||||||||||||||||||||||||||||
90 | |||||||||||||||||||||||||||||
91 | |||||||||||||||||||||||||||||
92 | |||||||||||||||||||||||||||||
93 | |||||||||||||||||||||||||||||
94 | |||||||||||||||||||||||||||||
95 | |||||||||||||||||||||||||||||
96 | |||||||||||||||||||||||||||||
97 | |||||||||||||||||||||||||||||
98 | |||||||||||||||||||||||||||||
99 | |||||||||||||||||||||||||||||
100 |