github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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  		}
   163  		nn -= nn % 3
   164  		if nn > 0 {
   165  			e.enc.Encode(e.out[0:], p[0:nn])
   166  			if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
   167  				return n, e.err
   168  			}
   169  		}
   170  		n += nn
   171  		p = p[nn:]
   172  	}
   173  
   174  	// Trailing fringe.
   175  	for i := 0; i < len(p); i++ {
   176  		e.buf[i] = p[i]
   177  	}
   178  	e.nbuf = len(p)
   179  	n += len(p)
   180  	return
   181  }
   182  
   183  // Close flushes any pending output from the encoder.
   184  // It is an error to call Write after calling Close.
   185  func (e *encoder) Close() error {
   186  	// If there's anything left in the buffer, flush it out
   187  	if e.err == nil && e.nbuf > 0 {
   188  		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
   189  		e.nbuf = 0
   190  		_, e.err = e.w.Write(e.out[0:4])
   191  	}
   192  	return e.err
   193  }
   194  
   195  // NewEncoder returns a new base64 stream encoder.  Data written to
   196  // the returned writer will be encoded using enc and then written to w.
   197  // Base64 encodings operate in 4-byte blocks; when finished
   198  // writing, the caller must Close the returned encoder to flush any
   199  // partially written blocks.
   200  func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
   201  	return &encoder{enc: enc, w: w}
   202  }
   203  
   204  // EncodedLen returns the length in bytes of the base64 encoding
   205  // of an input buffer of length n.
   206  func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
   207  
   208  /*
   209   * Decoder
   210   */
   211  
   212  type CorruptInputError int64
   213  
   214  func (e CorruptInputError) Error() string {
   215  	return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
   216  }
   217  
   218  // decode is like Decode but returns an additional 'end' value, which
   219  // indicates if end-of-message padding was encountered and thus any
   220  // additional data is an error. This method assumes that src has been
   221  // stripped of all supported whitespace ('\r' and '\n').
   222  func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
   223  	olen := len(src)
   224  	for len(src) > 0 && !end {
   225  		// Decode quantum using the base64 alphabet
   226  		var dbuf [4]byte
   227  		dlen := 4
   228  
   229  		for j := 0; j < 4; {
   230  			if len(src) == 0 {
   231  				return n, false, CorruptInputError(olen - len(src) - j)
   232  			}
   233  			in := src[0]
   234  			src = src[1:]
   235  			if in == '=' && j >= 2 && len(src) < 4 {
   236  				// We've reached the end and there's padding
   237  				if len(src)+j < 4-1 {
   238  					// not enough padding
   239  					return n, false, CorruptInputError(olen)
   240  				}
   241  				if len(src) > 0 && src[0] != '=' {
   242  					// incorrect padding
   243  					return n, false, CorruptInputError(olen - len(src) - 1)
   244  				}
   245  				dlen, end = j, true
   246  				break
   247  			}
   248  			dbuf[j] = enc.decodeMap[in]
   249  			if dbuf[j] == 0xFF {
   250  				return n, false, CorruptInputError(olen - len(src) - 1)
   251  			}
   252  			j++
   253  		}
   254  
   255  		// Pack 4x 6-bit source blocks into 3 byte destination
   256  		// quantum
   257  		switch dlen {
   258  		case 4:
   259  			dst[2] = dbuf[2]<<6 | dbuf[3]
   260  			fallthrough
   261  		case 3:
   262  			dst[1] = dbuf[1]<<4 | dbuf[2]>>2
   263  			fallthrough
   264  		case 2:
   265  			dst[0] = dbuf[0]<<2 | dbuf[1]>>4
   266  		}
   267  		dst = dst[3:]
   268  		n += dlen - 1
   269  	}
   270  
   271  	return n, end, nil
   272  }
   273  
   274  // Decode decodes src using the encoding enc.  It writes at most
   275  // DecodedLen(len(src)) bytes to dst and returns the number of bytes
   276  // written.  If src contains invalid base64 data, it will return the
   277  // number of bytes successfully written and CorruptInputError.
   278  // New line characters (\r and \n) are ignored.
   279  func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
   280  	src = bytes.Map(removeNewlinesMapper, src)
   281  	n, _, err = enc.decode(dst, src)
   282  	return
   283  }
   284  
   285  // DecodeString returns the bytes represented by the base64 string s.
   286  func (enc *Encoding) DecodeString(s string) ([]byte, error) {
   287  	s = strings.Map(removeNewlinesMapper, s)
   288  	dbuf := make([]byte, enc.DecodedLen(len(s)))
   289  	n, err := enc.Decode(dbuf, []byte(s))
   290  	return dbuf[:n], err
   291  }
   292  
   293  type decoder struct {
   294  	err    error
   295  	enc    *Encoding
   296  	r      io.Reader
   297  	end    bool       // saw end of message
   298  	buf    [1024]byte // leftover input
   299  	nbuf   int
   300  	out    []byte // leftover decoded output
   301  	outbuf [1024 / 4 * 3]byte
   302  }
   303  
   304  func (d *decoder) Read(p []byte) (n int, err error) {
   305  	if d.err != nil {
   306  		return 0, d.err
   307  	}
   308  
   309  	// Use leftover decoded output from last read.
   310  	if len(d.out) > 0 {
   311  		n = copy(p, d.out)
   312  		d.out = d.out[n:]
   313  		return n, nil
   314  	}
   315  
   316  	// Read a chunk.
   317  	nn := len(p) / 3 * 4
   318  	if nn < 4 {
   319  		nn = 4
   320  	}
   321  	if nn > len(d.buf) {
   322  		nn = len(d.buf)
   323  	}
   324  	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
   325  	d.nbuf += nn
   326  	if d.err != nil || d.nbuf < 4 {
   327  		return 0, d.err
   328  	}
   329  
   330  	// Decode chunk into p, or d.out and then p if p is too small.
   331  	nr := d.nbuf / 4 * 4
   332  	nw := d.nbuf / 4 * 3
   333  	if nw > len(p) {
   334  		nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
   335  		d.out = d.outbuf[0:nw]
   336  		n = copy(p, d.out)
   337  		d.out = d.out[n:]
   338  	} else {
   339  		n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
   340  	}
   341  	d.nbuf -= nr
   342  	for i := 0; i < d.nbuf; i++ {
   343  		d.buf[i] = d.buf[i+nr]
   344  	}
   345  
   346  	if d.err == nil {
   347  		d.err = err
   348  	}
   349  	return n, d.err
   350  }
   351  
   352  type newlineFilteringReader struct {
   353  	wrapped io.Reader
   354  }
   355  
   356  func (r *newlineFilteringReader) Read(p []byte) (int, error) {
   357  	n, err := r.wrapped.Read(p)
   358  	for n > 0 {
   359  		offset := 0
   360  		for i, b := range p[0:n] {
   361  			if b != '\r' && b != '\n' {
   362  				if i != offset {
   363  					p[offset] = b
   364  				}
   365  				offset++
   366  			}
   367  		}
   368  		if offset > 0 {
   369  			return offset, err
   370  		}
   371  		// Previous buffer entirely whitespace, read again
   372  		n, err = r.wrapped.Read(p)
   373  	}
   374  	return n, err
   375  }
   376  
   377  // NewDecoder constructs a new base64 stream decoder.
   378  func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
   379  	return &decoder{enc: enc, r: &newlineFilteringReader{r}}
   380  }
   381  
   382  // DecodedLen returns the maximum length in bytes of the decoded data
   383  // corresponding to n bytes of base64-encoded data.
   384  func (enc *Encoding) DecodedLen(n int) int { return n / 4 * 3 }