* Dump: Use mholt/archive/v3 to support tar including many compressions Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Allow dump output to stdout Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Fixed bug present since #6677 where SessionConfig.Provider is never "file" Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never pack RepoRootPath, LFS.ContentPath and LogRootPath when they are below AppDataPath Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: also dump LFS (fixes #10058) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never dump CustomPath if CustomPath is a subdir of or equal to AppDataPath (fixes #10365) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Use log.Info instead of fmt.Fprintf Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * import ordering * make fmt Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Matti R <matti@mdranta.net>
		
			
				
	
	
		
			127 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| package rardecode
 | |
| 
 | |
| import (
 | |
| 	"crypto/aes"
 | |
| 	"crypto/cipher"
 | |
| 	"io"
 | |
| )
 | |
| 
 | |
| // cipherBlockReader implements Block Mode decryption of an io.Reader object.
 | |
| type cipherBlockReader struct {
 | |
| 	r      io.Reader
 | |
| 	mode   cipher.BlockMode
 | |
| 	inbuf  []byte // input buffer for partial data block
 | |
| 	outbuf []byte // output buffer used when output slice < block size
 | |
| 	n      int    // bytes read from outbuf
 | |
| 	err    error
 | |
| }
 | |
| 
 | |
| // read reads and decrypts one or more input blocks into p.
 | |
| // len(p) must be >= cipher block size.
 | |
| func (cr *cipherBlockReader) read(p []byte) (n int, err error) {
 | |
| 	bs := cr.mode.BlockSize()
 | |
| 	// round p down to a multiple of the block size
 | |
| 	l := len(p) - len(p)%bs
 | |
| 	p = p[:l]
 | |
| 
 | |
| 	l = len(cr.inbuf)
 | |
| 	if l > 0 {
 | |
| 		// copy any buffered input into p
 | |
| 		copy(p, cr.inbuf)
 | |
| 		cr.inbuf = cr.inbuf[:0]
 | |
| 	}
 | |
| 	// read data for at least one block
 | |
| 	n, err = io.ReadAtLeast(cr.r, p[l:], bs-l)
 | |
| 	n += l
 | |
| 	p = p[:n]
 | |
| 
 | |
| 	l = n % bs
 | |
| 	// check if p is a multiple of the cipher block size
 | |
| 	if l > 0 {
 | |
| 		n -= l
 | |
| 		// save trailing partial block to process later
 | |
| 		cr.inbuf = append(cr.inbuf, p[n:]...)
 | |
| 		p = p[:n]
 | |
| 	}
 | |
| 
 | |
| 	if err != nil {
 | |
| 		if err == io.ErrUnexpectedEOF || err == io.ErrShortBuffer {
 | |
| 			// ignore trailing bytes < block size length
 | |
| 			err = io.EOF
 | |
| 		}
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	cr.mode.CryptBlocks(p, p) // decrypt block(s)
 | |
| 	return n, nil
 | |
| }
 | |
| 
 | |
| // Read reads and decrypts data into p.
 | |
| // If the input is not a multiple of the cipher block size,
 | |
| // the trailing bytes will be ignored.
 | |
| func (cr *cipherBlockReader) Read(p []byte) (n int, err error) {
 | |
| 	for {
 | |
| 		if cr.n < len(cr.outbuf) {
 | |
| 			// return buffered output
 | |
| 			n = copy(p, cr.outbuf[cr.n:])
 | |
| 			cr.n += n
 | |
| 			return n, nil
 | |
| 		}
 | |
| 		if cr.err != nil {
 | |
| 			err = cr.err
 | |
| 			cr.err = nil
 | |
| 			return 0, err
 | |
| 		}
 | |
| 		if len(p) >= cap(cr.outbuf) {
 | |
| 			break
 | |
| 		}
 | |
| 		// p is not large enough to process a block, use outbuf instead
 | |
| 		n, cr.err = cr.read(cr.outbuf[:cap(cr.outbuf)])
 | |
| 		cr.outbuf = cr.outbuf[:n]
 | |
| 		cr.n = 0
 | |
| 	}
 | |
| 	// read blocks into p
 | |
| 	return cr.read(p)
 | |
| }
 | |
| 
 | |
| // ReadByte returns the next decrypted byte.
 | |
| func (cr *cipherBlockReader) ReadByte() (byte, error) {
 | |
| 	for {
 | |
| 		if cr.n < len(cr.outbuf) {
 | |
| 			c := cr.outbuf[cr.n]
 | |
| 			cr.n++
 | |
| 			return c, nil
 | |
| 		}
 | |
| 		if cr.err != nil {
 | |
| 			err := cr.err
 | |
| 			cr.err = nil
 | |
| 			return 0, err
 | |
| 		}
 | |
| 		// refill outbuf
 | |
| 		var n int
 | |
| 		n, cr.err = cr.read(cr.outbuf[:cap(cr.outbuf)])
 | |
| 		cr.outbuf = cr.outbuf[:n]
 | |
| 		cr.n = 0
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // newCipherBlockReader returns a cipherBlockReader that decrypts the given io.Reader using
 | |
| // the provided block mode cipher.
 | |
| func newCipherBlockReader(r io.Reader, mode cipher.BlockMode) *cipherBlockReader {
 | |
| 	cr := &cipherBlockReader{r: r, mode: mode}
 | |
| 	cr.outbuf = make([]byte, 0, mode.BlockSize())
 | |
| 	cr.inbuf = make([]byte, 0, mode.BlockSize())
 | |
| 	return cr
 | |
| }
 | |
| 
 | |
| // newAesDecryptReader returns a cipherBlockReader that decrypts input from a given io.Reader using AES.
 | |
| // It will panic if the provided key is invalid.
 | |
| func newAesDecryptReader(r io.Reader, key, iv []byte) *cipherBlockReader {
 | |
| 	block, err := aes.NewCipher(key)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	mode := cipher.NewCBCDecrypter(block, iv)
 | |
| 
 | |
| 	return newCipherBlockReader(r, mode)
 | |
| }
 |