Example #1
0
func mscfbRdr(b *siegreader.Buffer) (Reader, error) {
	m, err := mscfb.New(siegreader.ReaderFrom(b))
	if err != nil {
		return nil, err
	}
	return &mscfbReader{rdr: m}, nil
}
Example #2
0
func newGzip(b *siegreader.Buffer, path string) (decompressor, error) {
	b.Quit = make(chan struct{}) // in case a stream with a closed quit channel, make a new one
	_ = b.SizeNow()              // in case a stream, force full read
	buf, err := b.EofSlice(0, 4) // gzip stores uncompressed size in last 4 bytes of the stream
	if err != nil {
		return nil, err
	}
	sz := int64(uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24)
	g, err := gzip.NewReader(siegreader.ReaderFrom(b))
	return &gzipD{sz: sz, p: path, rdr: g}, err
}
Example #3
0
func identifyRdr(r io.Reader, ctx *context, ctxts chan *context, gf getFn) {
	s := ctx.s
	b, berr := s.Buffer(r)
	defer s.Put(b)
	ids, err := s.IdentifyBuffer(b, berr, ctx.path, ctx.mime)
	if ids == nil {
		ctx.res <- results{err, nil, nil}
		return
	}
	// calculate checksum
	var cs []byte
	if ctx.h != nil {
		var i int64
		l := ctx.h.BlockSize()
		for ; ; i += int64(l) {
			buf, _ := b.Slice(i, l)
			if buf == nil {
				break
			}
			ctx.h.Write(buf)
		}
		cs = ctx.h.Sum(nil)
	}
	// decompress if an archive format
	if !ctx.z {
		ctx.res <- results{err, cs, ids}
		return
	}
	arc := isArc(ids)
	if arc == config.None {
		ctx.res <- results{err, cs, ids}
		return
	}
	var d decompressor
	switch arc {
	case config.Zip:
		d, err = newZip(siegreader.ReaderFrom(b), ctx.path, ctx.sz)
	case config.Gzip:
		d, err = newGzip(b, ctx.path)
	case config.Tar:
		d, err = newTar(siegreader.ReaderFrom(b), ctx.path)
	case config.ARC:
		d, err = newARC(siegreader.ReaderFrom(b), ctx.path)
	case config.WARC:
		d, err = newWARC(siegreader.ReaderFrom(b), ctx.path)
	}
	if err != nil {
		ctx.res <- results{fmt.Errorf("failed to decompress, got: %v", err), cs, ids}
		return
	}
	_, dw := ctx.w.(*droidWriter)
	// send the result
	ctx.res <- results{err, cs, ids}
	// decompress and recurse
	for err = d.next(); err == nil; err = d.next() {
		if dw {
			for _, v := range d.dirs() {
				dctx := gf(v, "", "", -1)
				dctx.res <- results{nil, nil, nil}
				dctx.wg.Add(1)
				ctxts <- dctx
			}
		}
		nctx := gf(d.path(), d.mime(), d.mod(), d.size())
		nctx.wg.Add(1)
		ctxts <- nctx
		identifyRdr(d.reader(), nctx, ctxts, gf)
	}
}
Example #4
0
func (m Matcher) Identify(na string, b *siegreader.Buffer, exclude ...int) (chan core.Result, error) {
	buf, err := b.Slice(0, 8)
	if err != nil || buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
		res := make(chan core.Result)
		close(res)
		return res, nil
	}
	rcc, rrdr, err := riff.NewReader(siegreader.ReaderFrom(b))
	if err != nil {
		res := make(chan core.Result)
		close(res)
		return res, nil
	}
	// now make structures for testing
	uniqs := make(map[riff.FourCC]bool)
	res := make(chan core.Result)
	waitset := m.priorities.WaitSet(exclude...)
	// send and report if satisified
	send := func(cc riff.FourCC) bool {
		if config.Debug() {
			fmt.Fprintf(config.Out(), "riff match %s\n", string(cc[:]))
		}
		if uniqs[cc] {
			return false
		}
		uniqs[cc] = true
		for _, hit := range m.riffs[cc] {
			if waitset.Check(hit) {
				if config.Debug() {
					fmt.Fprintf(config.Out(), "sending riff match %s\n", string(cc[:]))
				}
				res <- result{hit, cc}
				if waitset.Put(hit) {
					return true
				}
			}
		}
		return false
	}
	// riff walk
	var descend func(*riff.Reader) bool
	descend = func(r *riff.Reader) bool {
		for {
			chunkID, chunkLen, chunkData, err := r.Next()
			if err != nil || send(chunkID) {
				return true
			}
			if chunkID == riff.LIST {
				listType, list, err := riff.NewListReader(chunkLen, chunkData)
				if err != nil || send(listType) {
					return true
				}
				if descend(list) {
					return true
				}
			}
		}
	}
	// go time
	go func() {
		if send(rcc) {
			close(res)
			return
		}
		descend(rrdr)
		close(res)
	}()
	return res, nil
}