package mfer import ( "bytes" "compress/gzip" "errors" "io" "git.eeqj.de/sneak/mfer/internal/bork" "git.eeqj.de/sneak/mfer/internal/log" "google.golang.org/protobuf/proto" ) func (m *manifest) validateProtoOuter() error { if m.pbOuter.Version != MFFileOuter_VERSION_ONE { return errors.New("unknown version") } if m.pbOuter.CompressionType != MFFileOuter_COMPRESSION_GZIP { return errors.New("unknown compression type") } bb := bytes.NewBuffer(m.pbOuter.InnerMessage) gzr, err := gzip.NewReader(bb) if err != nil { return err } dat, err := io.ReadAll(gzr) defer gzr.Close() if err != nil { return err } isize := len(dat) if int64(isize) != m.pbOuter.Size { log.Debugf("truncated data, got %d expected %d", isize, m.pbOuter.Size) return bork.ErrFileTruncated } log.Debugf("inner data size is %d", isize) log.Dump(dat) log.Dump(m.pbOuter.Sha256) return nil } func validateMagic(dat []byte) bool { ml := len([]byte(MAGIC)) if len(dat) < ml { return false } got := dat[0:ml] expected := []byte(MAGIC) return bytes.Equal(got, expected) } func NewFromProto(input io.Reader) (*manifest, error) { m := New() dat, err := io.ReadAll(input) if err != nil { return nil, err } if !validateMagic(dat) { return nil, errors.New("invalid file format") } // remove magic bytes prefix: ml := len([]byte(MAGIC)) bb := bytes.NewBuffer(dat[ml:]) dat = bb.Bytes() log.Dump(dat) // deserialize: m.pbOuter = new(MFFileOuter) err = proto.Unmarshal(dat, m.pbOuter) if err != nil { return nil, err } ve := m.validateProtoOuter() if ve != nil { return nil, ve } // FIXME TODO deserialize inner return m, nil }