Skip to content

Commit 78fd608

Browse files
committed
init
1 parent 910bb49 commit 78fd608

8 files changed

+402
-0
lines changed

dir.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package ole2
2+
3+
import (
4+
"unicode/utf16"
5+
)
6+
7+
const (
8+
EMPTY = iota
9+
USERSTORAGE = iota
10+
USERSTREAM = iota
11+
LOCKBYTES = iota
12+
PROPERTY = iota
13+
ROOT = iota
14+
)
15+
16+
type File struct {
17+
NameBts [32]uint16
18+
Bsize uint16
19+
Type byte
20+
Flag byte
21+
Left uint32
22+
Right uint32
23+
Child uint32
24+
Guid [8]uint16
25+
Userflags uint32
26+
Time [2]uint64
27+
Sstart uint32
28+
Size uint32
29+
Proptype uint32
30+
}
31+
32+
func (d *File) Name() string {
33+
runes := utf16.Decode(d.NameBts[:d.Bsize/2-1])
34+
return string(runes)
35+
}

header.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package ole2
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"fmt"
7+
)
8+
9+
type Header struct {
10+
Id [2]uint32
11+
Clid [4]uint32
12+
Verminor uint16
13+
Verdll uint16
14+
Byteorder uint16
15+
Lsectorb uint16
16+
Lssectorb uint16
17+
_ uint16
18+
_ uint64
19+
20+
Cfat uint32 //Total number of sectors used for the sector allocation table
21+
Dirstart uint32 //SecID of first sector of the directory stream
22+
23+
_ uint32
24+
25+
Sectorcutoff uint32 //Minimum size of a standard stream
26+
Sfatstart uint32 //SecID of first sector of the short-sector allocation table
27+
Csfat uint32 //Total number of sectors used for the short-sector allocation table
28+
Difstart uint32 //SecID of first sector of the master sector allocation table
29+
Cdif uint32 //Total number of sectors used for the master sector allocation table
30+
Msat [109]uint32
31+
}
32+
33+
func parseHeader(bts []byte) (*Header, error) {
34+
buf := bytes.NewBuffer(bts)
35+
header := new(Header)
36+
binary.Read(buf, binary.LittleEndian, header)
37+
if header.Id[0] != 0xE011CFD0 || header.Id[1] != 0xE11AB1A1 || header.Byteorder != 0xFFFE {
38+
return nil, fmt.Errorf("not an excel file")
39+
}
40+
41+
return header, nil
42+
}

ole.go

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package ole2
2+
3+
import (
4+
"encoding/binary"
5+
"io"
6+
)
7+
8+
var ENDOFCHAIN = uint32(0xFFFFFFFE) //-2
9+
var FREESECT = uint32(0xFFFFFFFF) // -1
10+
11+
type Ole struct {
12+
header *Header
13+
Lsector uint32
14+
Lssector uint32
15+
SecID []uint32
16+
SSecID []uint32
17+
Files []File
18+
bts []byte
19+
}
20+
21+
func Open(bts []byte, charset string) (ole *Ole, err error) {
22+
var header *Header
23+
if header, err = parseHeader(bts[:512]); err == nil {
24+
ole = new(Ole)
25+
ole.bts = bts
26+
ole.header = header
27+
ole.Lsector = 512 //TODO
28+
ole.Lssector = 64 //TODO
29+
ole.bts = bts
30+
ole.readMSAT()
31+
return ole, nil
32+
}
33+
34+
return nil, err
35+
}
36+
37+
func (o *Ole) ListDir() (dir []*File, err error) {
38+
sector := o.stream_read(o.header.Dirstart, 0)
39+
dir = make([]*File, 0)
40+
for {
41+
d := new(File)
42+
err = binary.Read(sector, binary.LittleEndian, d)
43+
if err == nil && d.Type != EMPTY {
44+
dir = append(dir, d)
45+
} else {
46+
break
47+
}
48+
49+
}
50+
51+
return
52+
}
53+
54+
func (o *Ole) OpenFile(file *File) io.ReadSeeker {
55+
if file.Size < o.header.Sectorcutoff {
56+
return o.short_stream_read(file.Sstart, file.Size)
57+
} else {
58+
return o.stream_read(file.Sstart, file.Size)
59+
}
60+
}
61+
62+
// Read MSAT
63+
func (o *Ole) readMSAT() {
64+
// int sectorNum;
65+
66+
count := uint32(109)
67+
if o.header.Cfat < 109 {
68+
count = o.header.Cfat
69+
}
70+
71+
for i := uint32(0); i < count; i++ {
72+
sector := o.sector_read(o.header.Msat[i])
73+
sids := sector.AllValues(o.Lsector)
74+
75+
o.SecID = append(o.SecID, sids...)
76+
}
77+
78+
for sid := o.header.Difstart; sid != ENDOFCHAIN; {
79+
sector := o.sector_read(sid)
80+
sids := sector.MsatValues(o.Lsector)
81+
82+
for _, sid := range sids {
83+
sector := o.sector_read(sid)
84+
sids := sector.AllValues(o.Lsector)
85+
86+
o.SecID = append(o.SecID, sids...)
87+
}
88+
89+
sid = sector.NextSid(o.Lsector)
90+
}
91+
92+
for i := uint32(0); i < o.header.Csfat; i++ {
93+
sid := o.header.Sfatstart
94+
95+
if sid != ENDOFCHAIN {
96+
sector := o.sector_read(sid)
97+
98+
sids := sector.MsatValues(o.Lsector)
99+
100+
o.SSecID = append(o.SSecID, sids...)
101+
102+
sid = sector.NextSid(o.Lsector)
103+
}
104+
}
105+
106+
}
107+
108+
func (o *Ole) stream_read(sid uint32, size uint32) *StreamReader {
109+
return &StreamReader{o.SecID, sid, o, sid, 0, o.Lsector, int64(size), 0}
110+
}
111+
112+
func (o *Ole) short_stream_read(sid uint32, size uint32) *StreamReader {
113+
return &StreamReader{o.SSecID, sid, o, sid, 0, o.Lssector, int64(size), 0}
114+
}
115+
116+
func (o *Ole) sector_read(sid uint32) Sector {
117+
pos := o.sector_pos(sid, o.Lsector)
118+
bts := o.bts[pos : pos+o.Lsector]
119+
return Sector(bts)
120+
}
121+
122+
func (o *Ole) short_sector_read(sid uint32) Sector {
123+
pos := o.sector_pos(sid, o.Lssector)
124+
return Sector(o.bts[pos : pos+o.Lssector])
125+
}
126+
127+
func (o *Ole) sector_pos(sid uint32, size uint32) uint32 {
128+
return 512 + sid*size
129+
}

pss.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package ole2
2+
3+
import ()
4+
5+
type PSS struct {
6+
name [64]byte
7+
bsize uint16
8+
typ byte
9+
flag byte
10+
left uint32
11+
right uint32
12+
child uint32
13+
guid [16]uint16
14+
userflags uint32
15+
time [2]uint64
16+
sstart uint32
17+
size uint32
18+
_ uint32
19+
}

sector.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package ole2
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
)
7+
8+
type Sector []byte
9+
10+
func (s *Sector) Uint32(bit uint32) uint32 {
11+
return binary.LittleEndian.Uint32((*s)[bit : bit+4])
12+
}
13+
14+
func (s *Sector) NextSid(size uint32) uint32 {
15+
return s.Uint32(size - 4)
16+
}
17+
18+
func (s *Sector) MsatValues(size uint32) []uint32 {
19+
20+
return s.values(size, int(size/4-1))
21+
}
22+
23+
func (s *Sector) AllValues(size uint32) []uint32 {
24+
25+
return s.values(size, int(size/4))
26+
}
27+
28+
func (s *Sector) values(size uint32, length int) []uint32 {
29+
30+
var res = make([]uint32, length)
31+
32+
buf := bytes.NewBuffer((*s))
33+
34+
binary.Read(buf, binary.LittleEndian, res)
35+
36+
return res
37+
}

stream.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ole2
2+
3+
type Stream struct {
4+
Ole *Ole
5+
Start uint32
6+
Pos uint32
7+
Cfat int
8+
Size int
9+
Fatpos uint32
10+
Bufsize uint32
11+
Eof byte
12+
Sfat bool
13+
}

stream_reader.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package ole2
2+
3+
import (
4+
"io"
5+
"log"
6+
)
7+
8+
var DEBUG = false
9+
10+
type StreamReader struct {
11+
sat []uint32
12+
start uint32
13+
ole *Ole
14+
offset_of_sector uint32
15+
offset_in_sector uint32
16+
size_sector uint32
17+
size int64
18+
offset int64
19+
}
20+
21+
func (r *StreamReader) Read(p []byte) (n int, err error) {
22+
if r.offset_of_sector == ENDOFCHAIN {
23+
return 0, io.EOF
24+
}
25+
for i := 0; i < len(p); i++ {
26+
if r.offset_in_sector >= r.size_sector {
27+
r.offset_in_sector = 0
28+
r.offset_of_sector = r.sat[r.offset_of_sector]
29+
if r.offset_of_sector == ENDOFCHAIN {
30+
return i, io.EOF
31+
}
32+
}
33+
pos := r.ole.sector_pos(r.offset_of_sector, r.size_sector) + r.offset_in_sector
34+
p[i] = r.ole.bts[pos]
35+
if DEBUG {
36+
log.Printf("pos:%x,bit:%x", pos, p[i])
37+
}
38+
r.offset_in_sector++
39+
r.offset++
40+
if r.offset == int64(r.size) {
41+
return i + 1, io.EOF
42+
}
43+
}
44+
return len(p), nil
45+
}
46+
47+
func (r *StreamReader) Seek(offset int64, whence int) (offset_result int64, err error) {
48+
49+
if whence == 0 {
50+
r.offset_of_sector = r.start
51+
r.offset_in_sector = 0
52+
r.offset = offset
53+
} else {
54+
r.offset += offset
55+
}
56+
57+
if r.offset_of_sector == ENDOFCHAIN {
58+
return r.offset, io.EOF
59+
}
60+
61+
for offset >= int64(r.size_sector-r.offset_in_sector) {
62+
r.offset_of_sector = r.sat[r.offset_of_sector]
63+
offset -= int64(r.size_sector - r.offset_in_sector)
64+
r.offset_in_sector = 0
65+
if r.offset_of_sector == ENDOFCHAIN {
66+
err = io.EOF
67+
goto return_res
68+
}
69+
}
70+
71+
if r.size <= r.offset {
72+
err = io.EOF
73+
r.offset = r.size
74+
} else {
75+
r.offset_in_sector += uint32(offset)
76+
}
77+
return_res:
78+
offset_result = r.offset
79+
return
80+
}

0 commit comments

Comments
 (0)