github.com/shakinm/xlsReader@v0.9.12/cfb/header.go (about) 1 package cfb 2 3 import ( 4 "bytes" 5 "errors" 6 "github.com/shakinm/xlsReader/helpers" 7 ) 8 9 //HeaderSignature Identification signature for the compound file structure, and MUST be 10 //set to the value ... 11 var HeaderSignature = []byte{0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1} 12 13 //MajorVersion3 - Version number sign fot version 3 14 var MajorVersion3 = []byte{0x03, 0x00} 15 16 //MajorVersion4 - Version number sign fot version 4 17 var MajorVersion4 = []byte{0x04, 0x00} 18 19 //MajorVersion -Version number for breaking changes. This field MUST be set to either 20 //0x0003 (version 3) or 0x0004 (version 4). 21 var MajorVersion = [][]byte{MajorVersion3, MajorVersion4} 22 23 //ByteOrder - This field MUST be set to 0xFFFE. This field is a byte order mark for all integer 24 //fields, specifying little-endian byte order. 25 var ByteOrder = []byte{0xFE, 0xFF} 26 27 //SectorShiftForMajorVersion3 - If Major Version is 3, the Sector Shift MUST be 0x0009, specifying a sector size of 512 bytes. 28 var SectorShiftForMajorVersion3 = []byte{0x09, 0x00} 29 30 //SectorShiftForMajorVersion4 - If Major Version is 4, the Sector Shift MUST be 0x000C, specifying a sector size of 4096 bytes. 31 var SectorShiftForMajorVersion4 = []byte{0x0C, 0x00} 32 33 //MiniSectorShift - This field MUST be set to 0x0009, or 0x000c, depending on the Major 34 //Version field. This field specifies the sector size of the compound file as a power of 2. 35 var MiniSectorShift = []byte{0x06, 0x00} 36 37 //Reserved - This field MUST be set to all zeroes. 38 var Reserved = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 39 40 //NumberDirectorySectorsForMajorVersion3 - If Major Version is 3, the Number of Directory Sectors MUST be zero. 41 var NumberDirectorySectorsForMajorVersion3 = []byte{0x00, 0x00, 0x00, 0x00} 42 43 //MiniStreamCutoffSize - This integer field MUST be set to 0x00001000. This field 44 //specifies the maximum size of a user-defined data stream that is allocated from the mini FAT 45 //and mini stream, and that cutoff is 4,096 bytes. Any user-defined data stream that is greater than 46 //or equal to this cutoff size must be allocated as normal sectors from the FAT. 47 var MiniStreamCutoffSize = []byte{0x00, 0x10, 0x00, 0x00} 48 49 // Header - The Compound File Header structure 50 type Header struct { 51 HeaderSignature [8]byte 52 HeaderCLSID [16]byte 53 MinorVersion [2]byte 54 MajorVersion [2]byte 55 ByteOrder [2]byte 56 SectorShift [2]byte 57 MiniSectorShift [2]byte 58 Reserved [6]byte 59 NumberDirectorySectors [4]byte 60 NumberFATSectors [4]byte 61 FirstDirectorySectorLocation [4]byte 62 TransactionSignatureNumber [4]byte 63 MiniStreamCutoffSize [4]byte 64 FirstMiniFATSectorLocation [4]byte 65 NumberMiniFATSectors [4]byte 66 FirstDIFATSectorLocation [4]byte 67 NumberDIFATSectors [4]byte 68 DIFAT [3584]byte 69 } 70 71 func (h *Header) getDIFATEntry(i uint32) []byte { 72 return h.DIFAT[i*4:(i*4)+4] 73 } 74 75 func (h *Header) sectorSize() (size uint32) { 76 if bytes.Compare(h.MajorVersion[:], MajorVersion3) == 0 { 77 size = 512 78 } 79 if bytes.Compare(h.MajorVersion[:], MajorVersion4) == 0 { 80 size = 4096 81 } 82 83 return size 84 } 85 86 func (h *Header) validate() (err error) { // nolint: gocyclo 87 88 if bytes.Compare(h.HeaderSignature[:], HeaderSignature) != 0 { 89 return errors.New(`Identification signature for the compound file structure, and MUST be set to the value 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1`) 90 } 91 92 if !helpers.BytesInSlice(h.MajorVersion[:], MajorVersion) { 93 return errors.New(`Version number for breaking changes. This structure MUST be set to either 0x0003 (version 3) or 0x0004 (version 4)`) 94 } 95 96 if bytes.Compare(h.ByteOrder[:], ByteOrder) != 0 { 97 return errors.New(`Byte Order MUST be set to 0xFFFE. This structure is a byte order mark for all integer fields, specifying little-endian byte order`) 98 } 99 100 if bytes.Compare(h.MajorVersion[:], MajorVersion3) == 0 && bytes.Compare(h.SectorShift[:], SectorShiftForMajorVersion3) != 0 { 101 return errors.New(`If Major Version is 3, the Sector Shift MUST be 0x0009, specifying a sector size of 512 bytes`) 102 } 103 104 if bytes.Compare(h.MajorVersion[:], MajorVersion4) == 0 && bytes.Compare(h.SectorShift[:], SectorShiftForMajorVersion4) != 0 { 105 return errors.New(`If Major Version is 4, the Sector Shift MUST be 0x000C, specifying a sector size of 4,096 bytes`) 106 } 107 108 if bytes.Compare(h.MiniSectorShift[:], MiniSectorShift) != 0 { 109 return errors.New(`Mini Sector Shift MUST be set to 0x0006. This structure specifies the sector size of the Mini Stream as a power of 2. The sector size of the Mini Stream MUST be 64 bytes`) 110 } 111 112 if bytes.Compare(h.Reserved[:], Reserved) != 0 { 113 return errors.New(`Reserved MUST be set to all zeroes`) 114 } 115 116 if bytes.Compare(h.MiniStreamCutoffSize[:], MiniStreamCutoffSize) != 0 { 117 return errors.New(`Mini Stream Cutoff Size structure MUST be set to 0x00001000`) 118 } 119 120 if bytes.Compare(h.MajorVersion[:], MajorVersion3) == 0 && bytes.Compare(h.NumberDirectorySectors[:], NumberDirectorySectorsForMajorVersion3) != 0 { 121 return errors.New(`if Major Version is 3, the Number of Directory Sectors MUST be zero`) 122 } 123 124 if bytes.Compare(h.MajorVersion[:], MajorVersion4) == 0 { 125 for i := 513; i <= 4096; i++ { 126 if h.DIFAT[i] != 0x00 { 127 return errors.New(`For version 4 compound files, the header size (512 bytes) is less than the sector size (4,096 bytes), so the remaining part of the header (3,584 bytes) MUST be filled with all zeroes`) 128 } 129 } 130 131 } 132 133 return 134 } 135