GeezerVison is showing github.com — buffer: add base64url encoding option · nodejs/node@832cd01
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/buffer.md +13-3Lines changed: 13 additions & 3 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -50,6 +50,9 @@ const buf7 = Buffer.from('tést', 'latin1'); | 50 | 50 | ## Buffers and character encodings | 51 | 51 | <!-- YAML | 52 | 52 | changes: | | 53 | + - version: REPLACEME | | 54 | + pr-url: https://github.com/nodejs/node/pull/36952 | | 55 | + description: Introduced `base64url` encoding. | 53 | 56 | - version: v6.4.0 | 54 | 57 | pr-url: https://github.com/nodejs/node/pull/7111 | 55 | 58 | description: Introduced `latin1` as an alias for `binary`. | @@ -106,6 +109,11 @@ string into a `Buffer` as decoding. | 106 | 109 | specified in [RFC 4648, Section 5][]. Whitespace characters such as spaces, | 107 | 110 | tabs, and new lines contained within the base64-encoded string are ignored. | 108 | 111 |
| | 112 | +* `'base64url'`: [base64url][] encoding as specified in | | 113 | + [RFC 4648, Section 5][]. When creating a `Buffer` from a string, this | | 114 | + encoding will also correctly accept regular base64-encoded strings. When | | 115 | + encoding a `Buffer` to a string, this encoding will omit padding. | | 116 | + | 109 | 117 | * `'hex'`: Encode each byte as two hexadecimal characters. Data truncation | 110 | 118 | may occur when decoding strings that do exclusively contain valid hexadecimal | 111 | 119 | characters. See below for an example. | @@ -482,9 +490,10 @@ Returns the byte length of a string when encoded using `encoding`. | 482 | 490 | This is not the same as [`String.prototype.length`][], which does not account | 483 | 491 | for the encoding that is used to convert the string into bytes. | 484 | 492 |
| 485 | | -For `'base64'` and `'hex'`, this function assumes valid input. For strings that | 486 | | -contain non-base64/hex-encoded data (e.g. whitespace), the return value might be | 487 | | -greater than the length of a `Buffer` created from the string. | | 493 | +For `'base64'`, `'base64url'`, and `'hex'`, this function assumes valid input. | | 494 | +For strings that contain non-base64/hex-encoded data (e.g. whitespace), the | | 495 | +return value might be greater than the length of a `Buffer` created from the | | 496 | +string. | 488 | 497 |
| 489 | 498 | ```js | 490 | 499 | const str = '\u00bd + \u00bc = \u00be'; | @@ -3418,6 +3427,7 @@ introducing security vulnerabilities into an application. | 3418 | 3427 | [`buffer.constants.MAX_STRING_LENGTH`]: #buffer_buffer_constants_max_string_length | 3419 | 3428 | [`buffer.kMaxLength`]: #buffer_buffer_kmaxlength | 3420 | 3429 | [`util.inspect()`]: util.md#util_util_inspect_object_options | | 3430 | +[base64url]: https://tools.ietf.org/html/rfc4648#section-5 | 3421 | 3431 | [binary strings]: https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary | 3422 | 3432 | [endianness]: https://en.wikipedia.org/wiki/Endianness | 3423 | 3433 | [iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols |
Collapse file Copy file name to clipboardExpand all lines: lib/buffer.js +19Lines changed: 19 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -646,6 +646,20 @@ const encodingOps = { | 646 | 646 | encodingsMap.base64, | 647 | 647 | dir) | 648 | 648 | }, | | 649 | + base64url: { | | 650 | + encoding: 'base64url', | | 651 | + encodingVal: encodingsMap.base64url, | | 652 | + byteLength: (string) => base64ByteLength(string, string.length), | | 653 | + write: (buf, string, offset, len) => | | 654 | + buf.base64urlWrite(string, offset, len), | | 655 | + slice: (buf, start, end) => buf.base64urlSlice(start, end), | | 656 | + indexOf: (buf, val, byteOffset, dir) => | | 657 | + indexOfBuffer(buf, | | 658 | + fromStringFast(val, encodingOps.base64url), | | 659 | + byteOffset, | | 660 | + encodingsMap.base64url, | | 661 | + dir) | | 662 | + }, | 649 | 663 | hex: { | 650 | 664 | encoding: 'hex', | 651 | 665 | encodingVal: encodingsMap.hex, | @@ -702,6 +716,11 @@ function getEncodingOps(encoding) { | 702 | 716 | if (encoding === 'hex' || StringPrototypeToLowerCase(encoding) === 'hex') | 703 | 717 | return encodingOps.hex; | 704 | 718 | break; | | 719 | + case 9: | | 720 | + if (encoding === 'base64url' || | | 721 | + StringPrototypeToLowerCase(encoding) === 'base64url') | | 722 | + return encodingOps.base64url; | | 723 | + break; | 705 | 724 | } | 706 | 725 | } | 707 | 726 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/buffer.js +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -18,12 +18,14 @@ const { validateNumber } = require('internal/validators'); | 18 | 18 | const { | 19 | 19 | asciiSlice, | 20 | 20 | base64Slice, | | 21 | + base64urlSlice, | 21 | 22 | latin1Slice, | 22 | 23 | hexSlice, | 23 | 24 | ucs2Slice, | 24 | 25 | utf8Slice, | 25 | 26 | asciiWrite, | 26 | 27 | base64Write, | | 28 | + base64urlWrite, | 27 | 29 | latin1Write, | 28 | 30 | hexWrite, | 29 | 31 | ucs2Write, | @@ -1027,12 +1029,14 @@ function addBufferPrototypeMethods(proto) { | 1027 | 1029 |
| 1028 | 1030 | proto.asciiSlice = asciiSlice; | 1029 | 1031 | proto.base64Slice = base64Slice; | | 1032 | + proto.base64urlSlice = base64urlSlice; | 1030 | 1033 | proto.latin1Slice = latin1Slice; | 1031 | 1034 | proto.hexSlice = hexSlice; | 1032 | 1035 | proto.ucs2Slice = ucs2Slice; | 1033 | 1036 | proto.utf8Slice = utf8Slice; | 1034 | 1037 | proto.asciiWrite = asciiWrite; | 1035 | 1038 | proto.base64Write = base64Write; | | 1039 | + proto.base64urlWrite = base64urlWrite; | 1036 | 1040 | proto.latin1Write = latin1Write; | 1037 | 1041 | proto.hexWrite = hexWrite; | 1038 | 1042 | proto.ucs2Write = ucs2Write; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/util.js +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -180,6 +180,11 @@ function slowCases(enc) { | 180 | 180 | StringPrototypeToLowerCase(`${enc}`) === 'utf-16le') | 181 | 181 | return 'utf16le'; | 182 | 182 | break; | | 183 | + case 9: | | 184 | + if (enc === 'base64url' || enc === 'BASE64URL' || | | 185 | + StringPrototypeToLowerCase(`${enc}`) === 'base64url') | | 186 | + return 'base64url'; | | 187 | + break; | 183 | 188 | default: | 184 | 189 | if (enc === '') return 'utf8'; | 185 | 190 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/api/encoding.cc +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -68,13 +68,17 @@ enum encoding ParseEncoding(const char* encoding, | 68 | 68 | } else if (encoding[1] == 'a') { | 69 | 69 | if (strncmp(encoding + 2, "se64", 5) == 0) | 70 | 70 | return BASE64; | | 71 | + if (strncmp(encoding + 2, "se64url", 8) == 0) | | 72 | + return BASE64URL; | 71 | 73 | } | 72 | 74 | if (StringEqualNoCase(encoding, "binary")) | 73 | 75 | return LATIN1; // BINARY is a deprecated alias of LATIN1. | 74 | 76 | if (StringEqualNoCase(encoding, "buffer")) | 75 | 77 | return BUFFER; | 76 | 78 | if (StringEqualNoCase(encoding, "base64")) | 77 | 79 | return BASE64; | | 80 | + if (StringEqualNoCase(encoding, "base64url")) | | 81 | + return BASE64URL; | 78 | 82 | break; | 79 | 83 |
| 80 | 84 | case 'a': | |
Collapse file Copy file name to clipboardExpand all lines: src/node_buffer.cc +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1184,13 +1184,15 @@ void Initialize(Local<Object> target, | 1184 | 1184 |
| 1185 | 1185 | env->SetMethodNoSideEffect(target, "asciiSlice", StringSlice<ASCII>); | 1186 | 1186 | env->SetMethodNoSideEffect(target, "base64Slice", StringSlice<BASE64>); | | 1187 | + env->SetMethodNoSideEffect(target, "base64urlSlice", StringSlice<BASE64URL>); | 1187 | 1188 | env->SetMethodNoSideEffect(target, "latin1Slice", StringSlice<LATIN1>); | 1188 | 1189 | env->SetMethodNoSideEffect(target, "hexSlice", StringSlice<HEX>); | 1189 | 1190 | env->SetMethodNoSideEffect(target, "ucs2Slice", StringSlice<UCS2>); | 1190 | 1191 | env->SetMethodNoSideEffect(target, "utf8Slice", StringSlice<UTF8>); | 1191 | 1192 |
| 1192 | 1193 | env->SetMethod(target, "asciiWrite", StringWrite<ASCII>); | 1193 | 1194 | env->SetMethod(target, "base64Write", StringWrite<BASE64>); | | 1195 | + env->SetMethod(target, "base64urlWrite", StringWrite<BASE64URL>); | 1194 | 1196 | env->SetMethod(target, "latin1Write", StringWrite<LATIN1>); | 1195 | 1197 | env->SetMethod(target, "hexWrite", StringWrite<HEX>); | 1196 | 1198 | env->SetMethod(target, "ucs2Write", StringWrite<UCS2>); | @@ -1223,13 +1225,15 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 1223 | 1225 |
| 1224 | 1226 | registry->Register(StringSlice<ASCII>); | 1225 | 1227 | registry->Register(StringSlice<BASE64>); | | 1228 | + registry->Register(StringSlice<BASE64URL>); | 1226 | 1229 | registry->Register(StringSlice<LATIN1>); | 1227 | 1230 | registry->Register(StringSlice<HEX>); | 1228 | 1231 | registry->Register(StringSlice<UCS2>); | 1229 | 1232 | registry->Register(StringSlice<UTF8>); | 1230 | 1233 |
| 1231 | 1234 | registry->Register(StringWrite<ASCII>); | 1232 | 1235 | registry->Register(StringWrite<BASE64>); | | 1236 | + registry->Register(StringWrite<BASE64URL>); | 1233 | 1237 | registry->Register(StringWrite<LATIN1>); | 1234 | 1238 | registry->Register(StringWrite<HEX>); | 1235 | 1239 | registry->Register(StringWrite<UCS2>); | |
Collapse file Copy file name to clipboardExpand all lines: src/string_decoder.cc +6-2Lines changed: 6 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -70,7 +70,10 @@ MaybeLocal<String> StringDecoder::DecodeData(Isolate* isolate, | 70 | 70 |
| 71 | 71 | size_t nread = *nread_ptr; | 72 | 72 |
| 73 | | - if (Encoding() == UTF8 || Encoding() == UCS2 || Encoding() == BASE64) { | | 73 | + if (Encoding() == UTF8 || | | 74 | + Encoding() == UCS2 || | | 75 | + Encoding() == BASE64 || | | 76 | + Encoding() == BASE64URL) { | 74 | 77 | // See if we want bytes to finish a character from the previous | 75 | 78 | // chunk; if so, copy the new bytes to the missing bytes buffer | 76 | 79 | // and create a small string from it that is to be prepended to the | @@ -198,7 +201,7 @@ MaybeLocal<String> StringDecoder::DecodeData(Isolate* isolate, | 198 | 201 | state_[kBufferedBytes] = 2; | 199 | 202 | state_[kMissingBytes] = 2; | 200 | 203 | } | 201 | | - } else if (Encoding() == BASE64) { | | 204 | + } else if (Encoding() == BASE64 || Encoding() == BASE64URL) { | 202 | 205 | state_[kBufferedBytes] = nread % 3; | 203 | 206 | if (state_[kBufferedBytes] > 0) | 204 | 207 | state_[kMissingBytes] = 3 - BufferedBytes(); | @@ -311,6 +314,7 @@ void InitializeStringDecoder(Local<Object> target, | 311 | 314 | ADD_TO_ENCODINGS_ARRAY(ASCII, "ascii"); | 312 | 315 | ADD_TO_ENCODINGS_ARRAY(UTF8, "utf8"); | 313 | 316 | ADD_TO_ENCODINGS_ARRAY(BASE64, "base64"); | | 317 | + ADD_TO_ENCODINGS_ARRAY(BASE64URL, "base64url"); | 314 | 318 | ADD_TO_ENCODINGS_ARRAY(UCS2, "utf16le"); | 315 | 319 | ADD_TO_ENCODINGS_ARRAY(HEX, "hex"); | 316 | 320 | ADD_TO_ENCODINGS_ARRAY(BUFFER, "buffer"); | |
Collapse file Copy file name to clipboardExpand all lines: test/addons/parse-encoding/binding.cc +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -6,6 +6,7 @@ namespace { | 6 | 6 | #define ENCODING_MAP(V) \ | 7 | 7 | V(ASCII) \ | 8 | 8 | V(BASE64) \ | | 9 | + V(BASE64URL) \ | 9 | 10 | V(BUFFER) \ | 10 | 11 | V(HEX) \ | 11 | 12 | V(LATIN1) \ | |
Collapse file Copy file name to clipboardExpand all lines: test/addons/parse-encoding/test.js +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -8,6 +8,7 @@ assert.strictEqual(parseEncoding(''), 'UNKNOWN'); | 8 | 8 |
| 9 | 9 | assert.strictEqual(parseEncoding('ascii'), 'ASCII'); | 10 | 10 | assert.strictEqual(parseEncoding('base64'), 'BASE64'); | | 11 | +assert.strictEqual(parseEncoding('base64url'), 'BASE64URL'); | 11 | 12 | assert.strictEqual(parseEncoding('binary'), 'LATIN1'); | 12 | 13 | assert.strictEqual(parseEncoding('buffer'), 'BUFFER'); | 13 | 14 | assert.strictEqual(parseEncoding('hex'), 'HEX'); | |
|