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