...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package comdoc
23
24 import (
25 "bytes"
26 "encoding/binary"
27 "errors"
28 "io"
29 "os"
30 )
31
32
33 type ComDoc struct {
34 File io.ReaderAt
35 Header *Header
36 SectorSize int
37 ShortSectorSize int
38 FirstSector int64
39 MSAT, SAT, SSAT []SecID
40 Files []DirEnt
41
42 sectorBuf []byte
43 changed bool
44 rootStorage int
45 rootFiles []int
46 writer *os.File
47 closer io.Closer
48 }
49
50
51 func ReadPath(path string) (*ComDoc, error) {
52 f, err := os.Open(path)
53 if err != nil {
54 return nil, err
55 }
56 return openFile(f, nil, f)
57 }
58
59
60 func WritePath(path string) (*ComDoc, error) {
61 f, err := os.OpenFile(path, os.O_RDWR, 0)
62 if err != nil {
63 return nil, err
64 }
65 return openFile(f, f, f)
66 }
67
68
69 func ReadFile(reader io.ReaderAt) (*ComDoc, error) {
70 return openFile(reader, nil, nil)
71 }
72
73
74 func WriteFile(f *os.File) (*ComDoc, error) {
75 return openFile(f, f, nil)
76 }
77
78 func openFile(reader io.ReaderAt, writer *os.File, closer io.Closer) (*ComDoc, error) {
79 header := new(Header)
80 r := &ComDoc{
81 File: reader,
82 Header: header,
83 writer: writer,
84 closer: closer,
85 }
86 sr := io.NewSectionReader(reader, 0, 512)
87 if err := binary.Read(sr, binary.LittleEndian, header); err != nil {
88 return nil, err
89 }
90 if !bytes.Equal(header.Magic[:], fileMagic) {
91 return nil, errors.New("not a compound document file")
92 }
93 if header.ByteOrder != byteOrderMarker {
94 return nil, errors.New("incorrect byte order marker")
95 }
96 if header.SectorSize < 5 || header.SectorSize > 28 || header.ShortSectorSize >= header.SectorSize {
97 return nil, errors.New("unreasonable header values")
98 }
99 r.SectorSize = 1 << header.SectorSize
100 r.ShortSectorSize = 1 << header.ShortSectorSize
101 if r.SectorSize < 512 {
102 r.FirstSector = 512
103 } else {
104 r.FirstSector = int64(r.SectorSize)
105 }
106 r.sectorBuf = make([]byte, r.SectorSize)
107
108 if err := r.readMSAT(); err != nil {
109 return nil, err
110 }
111 if err := r.readSAT(); err != nil {
112 return nil, err
113 }
114 if err := r.readShortSAT(); err != nil {
115 return nil, err
116 }
117 if err := r.readDir(); err != nil {
118 return nil, err
119 }
120 return r, nil
121 }
122
View as plain text