Encoder/encoder.go

253 lines
5.2 KiB
Go

package encoder
import (
"errors"
"io"
"local/encryptor"
"os"
"path"
)
type Encoder struct {
bops []BOP
}
func New(config *Config, bops ...BOP) (*Encoder, error) {
if len(bops) != 0 {
return &Encoder{bops: bops}, nil
}
bops = []BOP{
&Zipper{},
&Salter{},
}
if config != nil {
if config.SymKey != "" {
bops = append(bops, &AES{Key: []byte(config.SymKey)})
}
if !config.SymKeyOnly {
var encr encryptor.Encryptor
if path.Base(config.KeyPath) == "env" {
pub := os.Getenv("PUB")
pri := os.Getenv("PRI")
if pub == "" || pri == "" {
return nil, errors.New("PUB and PRI cannot be empty")
}
encr = encryptor.NewEncryptor(pri, pub, false)
} else if config.KeyPath != "" {
encr = encryptor.NewEncryptor("", "", false)
priKeyPath := path.Join(config.KeyPath, "key.pri")
pubKeyPath := path.Join(config.KeyPath, "key.pub")
defer encr.ToFiles(priKeyPath, pubKeyPath)
if err := encr.FromFiles(priKeyPath, pubKeyPath); err != nil {
return nil, err
}
} else {
encr = encryptor.NewEncryptor("", "", false)
}
bops = append(bops, &asymCryptor{Encryptor: encr})
}
}
bops = append(bops, &Zipper{})
return &Encoder{
bops: bops,
}, nil
}
func (e *Encoder) Encode2(r io.Reader) (io.Reader, error) {
pipeR, pipeW := io.Pipe()
go func() {
defer pipeW.Close()
for i := 0; i < len(e.bops); i++ {
r = e.bops[i].(BOP2).Wrap2(r)
}
if _, err := io.Copy(pipeW, r); err != nil {
panic(err)
}
}()
return pipeR, nil
}
func (e *Encoder) Decode2(r io.Reader) (io.Reader, error) {
pipeR, pipeW := io.Pipe()
go func() {
defer pipeW.Close()
r = screenReader(r)
for i := len(e.bops) - 1; i >= 0; i-- {
r = e.bops[i].(BOP2).Unwrap2(r)
r = screenReader(r)
}
if _, err := io.Copy(pipeW, r); err != nil {
panic(err)
}
}()
return pipeR, nil
}
func (e *Encoder) Encode3(r io.Reader) (io.Reader, error) {
pipeR, pipeW := io.Pipe()
bopCh := make([]chan []byte, len(e.bops)+1)
inputChIndex := len(bopCh) - 1
bopCh[inputChIndex] = make(chan []byte)
//[0]=bops[0]([n+1])
//[1]=bops[1]([0])
//...
//[n]=bops[n]([n-1])
//[n+1]=firstin
for i := range e.bops {
bopCh[i] = e.bops[i].(BOP3).Wrap3(bopCh[(i-1+len(bopCh))%len(bopCh)])
}
go func() {
defer pipeW.Close()
for input := range bopCh[inputChIndex-1] {
if _, err := pipeW.Write(input); err != nil {
panic(err)
}
}
}()
go func() {
defer close(bopCh[inputChIndex])
buff := make([]byte, 64000)
for {
n, err := r.Read(buff)
if err != nil && err != io.EOF {
panic(err)
}
if n > 0 {
bopCh[inputChIndex] <- copyBSlice(buff[:n])
}
if err == io.EOF {
break
}
}
}()
return pipeR, nil
}
func (e *Encoder) Decode3(r io.Reader) (io.Reader, error) {
pipeR, pipeW := io.Pipe()
bopCh := make([]chan []byte, len(e.bops)+1)
inputChIndex := len(bopCh) - 1
bopCh[inputChIndex] = make(chan []byte)
//[0]=bops[0]([1])
//[1]=bops[1]([2])
//...
//[n]=bops[n]([n+1])
//[n+1]=firstin
for i := len(e.bops) - 1; i >= 0; i-- {
bopCh[i] = e.bops[i].(BOP3).Unwrap3(bopCh[i+1])
}
go func() {
defer pipeW.Close()
for input := range bopCh[0] {
if _, err := pipeW.Write(input); err != nil {
panic(err)
}
}
}()
go func() {
defer close(bopCh[inputChIndex])
buff := make([]byte, 64000)
for {
n, err := r.Read(buff)
if err != nil && err != io.EOF {
panic(err)
}
if n > 0 {
bopCh[inputChIndex] <- copyBSlice(buff[:n])
}
if err == io.EOF {
break
}
}
}()
return pipeR, nil
}
func (e *Encoder) Encode(payload []byte, metadata ...[]byte) ([]byte, error) {
if len(payload) == 0 {
return nil, nil
}
for i := range e.bops {
payload = e.bops[i].Wrap(payload)
if len(payload) == 0 {
return nil, errors.New("cannot encode payload")
}
}
return e.WriteMetadata(payload, metadata)
}
func (e *Encoder) Decode(payload []byte) ([]byte, error) {
metalen, err := e.metadataLength(payload)
if err != nil {
return nil, err
}
payload = payload[metalen:]
if len(payload) == 0 {
return nil, nil
}
for i := len(e.bops); i > 0; i-- {
payload = e.bops[i-1].Unwrap(payload)
if len(payload) == 0 {
return nil, errors.New("cannot decode payload")
}
}
return payload, nil
}
func (e *Encoder) WriteMetadata(payload []byte, metadata [][]byte) ([]byte, error) {
meta := []byte{byte(len(metadata))}
for i := range metadata {
meta = append(meta, byte(len(metadata[i])))
meta = append(meta, metadata[i]...)
}
payload = append(meta, payload...)
return payload, nil
}
func (e *Encoder) ReadMetadata(payload []byte) ([][]byte, error) {
metadata := [][]byte{}
if len(payload) < 2 {
return nil, nil
}
metalen := int(payload[0])
payload = payload[1:]
for i := 0; i < metalen; i++ {
if len(payload) < 1 {
return nil, nil
}
j := payload[0]
if len(payload) < 1+int(j) {
return nil, nil
}
metadata = append(metadata, payload[1:1+int(j)])
payload = payload[1+int(j):]
}
return metadata, nil
}
func (e *Encoder) metadataLength(payload []byte) (int, error) {
metadata, err := e.ReadMetadata(payload)
if err != nil {
return 0, err
}
n := 1
for i := range metadata {
n += 1 + len(metadata[i])
}
if len(payload) < n {
return 0, nil
}
return n, nil
}