package encoder import ( "errors" "io" "gogs.inhome.blapointe.com/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 }