github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/encoding/base64/base64.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package base64 implements base64 encoding as specified by RFC 4648. 6 package base64 7 8 import ( 9 "encoding/binary" 10 "io" 11 "strconv" 12 ) 13 14 /* 15 * Encodings 16 */ 17 18 // An Encoding is a radix 64 encoding/decoding scheme, defined by a 19 // 64-character alphabet. The most common encoding is the "base64" 20 // encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM 21 // (RFC 1421). RFC 4648 also defines an alternate encoding, which is 22 // the standard encoding with - and _ substituted for + and /. 23 type Encoding struct { 24 encode [64]byte 25 decodeMap [256]byte 26 padChar rune 27 strict bool 28 } 29 30 const ( 31 StdPadding rune = '=' // Standard padding character 32 NoPadding rune = -1 // No padding 33 ) 34 35 const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 36 const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" 37 38 // NewEncoding returns a new padded Encoding defined by the given alphabet, 39 // which must be a 64-byte string that does not contain the padding character 40 // or CR / LF ('\r', '\n'). 41 // The resulting Encoding uses the default padding character ('='), 42 // which may be changed or disabled via WithPadding. 43 func NewEncoding(encoder string) *Encoding { 44 if len(encoder) != 64 { 45 panic("encoding alphabet is not 64-bytes long") 46 } 47 for i := 0; i < len(encoder); i++ { 48 if encoder[i] == '\n' || encoder[i] == '\r' { 49 panic("encoding alphabet contains newline character") 50 } 51 } 52 53 e := new(Encoding) 54 e.padChar = StdPadding 55 copy(e.encode[:], encoder) 56 57 for i := 0; i < len(e.decodeMap); i++ { 58 e.decodeMap[i] = 0xFF 59 } 60 for i := 0; i < len(encoder); i++ { 61 e.decodeMap[encoder[i]] = byte(i) 62 } 63 return e 64 } 65 66 // WithPadding creates a new encoding identical to enc except 67 // with a specified padding character, or NoPadding to disable padding. 68 // The padding character must not be '\r' or '\n', must not 69 // be contained in the encoding's alphabet and must be a rune equal or 70 // below '\xff'. 71 func (enc Encoding) WithPadding(padding rune) *Encoding { 72 if padding == '\r' || padding == '\n' || padding > 0xff { 73 panic("invalid padding") 74 } 75 76 for i := 0; i < len(enc.encode); i++ { 77 if rune(enc.encode[i]) == padding { 78 panic("padding contained in alphabet") 79 } 80 } 81 82 enc.padChar = padding 83 return &enc 84 } 85 86 // Strict creates a new encoding identical to enc except with 87 // strict decoding enabled. In this mode, the decoder requires that 88 // trailing padding bits are zero, as described in RFC 4648 section 3.5. 89 func (enc Encoding) Strict() *Encoding { 90 enc.strict = true 91 return &enc 92 } 93 94 // StdEncoding is the standard base64 encoding, as defined in 95 // RFC 4648. 96 var StdEncoding = NewEncoding(encodeStd) 97 98 // URLEncoding is the alternate base64 encoding defined in RFC 4648. 99 // It is typically used in URLs and file names. 100 var URLEncoding = NewEncoding(encodeURL) 101 102 // RawStdEncoding is the standard raw, unpadded base64 encoding, 103 // as defined in RFC 4648 section 3.2. 104 // This is the same as StdEncoding but omits padding characters. 105 var RawStdEncoding = StdEncoding.WithPadding(NoPadding) 106 107 // RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648. 108 // It is typically used in URLs and file names. 109 // This is the same as URLEncoding but omits padding characters. 110 var RawURLEncoding = URLEncoding.WithPadding(NoPadding) 111 112 /* 113 * Encoder 114 */ 115 116 // Encode encodes src using the encoding enc, writing 117 // EncodedLen(len(src)) bytes to dst. 118 // 119 // The encoding pads the output to a multiple of 4 bytes, 120 // so Encode is not appropriate for use on individual blocks 121 // of a large data stream. Use NewEncoder() instead. 122 func (enc *Encoding) Encode(dst, src []byte) { 123 if len(src) == 0 { 124 return 125 } 126 // enc is a pointer receiver, so the use of enc.encode within the hot 127 // loop below means a nil check at every operation. Lift that nil check 128 // outside of the loop to speed up the encoder. 129 _ = enc.encode 130 131 di, si := 0, 0 132 n := (len(src) / 3) * 3 133 for si < n { 134 // Convert 3x 8bit source bytes into 4 bytes 135 val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2]) 136 137 dst[di+0] = enc.encode[val>>18&0x3F] 138 dst[di+1] = enc.encode[val>>12&0x3F] 139 dst[di+2] = enc.encode[val>>6&0x3F] 140 dst[di+3] = enc.encode[val&0x3F] 141 142 si += 3 143 di += 4 144 } 145 146 remain := len(src) - si 147 if remain == 0 { 148 return 149 } 150 // Add the remaining small block 151 val := uint(src[si+0]) << 16 152 if remain == 2 { 153 val |= uint(src[si+1]) << 8 154 } 155 156 dst[di+0] = enc.encode[val>>18&0x3F] 157 dst[di+1] = enc.encode[val>>12&0x3F] 158 159 switch remain { 160 case 2: 161 dst[di+2] = enc.encode[val>>6&0x3F] 162 if enc.padChar != NoPadding { 163 dst[di+3] = byte(enc.padChar) 164 } 165 case 1: 166 if enc.padChar != NoPadding { 167 dst[di+2] = byte(enc.padChar) 168 dst[di+3] = byte(enc.padChar) 169 } 170 } 171 } 172 173 // EncodeToString returns the base64 encoding of src. 174 func (enc *Encoding) EncodeToString(src []byte) string { 175 buf := make([]byte, enc.EncodedLen(len(src))) 176 enc.Encode(buf, src) 177 return string(buf) 178 } 179 180 type encoder struct { 181 err error 182 enc *Encoding 183 w io.Writer 184 buf [3]byte // buffered data waiting to be encoded 185 nbuf int // number of bytes in buf 186 out [1024]byte // output buffer 187 } 188 189 func (e *encoder) Write(p []byte) (n int, err error) { 190 if e.err != nil { 191 return 0, e.err 192 } 193 194 // Leading fringe. 195 if e.nbuf > 0 { 196 var i int 197 for i = 0; i < len(p) && e.nbuf < 3; i++ { 198 e.buf[e.nbuf] = p[i] 199 e.nbuf++ 200 } 201 n += i 202 p = p[i:] 203 if e.nbuf < 3 { 204 return 205 } 206 e.enc.Encode(e.out[:], e.buf[:]) 207 if _, e.err = e.w.Write(e.out[:4]); e.err != nil { 208 return n, e.err 209 } 210 e.nbuf = 0 211 } 212 213 // Large interior chunks. 214 for len(p) >= 3 { 215 nn := len(e.out) / 4 * 3 216 if nn > len(p) { 217 nn = len(p) 218 nn -= nn % 3 219 } 220 e.enc.Encode(e.out[:], p[:nn]) 221 if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil { 222 return n, e.err 223 } 224 n += nn 225 p = p[nn:] 226 } 227 228 // Trailing fringe. 229 for i := 0; i < len(p); i++ { 230 e.buf[i] = p[i] 231 } 232 e.nbuf = len(p) 233 n += len(p) 234 return 235 } 236 237 // Close flushes any pending output from the encoder. 238 // It is an error to call Write after calling Close. 239 func (e *encoder) Close() error { 240 // If there's anything left in the buffer, flush it out 241 if e.err == nil && e.nbuf > 0 { 242 e.enc.Encode(e.out[:], e.buf[:e.nbuf]) 243 _, e.err = e.w.Write(e.out[:e.enc.EncodedLen(e.nbuf)]) 244 e.nbuf = 0 245 } 246 return e.err 247 } 248 249 // NewEncoder returns a new base64 stream encoder. Data written to 250 // the returned writer will be encoded using enc and then written to w. 251 // Base64 encodings operate in 4-byte blocks; when finished 252 // writing, the caller must Close the returned encoder to flush any 253 // partially written blocks. 254 func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser { 255 return &encoder{enc: enc, w: w} 256 } 257 258 // EncodedLen returns the length in bytes of the base64 encoding 259 // of an input buffer of length n. 260 func (enc *Encoding) EncodedLen(n int) int { 261 if enc.padChar == NoPadding { 262 return (n*8 + 5) / 6 // minimum # chars at 6 bits per char 263 } 264 return (n + 2) / 3 * 4 // minimum # 4-char quanta, 3 bytes each 265 } 266 267 /* 268 * Decoder 269 */ 270 271 type CorruptInputError int64 272 273 func (e CorruptInputError) Error() string { 274 return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10) 275 } 276 277 // decodeQuantum decodes up to 4 base64 bytes. The received parameters are 278 // the destination buffer dst, the source buffer src and an index in the 279 // source buffer si. 280 // It returns the number of bytes read from src, the number of bytes written 281 // to dst, and an error, if any. 282 func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err error) { 283 // Decode quantum using the base64 alphabet 284 var dbuf [4]byte 285 dlen := 4 286 287 // Lift the nil check outside of the loop. 288 _ = enc.decodeMap 289 290 for j := 0; j < len(dbuf); j++ { 291 if len(src) == si { 292 switch { 293 case j == 0: 294 return si, 0, nil 295 case j == 1, enc.padChar != NoPadding: 296 return si, 0, CorruptInputError(si - j) 297 } 298 dlen = j 299 break 300 } 301 in := src[si] 302 si++ 303 304 out := enc.decodeMap[in] 305 if out != 0xff { 306 dbuf[j] = out 307 continue 308 } 309 310 if in == '\n' || in == '\r' { 311 j-- 312 continue 313 } 314 315 if rune(in) != enc.padChar { 316 return si, 0, CorruptInputError(si - 1) 317 } 318 319 // We've reached the end and there's padding 320 switch j { 321 case 0, 1: 322 // incorrect padding 323 return si, 0, CorruptInputError(si - 1) 324 case 2: 325 // "==" is expected, the first "=" is already consumed. 326 // skip over newlines 327 for si < len(src) && (src[si] == '\n' || src[si] == '\r') { 328 si++ 329 } 330 if si == len(src) { 331 // not enough padding 332 return si, 0, CorruptInputError(len(src)) 333 } 334 if rune(src[si]) != enc.padChar { 335 // incorrect padding 336 return si, 0, CorruptInputError(si - 1) 337 } 338 339 si++ 340 } 341 342 // skip over newlines 343 for si < len(src) && (src[si] == '\n' || src[si] == '\r') { 344 si++ 345 } 346 if si < len(src) { 347 // trailing garbage 348 err = CorruptInputError(si) 349 } 350 dlen = j 351 break 352 } 353 354 // Convert 4x 6bit source bytes into 3 bytes 355 val := uint(dbuf[0])<<18 | uint(dbuf[1])<<12 | uint(dbuf[2])<<6 | uint(dbuf[3]) 356 dbuf[2], dbuf[1], dbuf[0] = byte(val>>0), byte(val>>8), byte(val>>16) 357 switch dlen { 358 case 4: 359 dst[2] = dbuf[2] 360 dbuf[2] = 0 361 fallthrough 362 case 3: 363 dst[1] = dbuf[1] 364 if enc.strict && dbuf[2] != 0 { 365 return si, 0, CorruptInputError(si - 1) 366 } 367 dbuf[1] = 0 368 fallthrough 369 case 2: 370 dst[0] = dbuf[0] 371 if enc.strict && (dbuf[1] != 0 || dbuf[2] != 0) { 372 return si, 0, CorruptInputError(si - 2) 373 } 374 } 375 376 return si, dlen - 1, err 377 } 378 379 // DecodeString returns the bytes represented by the base64 string s. 380 func (enc *Encoding) DecodeString(s string) ([]byte, error) { 381 dbuf := make([]byte, enc.DecodedLen(len(s))) 382 n, err := enc.Decode(dbuf, []byte(s)) 383 return dbuf[:n], err 384 } 385 386 type decoder struct { 387 err error 388 readErr error // error from r.Read 389 enc *Encoding 390 r io.Reader 391 buf [1024]byte // leftover input 392 nbuf int 393 out []byte // leftover decoded output 394 outbuf [1024 / 4 * 3]byte 395 } 396 397 func (d *decoder) Read(p []byte) (n int, err error) { 398 // Use leftover decoded output from last read. 399 if len(d.out) > 0 { 400 n = copy(p, d.out) 401 d.out = d.out[n:] 402 return n, nil 403 } 404 405 if d.err != nil { 406 return 0, d.err 407 } 408 409 // This code assumes that d.r strips supported whitespace ('\r' and '\n'). 410 411 // Refill buffer. 412 for d.nbuf < 4 && d.readErr == nil { 413 nn := len(p) / 3 * 4 414 if nn < 4 { 415 nn = 4 416 } 417 if nn > len(d.buf) { 418 nn = len(d.buf) 419 } 420 nn, d.readErr = d.r.Read(d.buf[d.nbuf:nn]) 421 d.nbuf += nn 422 } 423 424 if d.nbuf < 4 { 425 if d.enc.padChar == NoPadding && d.nbuf > 0 { 426 // Decode final fragment, without padding. 427 var nw int 428 nw, d.err = d.enc.Decode(d.outbuf[:], d.buf[:d.nbuf]) 429 d.nbuf = 0 430 d.out = d.outbuf[:nw] 431 n = copy(p, d.out) 432 d.out = d.out[n:] 433 if n > 0 || len(p) == 0 && len(d.out) > 0 { 434 return n, nil 435 } 436 if d.err != nil { 437 return 0, d.err 438 } 439 } 440 d.err = d.readErr 441 if d.err == io.EOF && d.nbuf > 0 { 442 d.err = io.ErrUnexpectedEOF 443 } 444 return 0, d.err 445 } 446 447 // Decode chunk into p, or d.out and then p if p is too small. 448 nr := d.nbuf / 4 * 4 449 nw := d.nbuf / 4 * 3 450 if nw > len(p) { 451 nw, d.err = d.enc.Decode(d.outbuf[:], d.buf[:nr]) 452 d.out = d.outbuf[:nw] 453 n = copy(p, d.out) 454 d.out = d.out[n:] 455 } else { 456 n, d.err = d.enc.Decode(p, d.buf[:nr]) 457 } 458 d.nbuf -= nr 459 copy(d.buf[:d.nbuf], d.buf[nr:]) 460 return n, d.err 461 } 462 463 // Decode decodes src using the encoding enc. It writes at most 464 // DecodedLen(len(src)) bytes to dst and returns the number of bytes 465 // written. If src contains invalid base64 data, it will return the 466 // number of bytes successfully written and CorruptInputError. 467 // New line characters (\r and \n) are ignored. 468 func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { 469 if len(src) == 0 { 470 return 0, nil 471 } 472 473 // Lift the nil check outside of the loop. enc.decodeMap is directly 474 // used later in this function, to let the compiler know that the 475 // receiver can't be nil. 476 _ = enc.decodeMap 477 478 si := 0 479 for strconv.IntSize >= 64 && len(src)-si >= 8 && len(dst)-n >= 8 { 480 if dn, ok := assemble64( 481 enc.decodeMap[src[si+0]], 482 enc.decodeMap[src[si+1]], 483 enc.decodeMap[src[si+2]], 484 enc.decodeMap[src[si+3]], 485 enc.decodeMap[src[si+4]], 486 enc.decodeMap[src[si+5]], 487 enc.decodeMap[src[si+6]], 488 enc.decodeMap[src[si+7]], 489 ); ok { 490 binary.BigEndian.PutUint64(dst[n:], dn) 491 n += 6 492 si += 8 493 } else { 494 var ninc int 495 si, ninc, err = enc.decodeQuantum(dst[n:], src, si) 496 n += ninc 497 if err != nil { 498 return n, err 499 } 500 } 501 } 502 503 for len(src)-si >= 4 && len(dst)-n >= 4 { 504 if dn, ok := assemble32( 505 enc.decodeMap[src[si+0]], 506 enc.decodeMap[src[si+1]], 507 enc.decodeMap[src[si+2]], 508 enc.decodeMap[src[si+3]], 509 ); ok { 510 binary.BigEndian.PutUint32(dst[n:], dn) 511 n += 3 512 si += 4 513 } else { 514 var ninc int 515 si, ninc, err = enc.decodeQuantum(dst[n:], src, si) 516 n += ninc 517 if err != nil { 518 return n, err 519 } 520 } 521 } 522 523 for si < len(src) { 524 var ninc int 525 si, ninc, err = enc.decodeQuantum(dst[n:], src, si) 526 n += ninc 527 if err != nil { 528 return n, err 529 } 530 } 531 return n, err 532 } 533 534 // assemble32 assembles 4 base64 digits into 3 bytes. 535 // Each digit comes from the decode map, and will be 0xff 536 // if it came from an invalid character. 537 func assemble32(n1, n2, n3, n4 byte) (dn uint32, ok bool) { 538 // Check that all the digits are valid. If any of them was 0xff, their 539 // bitwise OR will be 0xff. 540 if n1|n2|n3|n4 == 0xff { 541 return 0, false 542 } 543 return uint32(n1)<<26 | 544 uint32(n2)<<20 | 545 uint32(n3)<<14 | 546 uint32(n4)<<8, 547 true 548 } 549 550 // assemble64 assembles 8 base64 digits into 6 bytes. 551 // Each digit comes from the decode map, and will be 0xff 552 // if it came from an invalid character. 553 func assemble64(n1, n2, n3, n4, n5, n6, n7, n8 byte) (dn uint64, ok bool) { 554 // Check that all the digits are valid. If any of them was 0xff, their 555 // bitwise OR will be 0xff. 556 if n1|n2|n3|n4|n5|n6|n7|n8 == 0xff { 557 return 0, false 558 } 559 return uint64(n1)<<58 | 560 uint64(n2)<<52 | 561 uint64(n3)<<46 | 562 uint64(n4)<<40 | 563 uint64(n5)<<34 | 564 uint64(n6)<<28 | 565 uint64(n7)<<22 | 566 uint64(n8)<<16, 567 true 568 } 569 570 type newlineFilteringReader struct { 571 wrapped io.Reader 572 } 573 574 func (r *newlineFilteringReader) Read(p []byte) (int, error) { 575 n, err := r.wrapped.Read(p) 576 for n > 0 { 577 offset := 0 578 for i, b := range p[:n] { 579 if b != '\r' && b != '\n' { 580 if i != offset { 581 p[offset] = b 582 } 583 offset++ 584 } 585 } 586 if offset > 0 { 587 return offset, err 588 } 589 // Previous buffer entirely whitespace, read again 590 n, err = r.wrapped.Read(p) 591 } 592 return n, err 593 } 594 595 // NewDecoder constructs a new base64 stream decoder. 596 func NewDecoder(enc *Encoding, r io.Reader) io.Reader { 597 return &decoder{enc: enc, r: &newlineFilteringReader{r}} 598 } 599 600 // DecodedLen returns the maximum length in bytes of the decoded data 601 // corresponding to n bytes of base64-encoded data. 602 func (enc *Encoding) DecodedLen(n int) int { 603 if enc.padChar == NoPadding { 604 // Unpadded data may end with partial block of 2-3 characters. 605 return n * 6 / 8 606 } 607 // Padded base64 should always be a multiple of 4 characters in length. 608 return n / 4 * 3 609 }