package asar // import "b612.me/asar" import ( "encoding/binary" "errors" "io" ) var ( errMalformed = errors.New("asar: malformed archive") ) // Decode decodes the ASAR archive in ra. // // Returns the root element and nil on success. nil and an error is returned on // failure. func Decode(ra io.ReaderAt) (*Entry, error) { headerSize := uint32(0) headerStringSize := uint32(0) // [pickle object header (4 bytes) == 4] // [pickle uint32 = $header_object_size] { var buff [8]byte if n, _ := ra.ReadAt(buff[:], 0); n != 8 { return nil, errMalformed } dataSize := binary.LittleEndian.Uint32(buff[:4]) if dataSize != 4 { return nil, errMalformed } headerSize = binary.LittleEndian.Uint32(buff[4:8]) } // [pickle object header (4 bytes)] // [pickle data header (4 bytes) == $string_size] // [pickle string ($string_size bytes)] { var buff [8]byte if n, _ := ra.ReadAt(buff[:], 8); n != 8 { return nil, errMalformed } headerObjectSize := binary.LittleEndian.Uint32(buff[:4]) if headerObjectSize != headerSize-4 { return nil, errMalformed } headerStringSize = binary.LittleEndian.Uint32(buff[4:8]) } // read header string headerSection := io.NewSectionReader(ra, 8+8, int64(headerStringSize)) baseOffset := 8 + int64(headerSize) baseOffset += baseOffset % 4 // pickle objects are uint32 aligned root, err := decodeHeader(ra, headerSection, baseOffset) if err != nil { return nil, err } return root, nil }