github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/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  	"bytes"
    10  	"io"
    11  	"strconv"
    12  	"strings"
    13  )
    14  
    15  /*
    16   * Encodings
    17   */
    18  
    19  // An Encoding is a radix 64 encoding/decoding scheme, defined by a
    20  // 64-character alphabet.  The most common encoding is the "base64"
    21  // encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
    22  // (RFC 1421).  RFC 4648 also defines an alternate encoding, which is
    23  // the standard encoding with - and _ substituted for + and /.
    24  type Encoding struct {
    25  	encode    string
    26  	decodeMap [256]byte
    27  }
    28  
    29  const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    30  const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
    31  
    32  // NewEncoding returns a new Encoding defined by the given alphabet,
    33  // which must be a 64-byte string.
    34  func NewEncoding(encoder string) *Encoding {
    35  	e := new(Encoding)
    36  	e.encode = encoder
    37  	for i := 0; i < len(e.decodeMap); i++ {
    38  		e.decodeMap[i] = 0xFF
    39  	}
    40  	for i := 0; i < len(encoder); i++ {
    41  		e.decodeMap[encoder[i]] = byte(i)
    42  	}
    43  	return e
    44  }
    45  
    46  // StdEncoding is the standard base64 encoding, as defined in
    47  // RFC 4648.
    48  var StdEncoding = NewEncoding(encodeStd)
    49  
    50  // URLEncoding is the alternate base64 encoding defined in RFC 4648.
    51  // It is typically used in URLs and file names.
    52  var URLEncoding = NewEncoding(encodeURL)
    53  
    54  var removeNewlinesMapper = func(r rune) rune {
    55  	if r == '\r' || r == '\n' {
    56  		return -1
    57  	}
    58  	return r
    59  }
    60  
    61  /*
    62   * Encoder
    63   */
    64  
    65  // Encode encodes src using the encoding enc, writing
    66  // EncodedLen(len(src)) bytes to dst.
    67  //
    68  // The encoding pads the output to a multiple of 4 bytes,
    69  // so Encode is not appropriate for use on individual blocks
    70  // of a large data stream.  Use NewEncoder() instead.
    71  func (enc *Encoding) Encode(dst, src []byte) {
    72  	if len(src) == 0 {
    73  		return
    74  	}
    75  
    76  	for len(src) > 0 {
    77  		var b0, b1, b2, b3 byte
    78  
    79  		// Unpack 4x 6-bit source blocks into a 4 byte
    80  		// destination quantum
    81  		switch len(src) {
    82  		default:
    83  			b3 = src[2] & 0x3F
    84  			b2 = src[2] >> 6
    85  			fallthrough
    86  		case 2:
    87  			b2 |= (src[1] << 2) & 0x3F
    88  			b1 = src[1] >> 4
    89  			fallthrough
    90  		case 1:
    91  			b1 |= (src[0] << 4) & 0x3F
    92  			b0 = src[0] >> 2
    93  		}
    94  
    95  		// Encode 6-bit blocks using the base64 alphabet
    96  		dst[0] = enc.encode[b0]
    97  		dst[1] = enc.encode[b1]
    98  		dst[2] = enc.encode[b2]
    99  		dst[3] = enc.encode[b3]
   100  
   101  		// Pad the final quantum
   102  		if len(src) < 3 {
   103  			dst[3] = '='
   104  			if len(src) < 2 {
   105  				dst[2] = '='
   106  			}
   107  			break
   108  		}
   109  
   110  		src = src[3:]
   111  		dst = dst[4:]
   112  	}
   113  }
   114  
   115  // EncodeToString returns the base64 encoding of src.
   116  func (enc *Encoding) EncodeToString(src []byte) string {
   117  	buf := make([]byte, enc.EncodedLen(len(src)))
   118  	enc.Encode(buf, src)
   119  	return string(buf)
   120  }
   121  
   122  type encoder struct {
   123  	err  error
   124  	enc  *Encoding
   125  	w    io.Writer
   126  	buf  [3]byte    // buffered data waiting to be encoded
   127  	nbuf int        // number of bytes in buf
   128  	out  [1024]byte // output buffer
   129  }
   130  
   131  func (e *encoder) Write(p []byte) (n int, err error) {
   132  	if e.err != nil {
   133  		return 0, e.err
   134  	}
   135  
   136  	// Leading fringe.
   137  	if e.nbuf > 0 {
   138  		var i int
   139  		for i = 0; i < len(p) && e.nbuf < 3; i++ {
   140  			e.buf[e.nbuf] = p[i]
   141  			e.nbuf++
   142  		}
   143  		n += i
   144  		p = p[i:]
   145  		if e.nbuf < 3 {
   146  			return
   147  		}
   148  		e.enc.Encode(e.out[0:], e.buf[0:])
   149  		if _, e.err = e.w.Write(e.out[0:4]); e.err != nil {
   150  			return n, e.err
   151  		}
   152  		e.nbuf = 0
   153  	}
   154  
   155  	// Large interior chunks.
   156  	for len(p) >= 3 {
   157  		nn := len(e.out) / 4 * 3
   158  		if nn > len(p) {
   159  			nn = len(p)
   160  			nn -= nn % 3
   161  		}
   162  		e.enc.Encode(e.out[0:], p[0:nn])
   163  		if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
   164  			return n, e.err
   165  		}
   166  		n += nn
   167  		p = p[nn:]
   168  	}
   169  
   170  	// Trailing fringe.
   171  	for i := 0; i < len(p); i++ {
   172  		e.buf[i] = p[i]
   173  	}
   174  	e.nbuf = len(p)
   175  	n += len(p)
   176  	return
   177  }
   178  
   179  // Close flushes any pending output from the encoder.
   180  // It is an error to call Write after calling Close.
   181  func (e *encoder) Close() error {
   182  	// If there's anything left in the buffer, flush it out
   183  	if e.err == nil && e.nbuf > 0 {
   184  		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
   185  		e.nbuf = 0
   186  		_, e.err = e.w.Write(e.out[0:4])
   187  	}
   188  	return e.err
   189  }
   190  
   191  // NewEncoder returns a new base64 stream encoder.  Data written to
   192  // the returned writer will be encoded using enc and then written to w.
   193  // Base64 encodings operate in 4-byte blocks; when finished
   194  // writing, the caller must Close the returned encoder to flush any
   195  // partially written blocks.
   196  func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
   197  	return &encoder{enc: enc, w: w}
   198  }
   199  
   200  // EncodedLen returns the length in bytes of the base64 encoding
   201  // of an input buffer of length n.
   202  func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
   203  
   204  /*
   205   * Decoder
   206   */
   207  
   208  type CorruptInputError int64
   209  
   210  func (e CorruptInputError) Error() string {
   211  	return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
   212  }
   213  
   214  // decode is like Decode but returns an additional 'end' value, which
   215  // indicates if end-of-message padding was encountered and thus any
   216  // additional data is an error. This method assumes that src has been
   217  // stripped of all supported whitespace ('\r' and '\n').
   218  func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
   219  	olen := len(src)
   220  	for len(src) > 0 && !end {
   221  		// Decode quantum using the base64 alphabet
   222  		var dbuf [4]byte
   223  		dlen := 4
   224  
   225  		for j := range dbuf {
   226  			if len(src) == 0 {
   227  				return n, false, CorruptInputError(olen - len(src) - j)
   228  			}
   229  			in := src[0]
   230  			src = src[1:]
   231  			if in == '=' {
   232  				// We've reached the end and there's padding
   233  				switch j {
   234  				case 0, 1:
   235  					// incorrect padding
   236  					return n, false, CorruptInputError(olen - len(src) - 1)
   237  				case 2:
   238  					// "==" is expected, the first "=" is already consumed.
   239  					if len(src) == 0 {
   240  						// not enough padding
   241  						return n, false, CorruptInputError(olen)
   242  					}
   243  					if src[0] != '=' {
   244  						// incorrect padding
   245  						return n, false, CorruptInputError(olen - len(src) - 1)
   246  					}
   247  					src = src[1:]
   248  				}
   249  				if len(src) > 0 {
   250  					// trailing garbage
   251  					err = CorruptInputError(olen - len(src))
   252  				}
   253  				dlen, end = j, true
   254  				break
   255  			}
   256  			dbuf[j] = enc.decodeMap[in]
   257  			if dbuf[j] == 0xFF {
   258  				return n, false, CorruptInputError(olen - len(src) - 1)
   259  			}
   260  		}
   261  
   262  		// Pack 4x 6-bit source blocks into 3 byte destination
   263  		// quantum
   264  		switch dlen {
   265  		case 4:
   266  			dst[2] = dbuf[2]<<6 | dbuf[3]
   267  			fallthrough
   268  		case 3:
   269  			dst[1] = dbuf[1]<<4 | dbuf[2]>>2
   270  			fallthrough
   271  		case 2:
   272  			dst[0] = dbuf[0]<<2 | dbuf[1]>>4
   273  		}
   274  		dst = dst[3:]
   275  		n += dlen - 1
   276  	}
   277  
   278  	return n, end, err
   279  }
   280  
   281  // Decode decodes src using the encoding enc.  It writes at most
   282  // DecodedLen(len(src)) bytes to dst and returns the number of bytes
   283  // written.  If src contains invalid base64 data, it will return the
   284  // number of bytes successfully written and CorruptInputError.
   285  // New line characters (\r and \n) are ignored.
   286  func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
   287  	src = bytes.Map(removeNewlinesMapper, src)
   288  	n, _, err = enc.decode(dst, src)
   289  	return
   290  }
   291  
   292  // DecodeString returns the bytes represented by the base64 string s.
   293  func (enc *Encoding) DecodeString(s string) ([]byte, error) {
   294  	s = strings.Map(removeNewlinesMapper, s)
   295  	dbuf := make([]byte, enc.DecodedLen(len(s)))
   296  	n, _, err := enc.decode(dbuf, []byte(s))
   297  	return dbuf[:n], err
   298  }
   299  
   300  type decoder struct {
   301  	err    error
   302  	enc    *Encoding
   303  	r      io.Reader
   304  	end    bool       // saw end of message
   305  	buf    [1024]byte // leftover input
   306  	nbuf   int
   307  	out    []byte // leftover decoded output
   308  	outbuf [1024 / 4 * 3]byte
   309  }
   310  
   311  func (d *decoder) Read(p []byte) (n int, err error) {
   312  	if d.err != nil {
   313  		return 0, d.err
   314  	}
   315  
   316  	// Use leftover decoded output from last read.
   317  	if len(d.out) > 0 {
   318  		n = copy(p, d.out)
   319  		d.out = d.out[n:]
   320  		return n, nil
   321  	}
   322  
   323  	// Read a chunk.
   324  	nn := len(p) / 3 * 4
   325  	if nn < 4 {
   326  		nn = 4
   327  	}
   328  	if nn > len(d.buf) {
   329  		nn = len(d.buf)
   330  	}
   331  	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
   332  	d.nbuf += nn
   333  	if d.err != nil || d.nbuf < 4 {
   334  		return 0, d.err
   335  	}
   336  
   337  	// Decode chunk into p, or d.out and then p if p is too small.
   338  	nr := d.nbuf / 4 * 4
   339  	nw := d.nbuf / 4 * 3
   340  	if nw > len(p) {
   341  		nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
   342  		d.out = d.outbuf[0:nw]
   343  		n = copy(p, d.out)
   344  		d.out = d.out[n:]
   345  	} else {
   346  		n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
   347  	}
   348  	d.nbuf -= nr
   349  	for i := 0; i < d.nbuf; i++ {
   350  		d.buf[i] = d.buf[i+nr]
   351  	}
   352  
   353  	if d.err == nil {
   354  		d.err = err
   355  	}
   356  	return n, d.err
   357  }
   358  
   359  type newlineFilteringReader struct {
   360  	wrapped io.Reader
   361  }
   362  
   363  func (r *newlineFilteringReader) Read(p []byte) (int, error) {
   364  	n, err := r.wrapped.Read(p)
   365  	for n > 0 {
   366  		offset := 0
   367  		for i, b := range p[0:n] {
   368  			if b != '\r' && b != '\n' {
   369  				if i != offset {
   370  					p[offset] = b
   371  				}
   372  				offset++
   373  			}
   374  		}
   375  		if offset > 0 {
   376  			return offset, err
   377  		}
   378  		// Previous buffer entirely whitespace, read again
   379  		n, err = r.wrapped.Read(p)
   380  	}
   381  	return n, err
   382  }
   383  
   384  // NewDecoder constructs a new base64 stream decoder.
   385  func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
   386  	return &decoder{enc: enc, r: &newlineFilteringReader{r}}
   387  }
   388  
   389  // DecodedLen returns the maximum length in bytes of the decoded data
   390  // corresponding to n bytes of base64-encoded data.
   391  func (enc *Encoding) DecodedLen(n int) int { return n / 4 * 3 }