Skip to content

Commit

Permalink
FIX: issue extrame#47
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeilem committed Dec 3, 2018
1 parent d1f3d0b commit 7162526
Showing 1 changed file with 41 additions and 24 deletions.
65 changes: 41 additions & 24 deletions workbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package xls
import (
"bytes"
"encoding/binary"
"golang.org/x/text/encoding/charmap"
"io"
"os"
"unicode/utf16"
"golang.org/x/text/encoding/charmap"
"unsafe"
)

//xls workbook type
Expand All @@ -26,6 +27,7 @@ type WorkBook struct {
continue_rich uint16
continue_apsb uint32
dateMode uint16
pos uintptr
}

//read workbook from ole2 file
Expand All @@ -44,8 +46,10 @@ func (w *WorkBook) Parse(buf io.ReadSeeker) {
bof_pre := new(bof)
// buf := bytes.NewReader(bts)
offset := 0
w.pos = 0
for {
if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
w.pos += unsafe.Sizeof(b)
bof_pre, b, offset = w.parseBof(buf, b, bof_pre, offset)
} else {
break
Expand Down Expand Up @@ -74,45 +78,43 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int
after_using = pre
var bts = make([]byte, b.Size)
binary.Read(buf, binary.LittleEndian, bts)
wb.pos += unsafe.Sizeof(bts)
buf_item := bytes.NewReader(bts)
switch b.Id {
case 0x809:
case 0x809: // BIFF 5-8
bif := new(biffHeader)
binary.Read(buf_item, binary.LittleEndian, bif)
wb.pos += unsafe.Sizeof(bif)
if bif.Ver != 0x600 {
wb.Is5ver = true
}
wb.Type = bif.Type
case 0x042: // CODEPAGE
binary.Read(buf_item, binary.LittleEndian, &wb.Codepage)
wb.pos += unsafe.Sizeof(wb.Codepage)
case 0x3c: // CONTINUE
// step back if previous element not yet completed
if wb.continue_utf16 > 0 {
offset_pre--
}

if pre.Id == 0xfc {
if pre.Id == 0xfc { //SST
var size uint16
var err error
if wb.continue_utf16 >= 1 {
if wb.continue_utf16 > 0 {
size = wb.continue_utf16
wb.continue_utf16 = 0
} else {
err = binary.Read(buf_item, binary.LittleEndian, &size)
wb.pos += unsafe.Sizeof(size)
}
for err == nil && offset_pre < len(wb.sst) {
var str string
if size > 0 {
str, err = wb.get_string(buf_item, size)
wb.sst[offset_pre] = wb.sst[offset_pre] + str
}
str, err = wb.get_string(buf_item, size)
wb.sst[offset_pre] = wb.sst[offset_pre] + str

if err == io.EOF {
break
}

offset_pre++
err = binary.Read(buf_item, binary.LittleEndian, &size)
wb.pos += unsafe.Sizeof(size)
}
}
offset = offset_pre
Expand All @@ -121,14 +123,17 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int
case 0xfc: // SST
info := new(SstInfo)
binary.Read(buf_item, binary.LittleEndian, info)
wb.pos += unsafe.Sizeof(info)
wb.sst = make([]string, info.Count)
var size uint16
var i = 0
// dont forget to initialize offset
offset = 0
for ; i < int(info.Count); i++ {
var err error
if err = binary.Read(buf_item, binary.LittleEndian, &size); err == nil {
err = binary.Read(buf_item, binary.LittleEndian, &size)
wb.pos += unsafe.Sizeof(size)
if err == nil {
var str string
str, err = wb.get_string(buf_item, size)
wb.sst[i] = wb.sst[i] + str
Expand All @@ -139,88 +144,98 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int
}
}
offset = i
case 0x85: // bOUNDSHEET
case 0x85: // boundsheet
var bs = new(boundsheet)
binary.Read(buf_item, binary.LittleEndian, bs)
wb.pos += unsafe.Sizeof(bs)
// different for BIFF5 and BIFF8
wb.addSheet(bs, buf_item)
case 0x0e0: // XF
if wb.Is5ver {
xf := new(Xf5)
binary.Read(buf_item, binary.LittleEndian, xf)
wb.pos += unsafe.Sizeof(xf)
wb.addXf(xf)
} else {
xf := new(Xf8)
binary.Read(buf_item, binary.LittleEndian, xf)
wb.pos += unsafe.Sizeof(xf)
wb.addXf(xf)
}
case 0x031: // FONT
f := new(FontInfo)
binary.Read(buf_item, binary.LittleEndian, f)
wb.pos += unsafe.Sizeof(f)
wb.addFont(f, buf_item)
case 0x41E: //FORMAT
font := new(Format)
binary.Read(buf_item, binary.LittleEndian, &font.Head)
wb.pos += unsafe.Sizeof(font.Head)
font.str, _ = wb.get_string(buf_item, font.Head.Size)
wb.addFormat(font)
case 0x22: //DATEMODE
binary.Read(buf_item, binary.LittleEndian, &wb.dateMode)
wb.pos += unsafe.Sizeof(wb.dateMode)
}
return
}
func decodeWindows1251(enc []byte) string {
dec := charmap.Windows1251.NewDecoder()
out, _ := dec.Bytes(enc)
return string(out)
dec := charmap.Windows1251.NewDecoder()
out, _ := dec.Bytes(enc)
return string(out)
}
func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err error) {
if w.Is5ver {
var bts = make([]byte, size)
_, err = buf.Read(bts)
w.pos += unsafe.Sizeof(bts)
res = decodeWindows1251(bts)
//res = string(bts)
} else {
var richtext_num = uint16(0)
var phonetic_size = uint32(0)
var flag byte
err = binary.Read(buf, binary.LittleEndian, &flag)
w.pos += unsafe.Sizeof(flag)
if flag&0x8 != 0 {
err = binary.Read(buf, binary.LittleEndian, &richtext_num)
w.pos += unsafe.Sizeof(richtext_num)
} else if w.continue_rich > 0 {
richtext_num = w.continue_rich
w.continue_rich = 0
}
if flag&0x4 != 0 {
err = binary.Read(buf, binary.LittleEndian, &phonetic_size)
w.pos += unsafe.Sizeof(phonetic_size)
} else if w.continue_apsb > 0 {
phonetic_size = w.continue_apsb
w.continue_apsb = 0
}
if flag&0x1 != 0 {
var bts = make([]uint16, size)
var i = uint16(0)
// we need local err here
var err error
for ; i < size && err == nil; i++ {
err = binary.Read(buf, binary.LittleEndian, &bts[i])
w.pos += 2
}

// when eof found, we dont want to append last element
var runes []rune
if err == io.EOF {
runes = utf16.Decode(bts[:i-1])
} else {
runes = utf16.Decode(bts[:i])
i = i - 1
}
runes = utf16.Decode(bts[:i])

res = string(runes)
if i < size {
w.continue_utf16 = size - i + 1
w.continue_utf16 = size - i
}

} else {
var bts = make([]byte, size)
var n int
n, err = buf.Read(bts)
w.pos += unsafe.Sizeof(bts)
if uint16(n) < size {
w.continue_utf16 = size - uint16(n)
err = io.EOF
Expand All @@ -243,6 +258,7 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
}
bts = make([]byte, seek_size)
err = binary.Read(buf, binary.LittleEndian, bts)
w.pos += unsafe.Sizeof(bts)
if err == io.EOF {
w.continue_rich = richtext_num
}
Expand All @@ -253,6 +269,7 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
var bts []byte
bts = make([]byte, phonetic_size)
err = binary.Read(buf, binary.LittleEndian, bts)
w.pos += unsafe.Sizeof(bts)
if err == io.EOF {
w.continue_apsb = phonetic_size
}
Expand Down

0 comments on commit 7162526

Please sign in to comment.