import io import struct import olefile from .record_decoder import ParseError, binary_records, ascii_records, detect_format MAX_STREAM_BYTES = 32 * 1024 * 1024 MAX_TOTAL_BYTES = 64 * 1024 * 1024 def read_document(data): fmt=detect_format(data) if fmt=='ascii': return fmt,[],ascii_records(data),[] try: with olefile.OleFileIO(io.BytesIO(data),raise_defects=olefile.DEFECT_INCORRECT) as ole: entries=ole.listdir(streams=True,storages=False) if len(entries)>256: raise ParseError('Too many OLE streams') streams=[{'name':'/'.join(p),'size':ole.get_size(p)} for p in entries] if any(s['size']>MAX_STREAM_BYTES for s in streams) or sum(s['size'] for s in streams)>MAX_TOTAL_BYTES: raise ParseError('OLE stream size limit exceeded') if not ole.exists('FileHeader') or ole.get_type('FileHeader')!=2: raise ParseError('OLE container has no FileHeader stream') main=binary_records(ole.openstream('FileHeader').read(),'FileHeader') extra=[] if ole.exists('Additional') and ole.get_type('Additional')==2: extra=binary_records(ole.openstream('Additional').read(),'Additional') return fmt,streams,main,extra except (OSError,IOError,ValueError,IndexError,struct.error) as exc: raise ParseError(f'Invalid OLE schematic: {exc}') from exc