...

Source file src/github.com/sassoftware/relic/lib/comdoc/reader.go

Documentation: github.com/sassoftware/relic/lib/comdoc

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  // Microsoft Compound Document File
    18  // Reference: https://www.openoffice.org/sc/compdocfileformat.pdf
    19  // ERRATA: The above document says the 0th sector is always 512 bytes into the
    20  // file. This is not correct. If SectorSize > 512 bytes then the 0th sector is
    21  // SectorSize bytes into the file.
    22  package comdoc
    23  
    24  import (
    25  	"bytes"
    26  	"encoding/binary"
    27  	"errors"
    28  	"io"
    29  	"os"
    30  )
    31  
    32  // CDF file open for reading or writing
    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   // index into files
    45  	rootFiles   []int // index into Files
    46  	writer      *os.File
    47  	closer      io.Closer
    48  }
    49  
    50  // Open a CDF file for reading
    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  // Open a CDF file for reading and writing
    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  // Parse an already-open CDF file for reading
    69  func ReadFile(reader io.ReaderAt) (*ComDoc, error) {
    70  	return openFile(reader, nil, nil)
    71  }
    72  
    73  // Parse an already-open CDF file for reading and writing
    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