isomorphic-git 1.41.0 → 1.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -8974,21 +8974,76 @@ async function collect(iterable) {
8974
8974
  return result
8975
8975
  }
8976
8976
 
8977
+ // The `@` that ends the credentials is the last one in the authority, and the
8978
+ // scheme is matched case-insensitively: `HTTPS://user:pass@host/x` is a URL
8979
+ // like any other, and leaving the credentials in it is what `fetch` rejects.
8980
+ // The authority ends at the first `/`, `?` or `#`, so an `@` that lives in a
8981
+ // query or a fragment is left where it is.
8982
+ const CREDENTIALS = /^(https?:\/\/)([^/?#]+)@/i;
8983
+
8977
8984
  function extractAuthFromUrl(url) {
8978
8985
  // For whatever reason, the `fetch` API does not convert credentials embedded in the URL
8979
8986
  // into Basic Authentication headers automatically. Instead it throws an error!
8980
8987
  // So we must manually parse the URL, rip out the user:password portion if it is present
8981
8988
  // and compute the Authorization header.
8982
- // Note: I tried using new URL(url) but that throws a security exception in Edge. :rolleyes:
8983
- let userpass = url.match(/^https?:\/\/([^/]+)@/);
8989
+ const credentials = url.match(CREDENTIALS);
8984
8990
  // No credentials, return the url unmodified and an empty auth object
8985
- if (userpass == null) return { url, auth: {} }
8986
- userpass = userpass[1];
8987
- const [username, password] = userpass.split(':');
8988
- // Remove credentials from URL
8989
- url = url.replace(`${userpass}@`, '');
8990
- // Has credentials, return the fetch-safe URL and the parsed credentials
8991
- return { url, auth: { username, password } }
8991
+ if (credentials == null) return { url, auth: {} }
8992
+ // Has credentials, return the fetch-safe URL and the parsed credentials.
8993
+ // The credentials are cut out of the original string rather than read back
8994
+ // off the parsed URL: serializing that one would also drop an explicit
8995
+ // `:443` and append a slash to a URL that has no path, and this return value
8996
+ // is what the request goes out against.
8997
+ return {
8998
+ url: url.replace(CREDENTIALS, '$1'),
8999
+ auth: parseUserinfo(url, credentials[2]),
9000
+ }
9001
+ }
9002
+
9003
+ function parseUserinfo(url, userpass) {
9004
+ // `URL` splits the two halves the way the platform does, so the first colon
9005
+ // separates them and any later one stays in the password. Only the split is
9006
+ // taken from it, for the reason above.
9007
+ const parsed = parseUrl(url);
9008
+ // A password is absent, not empty, when no colon was written at all. `URL`
9009
+ // reports `''` for both, and the difference is worth keeping.
9010
+ const hasPassword = userpass.indexOf(':') !== -1;
9011
+
9012
+ if (parsed !== null) {
9013
+ return {
9014
+ username: decodeUserinfo(parsed.username),
9015
+ password: hasPassword ? decodeUserinfo(parsed.password) : undefined,
9016
+ }
9017
+ }
9018
+
9019
+ // No `URL` to parse with, or it rejected a string the expression above
9020
+ // accepted. Split on the first colon by hand, without the percent-decoding.
9021
+ const separatorIndex = userpass.indexOf(':');
9022
+ return {
9023
+ username: hasPassword ? userpass.slice(0, separatorIndex) : userpass,
9024
+ password: hasPassword ? userpass.slice(separatorIndex + 1) : undefined,
9025
+ }
9026
+ }
9027
+
9028
+ function parseUrl(url) {
9029
+ if (typeof URL !== 'function') return null
9030
+ try {
9031
+ return new URL(url)
9032
+ } catch (_) {
9033
+ return null
9034
+ }
9035
+ }
9036
+
9037
+ // `URL` hands back the userinfo still percent-encoded, so `p:ss` arrives as
9038
+ // `p%3Ass` and has to be decoded before it reaches the Authorization header. A
9039
+ // lone `%` is not something the parser encodes, and it makes the decode throw,
9040
+ // so the raw value stands in whenever the decode fails.
9041
+ function decodeUserinfo(value) {
9042
+ try {
9043
+ return decodeURIComponent(value)
9044
+ } catch (_) {
9045
+ return value
9046
+ }
8992
9047
  }
8993
9048
 
8994
9049
  function padHex(b, n) {
@@ -9630,8 +9685,8 @@ function filterCapabilities(server, client) {
9630
9685
 
9631
9686
  const pkg = {
9632
9687
  name: 'isomorphic-git',
9633
- version: '1.41.0',
9634
- agent: 'git/isomorphic-git@1.41.0',
9688
+ version: '1.41.1',
9689
+ agent: 'git/isomorphic-git@1.41.1',
9635
9690
  };
9636
9691
 
9637
9692
  class FIFO {
package/index.js CHANGED
@@ -8961,21 +8961,76 @@ async function collect(iterable) {
8961
8961
  return result
8962
8962
  }
8963
8963
 
8964
+ // The `@` that ends the credentials is the last one in the authority, and the
8965
+ // scheme is matched case-insensitively: `HTTPS://user:pass@host/x` is a URL
8966
+ // like any other, and leaving the credentials in it is what `fetch` rejects.
8967
+ // The authority ends at the first `/`, `?` or `#`, so an `@` that lives in a
8968
+ // query or a fragment is left where it is.
8969
+ const CREDENTIALS = /^(https?:\/\/)([^/?#]+)@/i;
8970
+
8964
8971
  function extractAuthFromUrl(url) {
8965
8972
  // For whatever reason, the `fetch` API does not convert credentials embedded in the URL
8966
8973
  // into Basic Authentication headers automatically. Instead it throws an error!
8967
8974
  // So we must manually parse the URL, rip out the user:password portion if it is present
8968
8975
  // and compute the Authorization header.
8969
- // Note: I tried using new URL(url) but that throws a security exception in Edge. :rolleyes:
8970
- let userpass = url.match(/^https?:\/\/([^/]+)@/);
8976
+ const credentials = url.match(CREDENTIALS);
8971
8977
  // No credentials, return the url unmodified and an empty auth object
8972
- if (userpass == null) return { url, auth: {} }
8973
- userpass = userpass[1];
8974
- const [username, password] = userpass.split(':');
8975
- // Remove credentials from URL
8976
- url = url.replace(`${userpass}@`, '');
8977
- // Has credentials, return the fetch-safe URL and the parsed credentials
8978
- return { url, auth: { username, password } }
8978
+ if (credentials == null) return { url, auth: {} }
8979
+ // Has credentials, return the fetch-safe URL and the parsed credentials.
8980
+ // The credentials are cut out of the original string rather than read back
8981
+ // off the parsed URL: serializing that one would also drop an explicit
8982
+ // `:443` and append a slash to a URL that has no path, and this return value
8983
+ // is what the request goes out against.
8984
+ return {
8985
+ url: url.replace(CREDENTIALS, '$1'),
8986
+ auth: parseUserinfo(url, credentials[2]),
8987
+ }
8988
+ }
8989
+
8990
+ function parseUserinfo(url, userpass) {
8991
+ // `URL` splits the two halves the way the platform does, so the first colon
8992
+ // separates them and any later one stays in the password. Only the split is
8993
+ // taken from it, for the reason above.
8994
+ const parsed = parseUrl(url);
8995
+ // A password is absent, not empty, when no colon was written at all. `URL`
8996
+ // reports `''` for both, and the difference is worth keeping.
8997
+ const hasPassword = userpass.indexOf(':') !== -1;
8998
+
8999
+ if (parsed !== null) {
9000
+ return {
9001
+ username: decodeUserinfo(parsed.username),
9002
+ password: hasPassword ? decodeUserinfo(parsed.password) : undefined,
9003
+ }
9004
+ }
9005
+
9006
+ // No `URL` to parse with, or it rejected a string the expression above
9007
+ // accepted. Split on the first colon by hand, without the percent-decoding.
9008
+ const separatorIndex = userpass.indexOf(':');
9009
+ return {
9010
+ username: hasPassword ? userpass.slice(0, separatorIndex) : userpass,
9011
+ password: hasPassword ? userpass.slice(separatorIndex + 1) : undefined,
9012
+ }
9013
+ }
9014
+
9015
+ function parseUrl(url) {
9016
+ if (typeof URL !== 'function') return null
9017
+ try {
9018
+ return new URL(url)
9019
+ } catch (_) {
9020
+ return null
9021
+ }
9022
+ }
9023
+
9024
+ // `URL` hands back the userinfo still percent-encoded, so `p:ss` arrives as
9025
+ // `p%3Ass` and has to be decoded before it reaches the Authorization header. A
9026
+ // lone `%` is not something the parser encodes, and it makes the decode throw,
9027
+ // so the raw value stands in whenever the decode fails.
9028
+ function decodeUserinfo(value) {
9029
+ try {
9030
+ return decodeURIComponent(value)
9031
+ } catch (_) {
9032
+ return value
9033
+ }
8979
9034
  }
8980
9035
 
8981
9036
  function padHex(b, n) {
@@ -9617,8 +9672,8 @@ function filterCapabilities(server, client) {
9617
9672
 
9618
9673
  const pkg = {
9619
9674
  name: 'isomorphic-git',
9620
- version: '1.41.0',
9621
- agent: 'git/isomorphic-git@1.41.0',
9675
+ version: '1.41.1',
9676
+ agent: 'git/isomorphic-git@1.41.1',
9622
9677
  };
9623
9678
 
9624
9679
  class FIFO {