You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

174 lines
5.1 KiB

/*
* GodoOS - A lightweight cloud desktop
* Copyright (C) 2024 https://godoos.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package doc
import (
"encoding/binary"
"errors"
"github.com/richardlehane/mscfb"
)
var (
errFibInvalid = errors.New("file information block validation failed")
)
type fib struct {
base fibBase
csw int
fibRgW fibRgW
cslw int
fibRgLw fibRgLw
cbRgFcLcb int
fibRgFcLcb fibRgFcLcb
}
type fibBase struct {
fWhichTblStm int
}
type fibRgW struct {
}
type fibRgLw struct {
ccpText int
ccpFtn int
ccpHdd int
ccpMcr int
ccpAtn int
ccpEdn int
ccpTxbx int
ccpHdrTxbx int
cpLength int
}
type fibRgFcLcb struct {
fcPlcfFldMom int
lcbPlcfFldMom int
fcPlcfFldHdr int
lcbPlcfFldHdr int
fcPlcfFldFtn int
lcbPlcfFldFtn int
fcPlcfFldAtn int
lcbPlcfFldAtn int
fcClx int
lcbClx int
}
// parse File Information Block (section 2.5.1)
func getFib(wordDoc *mscfb.File) (*fib, error) {
if wordDoc == nil {
return nil, errDocEmpty
}
b := make([]byte, 898) // get FIB block up to FibRgFcLcb97
_, err := wordDoc.ReadAt(b, 0)
if err != nil {
return nil, err
}
fibBase := getFibBase(b[0:32])
fibRgW, csw, err := getFibRgW(b, 32)
if err != nil {
return nil, err
}
fibRgLw, cslw, err := getFibRgLw(b, 34+csw)
if err != nil {
return nil, err
}
fibRgFcLcb, cbRgFcLcb, err := getFibRgFcLcb(b, 34+csw+2+cslw)
return &fib{base: *fibBase, csw: csw, cslw: cslw, fibRgW: *fibRgW, fibRgLw: *fibRgLw, fibRgFcLcb: *fibRgFcLcb, cbRgFcLcb: cbRgFcLcb}, err
}
// parse FibBase (section 2.5.2)
func getFibBase(fib []byte) *fibBase {
byt := fib[11] // fWhichTblStm is 2nd highest bit in this byte
fWhichTblStm := int(byt >> 1 & 1) // set which table (0Table or 1Table) is the table stream
return &fibBase{fWhichTblStm: fWhichTblStm}
}
func getFibRgW(fib []byte, start int) (*fibRgW, int, error) {
if start+2 >= len(fib) { // must be big enough for csw
return &fibRgW{}, 0, errFibInvalid
}
csw := int(binary.LittleEndian.Uint16(fib[start:start+2])) * 2 // in bytes
return &fibRgW{}, csw, nil
}
// parse FibRgLw (section 2.5.4)
func getFibRgLw(fib []byte, start int) (*fibRgLw, int, error) {
fibRgLwStart := start + 2 // skip cslw
if fibRgLwStart+88 >= len(fib) { // expect 88 bytes in fibRgLw
return &fibRgLw{}, 0, errFibInvalid
}
cslw := getInt16(fib, start) * 4 // in bytes
ccpText := getInt(fib, fibRgLwStart+3*4)
ccpFtn := getInt(fib, fibRgLwStart+4*4)
ccpHdd := getInt(fib, fibRgLwStart+5*4)
ccpMcr := getInt(fib, fibRgLwStart+6*4)
ccpAtn := getInt(fib, fibRgLwStart+7*4)
ccpEdn := getInt(fib, fibRgLwStart+8*4)
ccpTxbx := getInt(fib, fibRgLwStart+9*4)
ccpHdrTxbx := getInt(fib, fibRgLwStart+10*4)
// calculate cpLength. Used in PlcPcd verification (see section 2.8.35)
var cpLength int
if ccpFtn != 0 || ccpHdd != 0 || ccpMcr != 0 || ccpAtn != 0 || ccpEdn != 0 || ccpTxbx != 0 || ccpHdrTxbx != 0 {
cpLength = ccpFtn + ccpHdd + ccpMcr + ccpAtn + ccpEdn + ccpTxbx + ccpHdrTxbx + ccpText + 1
} else {
cpLength = ccpText
}
return &fibRgLw{ccpText: ccpText, ccpFtn: ccpFtn, ccpHdd: ccpHdd, ccpMcr: ccpMcr, ccpAtn: ccpAtn,
ccpEdn: ccpEdn, ccpTxbx: ccpTxbx, ccpHdrTxbx: ccpHdrTxbx, cpLength: cpLength}, cslw, nil
}
// parse FibRgFcLcb (section 2.5.5)
func getFibRgFcLcb(fib []byte, start int) (*fibRgFcLcb, int, error) {
fibRgFcLcbStart := start + 2 // skip cbRgFcLcb
if fibRgFcLcbStart+186*4 < len(fib) { // expect 186+ values in FibRgFcLcb
return &fibRgFcLcb{}, 0, errFibInvalid
}
cbRgFcLcb := getInt16(fib, start)
fcPlcfFldMom := getInt(fib, fibRgFcLcbStart+32*4)
lcbPlcfFldMom := getInt(fib, fibRgFcLcbStart+33*4)
fcPlcfFldHdr := getInt(fib, fibRgFcLcbStart+34*4)
lcbPlcfFldHdr := getInt(fib, fibRgFcLcbStart+35*4)
fcPlcfFldFtn := getInt(fib, fibRgFcLcbStart+36*4)
lcbPlcfFldFtn := getInt(fib, fibRgFcLcbStart+37*4)
fcPlcfFldAtn := getInt(fib, fibRgFcLcbStart+38*4)
lcbPlcfFldAtn := getInt(fib, fibRgFcLcbStart+39*4)
fcClx := getInt(fib, fibRgFcLcbStart+66*4)
lcbClx := getInt(fib, fibRgFcLcbStart+67*4)
return &fibRgFcLcb{fcPlcfFldMom: fcPlcfFldMom, lcbPlcfFldMom: lcbPlcfFldMom, fcPlcfFldHdr: fcPlcfFldHdr, lcbPlcfFldHdr: lcbPlcfFldHdr,
fcPlcfFldFtn: fcPlcfFldFtn, lcbPlcfFldFtn: lcbPlcfFldFtn, fcPlcfFldAtn: fcPlcfFldAtn, lcbPlcfFldAtn: lcbPlcfFldAtn,
fcClx: fcClx, lcbClx: lcbClx}, cbRgFcLcb, nil
}
func getInt16(buf []byte, start int) int {
return int(binary.LittleEndian.Uint16(buf[start : start+2]))
}
func getInt(buf []byte, start int) int {
return int(binary.LittleEndian.Uint32(buf[start : start+4]))
}