|iB rdZdZddlZddlZddlmZddlZej ej ej ej e Z e ejvrejde [ ddlmZejddkreZdZdZd ZGd d ejZGd d ejZGddeZGddejZegdZegdZGddej Z!Gdde!Z"Gdde!Z#Gdde!Z$Gddej Z%Gdde%Z&d Z'e(d!kr/ej)ej*ej+d"deedSdS)#zQ Parse xls up to some point Read storages, (sub-)streams, records from xls file z0.54N)unpack) record_basecld} t|}|D]2}t|tr||dSdS3n&#t $rt jddYnwxYw||n#||wwxYwdS)a  determine whether a given file is an excel ole file returns True if given file is an ole file and contains a Workbook stream todo: could further check that workbook stream starts with a globals substream. See also: oleid.OleID.check_excel NTz/Ignoring exception in is_xls, assume is not xls)exc_infoF)XlsFile iter_streams isinstanceWorkbookStreamclose Exceptionloggingdebug)filenamexls_filestreams AC:\PYTHON\_runtimes\venv\Lib\site-packages\oletools/xls_parser.pyis_xlsrQsH 8$$++--  F&.11    NN          %%% G# % % % % % %%   NN      NN     5s/;AAB A>;B=A>>BB1ct|||dzdk}|r*|dz|z}||dz|d|fSt||dz|S)z= read a unicode string from a XLUnicodeStringNoCch structure rascii)orddecoderead_unicode_2byte)data start_idxn_charslow_bytes_onlyend_idxs r read_unicoder jsw$y14566!;N>a-')IaK'(//88'AA!$ ! W===c||dzz}|dkr)dtdd|zz||D}nfdt||dD}d||fS)z: read a unicode string with characters encoded by 2 bytes c34K|]}t|VdS)N)unichr).0vals r z%read_unicode_2byte..zs@HHCF3KKHHHHHHr!<Hc 3tK|]2}ttd||dzdV3dS).}sdBB 6$Xhqj-@(ABB1EFFBBBBBBr!)rrangejoin)rrrrunicharss` rrrvs'A+%G}}HH3W,d9W3D.EFFHHHBBBB$))Wa$@$@BBB 88H  w &&r!c(eZdZdZedZdS)rz1 An xls file has most streams made up of records c*|dkrtStS)z helper for iter_streams Workbook)r XlsStream)cls stream_names rstream_class_for_namezXlsFile.stream_class_for_names * $ $! !r!N)__name__ __module__ __qualname____doc__ classmethodr9r!rrrs3;;[r!rc.eZdZdZdZedZdS)r6z- most streams in xls file consist of records cbtd|jd\}}||dfS)| read first few bytes of record to determine size and type returns (type, size, other) where other is None +>??(4''r!ctdfS)T determine a class for given record type returns (clz, force_read) F) XlsRecordr7rGs rrecord_class_for_typezXlsStream.record_class_for_types %r!N)r:r;r<r=rIr>rNr?r!rr6r6sD77(((  [   r!r6c(eZdZdZedZdS)r z+ Stream in excel file that holds most info c|tjkr tdfS|tjkr tdfS|tjkr tdfStdfSrKTF) XlsRecordBofTYPE XlsRecordEofXlsRecordSupBookrLrMs rrNz$WorkbookStream.record_class_for_types[ |( ( (% % * * *& & ). . .#T) )e# #r!N)r:r;r<r=r>rNr?r!rr r s355 $ $[ $ $ $r!r c6eZdZdZdZdZdZedZdS) XlsbStreamz@ binary stream of an xlsb file, usually have a record structure ct|jd}||jzr@t|jd}||jz||jzdzz}n|}d}d}t dD]N}t|jd}|||jz|zz }|dz }||jzdkrnO||dfS)rBrrrDN)rrrE HIGH_BIT_MASK LOW7_BIT_MASKr0)rFr(val2rGrHshift_s rrIzXlsbStream.read_record_heads $+""1%%&& # # t{''**++Dd00 22q8:HHHq  Adk&&q))**C t11e; ;H QJEd((Q../4''r!cF|tjkr tdfStdfSrQ)XlsbBeginSupBookrS XlsbRecordrMs rrNz XlsbStream.record_class_for_types) ', , ,#T) )u$ $r!N) r:r;r<r=r\r]rIr>rNr?r!rrWrWsNJJMM(((0%%[%%%r!rW)()BuiltInFnGroupCount)icBookExt)iCodeName)BCodePage)icDat)ij DataLabExt)ikDataLabExtContents)DBCell) DbOrParmQry)i DBQueryExt)ivDConn)# ExternName) ExternSheet)ExtSST)i ExtString)igFeatHdr)[ FileSharing)iFormat)1Font)i GUIDTypeLib)iHLink) InterfaceHdr) InterfaceEnd)i Index)Lbl)Mms)]Obj)i' ObjectLink)i  OleDbConn) OleObjectSize)iRichTextStream)ibSheetExt)iShrFmla)i  SxViewExt)iX SxViewLink)iWebPub)zXF (formatting))i}zXFExt (formatting))iStyle)iStyleExt))iL BrtEndSupBook)i BrtSupAddin)ic BrtSupBookSrc)iJBrtSupNameBits)iHBrtSupNameBool)iK BrtSupNameEnd)iE BrtSupNameErr)iIBrtSupNameFmla)iG BrtSupNameNil)iD BrtSupNameNum)iF BrtSupNameSt)iABrtSupNameStart)iCBrtSupNameValueEnd)iBBrtSupNameValueStart)if BrtSupSame)ie BrtSupSelf)ig BrtSupTabsceZdZdZdZdZdS)rLz1 basic building block of data in workbook stream i c| t|jS#t$rd|jcYSwxYw); simplification for subclasses to create their own __str__ zXlsRecord type {0})FREQUENT_RECORDStypeKeyErrorformatrFs r _type_strzXlsRecord._type_str.sK :#DI. . : : :'..ty99 9 9 9 : $;;Nr:r;r<r=MAX_SIZErr?r!rrLrL(s0;;H:::::r!rLc@eZdZdZdZdZegdZdZdZ dS)rRz) record found at beginning of substreams i ))workbook)rzdialog/worksheet) chart)@macrocv|j d|_dStd|jddd|_dS)Nr-r#rDr)rdoctyperrFr`s rfinish_constructingz XlsRecordBof.finish_constructing>s: 9 DL FdDIacN33A6 r!cld|j|jvr|j|jndS)NzBOF Record ({0} substream)unknown)rrDOCTYPESrs rrzXlsRecordBof._type_strEs:+22+/<4=+H+HDM$, ' ' r!N) r:r;r<r=rSSIZEdictrrrr?r!rrRrR6sb33 D Dt77788H777r!rRc eZdZdZdZdZdZdS)rTz# record found at end of substreams rcdS)Nz EOF Recordr?rs rrzXlsRecordEof._type_strPs|r!N)r:r;r<r=rSrrr?r!rrTrTKs3-- D Dr!rTc>eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d S) rUz The SupBook record specifies a supporting link "... The collection of records specifies the contents of an external workbook, DDE data source, or OLE data source." (MS-XLS, paragraph 2.4.271) irzself-referencingzaddin-referencingunusedz same-sheetzole/dde data sourcezexternal workbookcd|_d|_d|_|j|_|jdS|jdkr'td|jtd|jdd\|_|_d|jcxkrdkr'nn$t|jd|j\|_}n d\|_}|jdkr|j |_dS|jd kr|jd kr|j |_dS|jd kr|j |_dS|jd kr|j|_dS|jdkr|jr|j|_dS|jdkr|jr|j|_dSdSdS) z>Finish constructing this record; called at end of constructor.NrDz+not enough data (size is {0} but need >= 4)rCrrw)r/rDiri: )ctabcch virt_pathLINK_TYPE_UNKNOWNsupport_link_typersize ValueErrorrrr LINK_TYPE_SELFLINK_TYPE_ADDINLINK_TYPE_UNUSEDLINK_TYPE_SAMESHEETLINK_TYPE_OLE_DDELINK_TYPE_EXTERNALrs rrz$XlsRecordSupBook.finish_constructinges !%!7 9  F 9q==J$fTY//11 1$UDIbqbM:: 48 tx    4      ,TY48 D D DNAA & DNA 8u  %)%8D " " " Y#  $(f"4"4%)%9D " " " ^y ( (%)%:D " " " ^y ( (%)%=D " " " Y#  $. %)%;D " " " Y]]t~]%)%tj d |jd|j |_d}t d|j||dzd}|d krtj d nc|j|dz|zdzkr.tj d ||jn!t|j|dz|\|_}t d|j||dzd}|d krtj d dS|j|dz|zdzkr2tj d ||jd zdSt|j|dz|\|_}dS) Nr/r-rr#rz$Unexpected link type {0} encounteredz?@@C j OH I I I I YY.q0 0 0 ON#VGTY77 9 9 9 9'99B1g'O'O #DL)ty9Q;)>?@@C j OH I I I I I YY.q0 0 0 ON#VGTY77.I J J J J J1IaK18::ODL!!!r!cNd|j|j|jS)Nz+XlsbBeginSupBook Record ({0}, "{1}", "{2}"))rrrrrs rrzXlsbBeginSupBook._type_strs"<t~t|T\BB Cr!N) r:r;r<r=rSrrrrrrrr?r!rrbrbse D#MM'!%:%:%:NCCCCCr!rbc#Kd} t||j|tj}|D]}|Vn#t $rwxYw ||dSdS#||wwxYw)zC Excel xlsb files also have bin files with record structure. iter! N)rWrr STGTY_STREAM iter_recordsr r ) file_streamr`r xlsb_streamrecords rparse_xlsb_partrsK   k.>!,!9;; !..00  FLLLL      "         # "; "        #sr sxL " W  bgoobgooGOOH//  !!  SXHOOAz""" A! F2 > > > ' ' ' k'     +   ($$$$$Y$$$&'%'%'%'%'%,'%'%'%^4)))))X* : : : : : ) : : :9*96E6E6E6E6Ey6E6E6Er ; ; ; ; ;* ; ; ; 7C7C7C7C7Cz7C7C7C~    ( z CH [ chqrrlG^ D DEEEEEr!