...

Source file src/github.com/gabriel-vasile/mimetype/internal/magic/zip.go

Documentation: github.com/gabriel-vasile/mimetype/internal/magic

     1  package magic
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"strings"
     7  )
     8  
     9  var (
    10  	// Odt matches an OpenDocument Text file.
    11  	Odt = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text"), 30)
    12  	// Ott matches an OpenDocument Text Template file.
    13  	Ott = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text-template"), 30)
    14  	// Ods matches an OpenDocument Spreadsheet file.
    15  	Ods = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet"), 30)
    16  	// Ots matches an OpenDocument Spreadsheet Template file.
    17  	Ots = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"), 30)
    18  	// Odp matches an OpenDocument Presentation file.
    19  	Odp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation"), 30)
    20  	// Otp matches an OpenDocument Presentation Template file.
    21  	Otp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation-template"), 30)
    22  	// Odg matches an OpenDocument Drawing file.
    23  	Odg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics"), 30)
    24  	// Otg matches an OpenDocument Drawing Template file.
    25  	Otg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics-template"), 30)
    26  	// Odf matches an OpenDocument Formula file.
    27  	Odf = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.formula"), 30)
    28  	// Odc matches an OpenDocument Chart file.
    29  	Odc = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.chart"), 30)
    30  	// Epub matches an EPUB file.
    31  	Epub = offset([]byte("mimetypeapplication/epub+zip"), 30)
    32  	// Sxc matches an OpenOffice Spreadsheet file.
    33  	Sxc = offset([]byte("mimetypeapplication/vnd.sun.xml.calc"), 30)
    34  )
    35  
    36  // Zip matches a zip archive.
    37  func Zip(raw []byte, limit uint32) bool {
    38  	return len(raw) > 3 &&
    39  		raw[0] == 0x50 && raw[1] == 0x4B &&
    40  		(raw[2] == 0x3 || raw[2] == 0x5 || raw[2] == 0x7) &&
    41  		(raw[3] == 0x4 || raw[3] == 0x6 || raw[3] == 0x8)
    42  }
    43  
    44  // Jar matches a Java archive file.
    45  func Jar(raw []byte, limit uint32) bool {
    46  	return zipContains(raw, "META-INF/MANIFEST.MF")
    47  }
    48  
    49  // zipTokenizer holds the source zip file and scanned index.
    50  type zipTokenizer struct {
    51  	in []byte
    52  	i  int // current index
    53  }
    54  
    55  // next returns the next file name from the zip headers.
    56  // https://web.archive.org/web/20191129114319/https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
    57  func (t *zipTokenizer) next() (fileName string) {
    58  	if t.i > len(t.in) {
    59  		return
    60  	}
    61  	in := t.in[t.i:]
    62  	// pkSig is the signature of the zip local file header.
    63  	pkSig := []byte("PK\003\004")
    64  	pkIndex := bytes.Index(in, pkSig)
    65  	// 30 is the offset of the file name in the header.
    66  	fNameOffset := pkIndex + 30
    67  	// end if signature not found or file name offset outside of file.
    68  	if pkIndex == -1 || fNameOffset > len(in) {
    69  		return
    70  	}
    71  
    72  	fNameLen := int(binary.LittleEndian.Uint16(in[pkIndex+26 : pkIndex+28]))
    73  	if fNameLen <= 0 || fNameOffset+fNameLen > len(in) {
    74  		return
    75  	}
    76  	t.i += fNameOffset + fNameLen
    77  	return string(in[fNameOffset : fNameOffset+fNameLen])
    78  }
    79  
    80  // zipContains returns true if the zip file headers from in contain any of the paths.
    81  func zipContains(in []byte, paths ...string) bool {
    82  	t := zipTokenizer{in: in}
    83  	for i, tok := 0, t.next(); tok != ""; i, tok = i+1, t.next() {
    84  		for p := range paths {
    85  			if strings.HasPrefix(tok, paths[p]) {
    86  				return true
    87  			}
    88  		}
    89  	}
    90  
    91  	return false
    92  }
    93  

View as plain text