
    Zim                        S r SrSSKrSSKJr  SSKJr  SSKJrJ	r	J
r
  SSKJr  SSKrSSKr SSKJr  \R*                  " S5      rS	rS
rSrSrSrSrSrSrSrSr Sr!Sr"Sr#Sr$Sr%Sr&Sr'Sr(S r)S r*S r+S r, " S S \-5      r. " S! S"\/5      r0 " S# S$\-5      r1S% r2\3S&:X  a  \Rh                  " \2" 5       5        gg! \ a    SSKJs  Jr   Nf = f)'a  Common operations for OpenXML files (docx, xlsx, pptx, ...)

This is mostly based on ECMA-376 (5th edition, Part 1)
http://www.ecma-international.org/publications/standards/Ecma-376.htm

See also: Notes on Microsoft's implementation of ECMA-376: [MS-0E376]

.. codeauthor:: Intra2net AG <info@intra2net>
License: BSD, see source code or documentation

ooxml is part of the python-oletools package:
http://www.decalage.info/python/oletools
z0.54.2    N)
log_helper)uopen)ZipFile
BadZipfile
is_zipfile)splitextooxmlz[Content_Types].xmlz_rels/.rels)z<application/vnd.openxmlformats-officedocument.spreadsheetml.zapplication/vnd.ms-excel.)z?application/vnd.openxmlformats-officedocument.wordprocessingml.)z=application/vnd.openxmlformats-officedocument.presentationml.)zapplication/xmlz8application/vnd.openxmlformats-package.relationships+xmlz:application/vnd.openxmlformats-package.core-properties+xmlz7application/vnd.openxmlformats-officedocument.theme+xmlzEapplication/vnd.openxmlformats-officedocument.extended-properties+xmlz#<\?mso-application progid="(.*)"\?>zWord.DocumentzExcel.Sheetwordexcel
powerpointnonemixedzword-xmlz	excel-xmlzword-xml2003zexcel-xml2003c                 |   U c  gU R                   S   S:X  a[  U R                   R                  S5      S:X  a<  SR                  U R                   U R                   R                  S5      S-   S 5      /nOSR                  U R                   5      /nU R                  (       a:  UR                  S	R                  U R                  R                  S
S5      5      5        U R                  (       a:  UR                  SR                  U R                  R                  S
S5      5      5        U R                  R                  5        H  u  p#UR                  SR                  X#5      5        US:X  d  M-  UR                  [        5      (       a  US==   S-  ss'   MV  UR                  [        5      (       a  US==   S-  ss'   M  UR                  [        5      (       a  US==   S-  ss'   M  U[        ;   a  US==   S-  ss'   M  US==   S-  ss'   M     SR                  U5      n[!        U5      S:  a  USS S-   $ US-   $ )z for debugging: print an element NNoner   {}   z[tag={{...}}{0}z[tag={0}z
text="{0}"
z\nz
tail="{0}"z	{0}="{1}"ContentTypez-->xlsz-->docz-->pptz-->_z!!!z,       z...]])tagcountformatindextextappendreplacetailattribitems
startswithCONTENT_TYPES_EXCELCONTENT_TYPES_WORDCONTENT_TYPES_PPTCONTENT_TYPES_NEUTRALjoinlen)elempartskeyvaluer   s        h/var/www/eduai.edurigo.com/question_generate/ques_gen_env/lib/python3.13/site-packages/oletools/ooxml.py	debug_strr0      s   |xx{cdhhnnS1Q6"))$((488>>#3Fq3H3I*JKN""488,/yy]))$))*;*;D%*HIJyy]))$))*;*;D%*HIJkk'')
\((45- 344b	Y&	!!"455b	Y&	!!"344b	Y&	//b	W$	b	V#	 * ::eD
4y3DSzG##$;    c                 ~    [         R                  R                  S:X  a  [        U [        5      $ [        U [
        5      $ )zBversion-independent test for isinstance(some_var, (str, unicode))    )sysversion_infomajor
isinstance
basestringstr)some_vars    r/   isstrr;      s0    
"(J//h$$r1   c                    [        U 5      nUR                  5       (       a  Sn[        U S5       n[        R                  " [
        UR                  S5      5      nSSS5        U(       d  [        $ UR                  5       S   nU[        :X  a  [        $ U[        :X  a  [        $ [        $ SnSnSn UR                  [        5       H|  u  pn[        R!                  S[#        U	5      -   5         U	R$                  S   n
XjR)                  [*        5      -  nXZR)                  [,        5      -  nXzR)                  [.        5      -  nM~     U(       a  U(       d  U(       d  [4        $ U(       d  U(       a  U(       d  [6        $ U(       d  U(       d  U(       a  [8        $ U(       d  U(       d  U(       d  [        $ [        R;                  S	5        [<        $ ! , (       d  f       GNx= f! [&         a     GM'  f = f! [0         aE  nUR2                  R)                  S5      (       a  [        UR2                  ;   a  [        s SnA$ e SnAff = f)
z5return one of the DOCTYPE_* constants or raise error Nr   r   F  r   invalid subfilez'Encountered contradictory content types)	XmlParseris_single_xmlr   researchOFFICE_XML_PROGID_REGEXreadDOCTYPE_NONEgroupsWORD_XML_PROG_IDDOCTYPE_WORD_XMLEXCEL_XML_PROG_IDDOCTYPE_EXCEL_XMLiter_xmlFILE_CONTENT_TYPESloggerdebugr0   r"   KeyErrorr$   r%   r&   r'   BadOOXML	more_infoDOCTYPE_WORDDOCTYPE_EXCELDOCTYPE_POWERPOINTwarningDOCTYPE_MIXED)filenameparsermatchhandleprog_idis_docis_xlsis_ppt_r+   content_typeoo_errs               r/   get_typerd      s   x F8S!VII5v{{47HIE ",,.#&&##''$$FFF //*<=JAQLL401#{{=9 --.ABBF--.@AAF--.?@@F >  fVfV&V!!&
NN<=Q "!&  
  &&'899"f&6&66sT   +G/<G/ ,G;A	G/ 
G
G,'G/ +G,,G/ /
H>99H92H>8H99H>c                 h     [        U 5      nU[        :X  a  gg! [         a     g[         a     gf = f)z>Determine whether given file is an ooxml file; tries get_type FT)rd   rR   IOErrorrG   )rY   doctypes     r/   is_ooxmlrh      s@    8$
 ,   s    
1	11c                       \ rS rSrSrSrSS jrS rS rS r	S	 r
S
 rSS jr\R                  4S jrS rS rS rS rS rS rS rSrg)
ZipSubFile   a)  A file-like object like ZipFile.open returns them, with size and seek()

ZipFile.open() gives file handles that can be read but not seek()ed since
the file is being decompressed in the background. This class implements a
reset() function (close and re-open stream) and a seek() that uses it.
--> can be used as argument to olefile.OleFileIO and olefile.isOleFile()

Can be used as a context manager::

    with zipfile.ZipFile('file.zip') as zipper:
        # replaces with zipper.open(subfile) as handle:
        with ZipSubFile(zipper, 'subfile') as handle:
            print('subfile in file.zip has size {0}, starts with {1}'
                  .format(handle.size, handle.read(20)))
            handle.reset()

Attributes always present:
container: the containing zip file
name: name of file within zip file
mode: open-mode, 'r' per default
size: size of the stream (constructor arg or taken from ZipFile.getinfo)
closed: True if there was an open() but no close() since then

Attributes only not-None after open() and before close():
handle: direct handle to subfile stream, created by ZipFile.open()
pos: current position within stream (can deviate from actual position in
     self.handle if we fake jump to end)

See also (and maybe could some day merge with):
ppt_record_parser.IterStream; also: oleobj.FakeFile
i   Nc                 ^   Xl         X l        UcO  UR                  U5      R                  U l        [
        R                  SR                  U R                  5      5        OX@l        SUR                  5       ;   a  [        SR                  U5      5      eX0l
        SU l        SU l        SU l        g)z0remember all necessary vars but do not open yet Nzzip stream has size {0}wz%Can only read, mode "{0}" not allowedT)	containernamegetinfo	file_sizesizerO   rP   r   lower
ValueErrormoder\   posclosed)selfrn   rY   ru   rr   s        r/   __init__ZipSubFile.__init__  s    "	<!))(3==DILL299$))DEI$**,D$fTl, ,	r1   c                     gNT rx   s    r/   readableZipSubFile.readable!      r1   c                     gNFr}   r~   s    r/   writableZipSubFile.writable$  s    r1   c                     gr|   r}   r~   s    r/   seekableZipSubFile.seekable'  r   r1   c                     U R                   b  [        S5      eU R                  R                  U R                  U R
                  5      U l         SU l        SU l        U $ )z@open subfile for reading; open mode given to constructor before zre-opening file not supported!r   F)r\   rf   rn   openro   ru   rv   rw   r~   s    r/   r   ZipSubFile.open*  sK    ;;":;;nn))$))TYY?r1   c                     [        S5      e)zwrite is not allowed zwriting not implemented)rf   rx   argskwargss      r/   writeZipSubFile.write4  s    /00r1   c                     U R                   c  [        S5      eU R                  U R                  :  a  gU R                   R	                  U5      nU =R                  [        U5      -  sl        U$ )zm
read given number of bytes (or all data) from stream

returns bytes (i.e. str in python2, bytes in python3)
zread on closed handler1   )r\   rf   rv   rr   rF   r*   )rx   rr   datas      r/   rF   ZipSubFile.read8  sX     ;;12288tyy {{%CIr1   c                 .   U[         R                  :X  a  UnObU[         R                  :X  a  U R                  U-   nO>U[         R                  :X  a  U R
                  U-   nO[        SR                  U5      5      eUS:  a  [        S5      eX0R                  :X  a  gUS:X  a  U R                  5         gX0R                  :  a"  U R                  5         U R                  U5        gX0R
                  :  a  U R                  X0R                  -
  5        gX0l        g)z4re-position point so read() will continue elsewhere z(invalid offset {0}, need SEEK_* constantr   z%Seek beyond start of file not allowedN)ioSEEK_SETSEEK_CURrv   SEEK_ENDrr   rt   r   rf   reset
_seek_skip)rx   rv   offsetnew_poss       r/   seekZipSubFile.seekH  s     R[[ Gr{{"hhnGr{{"ii#oGG$fVn. . Q;ABB \JJLxxJJLOOG$yy OOGhh./ Hr1   c                     [        XR                  5      u  p#[        U5       H  nU R                  U R                  5        M      U R                  U5        g)z;helper for seek: skip forward by given amount using read() N)divmod
CHUNK_SIZErangerF   )rx   to_skipn_chunksleftoverra   s        r/   r   ZipSubFile._seek_skipj  s?     $G__=xAIIdoo& !		(r1   c                     U R                   $ )z#inform about position of next read )rv   r~   s    r/   tellZipSubFile.tellu  s     xxr1   c                 D    U R                  5         U R                  5         g)zclose and re-open N)closer   r~   s    r/   r   ZipSubFile.resetz  s     	

		r1   c                 |    U R                   b  U R                   R                  5         SU l        SU l         SU l        g)zclose file NT)r\   r   rv   rw   r~   s    r/   r   ZipSubFile.close  s3     ;;"KKr1   c                 &    U R                  5         U $ )z)start of context manager; opens the file )r   r~   s    r/   	__enter__ZipSubFile.__enter__  s     			r1   c                 $    U R                  5         g)z(end of context manager; closes the file N)r   r   s      r/   __exit__ZipSubFile.__exit__  s     	

r1   c                    U R                   c  SnOKU R                  S:X  a  SnO8U R                  U R                  :  a  SnOSR                  U R                  5      nSR                  U R                  U R                  U R
                  U5      $ )z6creates a nice textual representation for this object rw   r   zopen, at startzopen, at endzopen, at pos {0}z*[ZipSubFile {0} (size {1}, mode {2}, {3})])r\   rv   rr   r   ro   ru   )rx   statuss     r/   __str__ZipSubFile.__str__  so    ;;FXX]%FXX"#F'..txx8F;tyy$))TYY?	@r1   )rw   rn   r\   ru   ro   rv   rr   )r=   N)r   )__name__
__module____qualname____firstlineno____doc__r   ry   r   r   r   r   r   rF   r   r   r   r   r   r   r   r   r   r   __static_attributes__r}   r1   r/   rj   rj      sd    > J"1   "{{  D

@r1   rj   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )rR   i  z3exception thrown if file is not an office XML file c                 z   > [         [        U ]  SR                  X(       a  SU-   OS5      5        Xl        X l        g)z2create exception, remember filename and more_info z {0} is not an Office XML file{1}z:  N)superrR   ry   r   rY   rS   )rx   rY   rS   	__class__s      r/   ry   BadOOXML.__init__  s7    h&.VH)dY.D	F !"r1   )rY   rS   N)r   r   r   r   r   ry   r   __classcell__)r   s   @r/   rR   rR     s    ># #r1   rR   c                   D    \ rS rSrSrS rS rSS jrSS jrS r	S	 r
S
rg)rA   i  ar  parser for OOXML files

handles two different types of files: "regular" OOXML files are zip
archives that contain xml data and possibly other files in binary format.
In Office 2003, Microsoft introduced another xml-based format, which uses
a single xml file as data source. The content of these types is also
different. Method :py:meth:`is_single_xml` tells them apart.
c                 J    Xl         SU l        [        5       U l        S U l        g r   )rY   did_iter_allsetsubfiles_no_xml_is_single_xml)rx   rY   s     r/   ry   XmlParser.__init__  s!     !"u"r1   c                 z   U R                   b  U R                   $ [        U R                  5      (       a  SU l         gSn[        U R                  S5       n[        R
                  " [        UR                  S5      5      nSSS5        U(       a  SU l         g[        U R                  S5      e! , (       d  f       N3= f)zvdetermine whether this is "regular" ooxml or a single xml file

Raises a BadOOXML if this is neither one or the other
NFr=   r>   Tzis no zip and has no prog_id)	r   r   rY   r   rC   rD   rE   rF   rR   )rx   r[   r\   s      r/   rB   XmlParser.is_single_xml  s    
 *&&&dmm$$"'D 4==#&&II5v{{47HIE '"&Dt}}&DEE '&s   +B,,
B:Nc              #   >  #    U R                  5       (       aJ  U(       a  [        U R                  S5      e[        U R                  S5       nSU4v   SSS5        SU l        gSnSn [        U R                  5      nU(       d  UR                  5       nO&[        U5      (       a  U/nO[        S U 5       5      nU H#  nUR                  US5       nXR4v   SSS5        M%     U(       d  SU l        U(       a  UR                  5         gg! , (       d  f       N= f! , (       d  f       Mn  = f! [         a'  n[        U R                  S[        U5      -   5      eSnAf[         a    [        U R                  S5      ef = f! U(       a  UR                  5         f f = f7f)	z
Find files in zip or just give single xml file

yields pairs (subfile-name, file-handle) where file-handle is an open
file-like object. (Do not care too much about encoding here, the xml
parser reads the encoding from the first lines in the file.)
zxml has no subfilesrbNTc              3   $   #    U  H  ov   M     g 7fr   r}   ).0args     r/   	<genexpr>'XmlParser.iter_files.<locals>.<genexpr>  s     $9DSSDs   r=   zinvalid subfile: znot in zip format)rB   rR   rY   r   r   r   namelistr;   tuplerQ   r9   r   r   )rx   r   r\   zippersubfilessubfileorig_errs          r/   
iter_filesXmlParser.iter_files  s`     t}}.CDDdmmT*fFl" + $DFH# /%0H4[[ $xH  %$9D$99H'GWc2f%o- 32  ( (,D% LLN = +*$ 32  D t}}2S]BD D Ct}}.ABBC LLN sg   A	FD
F'A*D- DD- 1F

DF
D*	%D- -
E=7"E$E==F   FFc           	   #     #    Uc  / nO^[        U5      (       a(  U/n[        R                  SR                  U5      5        O&Un[        R                  SR                  U5      5        U R	                  U5       GH  u  pVSnSn/ n	 [
        R                  " Xg5       GH  u  pUc  M  U
S:X  ac  UR                  U;   aL  [        R                  SR                  UR                  U5      5        U	R                  UR                  U45        US-  nMt  U
S:X  d   eUS-  nUS:  d   eUR                  U;   nU(       a  UR                  U4n U	S	   U:X  a  U	R                  5         O[        R                  S
R                  UU	S	   5      5        U	(       aX  U	S	   S   U:  aL  [        R                  SR                  U	S	   5      5        U	R                  5         U	(       a  U	S	   S   U:  a  ML  U(       d  U(       d  X[U4v   U(       a  GMm  U	(       a  GMw  UR                  5         GM     US:X  a  GM   e   g! [         a    [        R                  S5         Nlf = f! [
        R                   a  nU R                  R                  U5        Uc  [!        U R"                  S5      eUR%                  S5      (       a  [        R&                  nO[        R                  nU" SR                  X^5      S-   5         SnANSnAff = f7f)a  Iterate xml contents of document

If given subfile name[s] as optional arg[s], will only parse that
subfile[s]

yields 3-tuples (subfilename, element, depth) where depth indicates how
deep in the hierarchy the element is located. Containers of element
will come *after* the elements they contain (since they are only
finished then).

Subfiles that are not xml (e.g. OLE or image files) are remembered
internally and can be retrieved using iter_non_xml().

The argument need_children is set to False per default. If you need to
access an element's children, set it to True. Note, however, that
leaving it at False should save a lot of memory. Otherwise, the parser
has to keep every single element in memory since the last element
returned is the root which has the rest of the document as children.
c.f. http://www.ibm.com/developerworks/xml/library/x-hiperfparse/

Argument tags restricts output to tags with names from that list (or
equal to that string). Children are preserved for these.
Nzlooking for tags: {0})startendr   r   z remember start of tag {0} at {1}r   r   r   zBfound end for wanted tag {0} but last start tag {1} does not matchzrecover: pop {0}z0found end of {0} at depth {1} but no start eventzcontent is not valid XMLz.xmlz$  xml-parsing for {0} failed ({1}). z Run iter_non_xml to investigate.)r;   rO   rP   r   r   ET	iterparser   r   poperror
IndexErrorclear
ParseErrorr   addrR   rY   endswithrW   )rx   r   need_childrentags	want_tagsr   r\   eventsdepthinside_tagseventr+   	is_wantedcurr_tagerrlogs                   r/   rM   XmlParser.iter_xml  s    0 <I4[[ILL077=>ILL077=>#x8OG%FEK78#%<<#?KE| '88y0"LL)K*0&5*AC'..%/@A
  E>*>QJE A:&: $I 5I $(HHe#4;*2(: + 1 & .66<fX=H_7N!O
 '2(3B(:e(C$*LL1C28&R2I%K$/OO$5	 '2(3B(:e(C !	%U22 )=

Q $@n A::y  9H  * ;"LL *: ;; == 
8$$((1?"4==2LMM%%f-- ..C ,,C:VG)67 8 8
8su   BL CI	H5"I#BH5*III'L 0L 5IIIIK=.BK83L 8K==L c                    U R                  5       (       a  0 0 4$ / n/ n U R                  [        5       GH+  u  p4nUR                  R	                  S5      (       ar  UR
                  S   nUR                  S5      (       a  USS nUR                  XTR
                  S   45        [        R                  SR                  US   5      5        M  UR                  R	                  S	5      (       d  M  UR
                  S
   nUR                  S5      (       a  USS nUR                  XdR
                  S   45        [        R                  SR                  US   5      5        GM.     [        U5      [        U5      4$ ! [         a?  nUR                  R                  S5      (       a  [        UR                  ;   a   SnANYe SnAff = f)zretrieve subfile infos from [Content_Types].xml subfile

returns (files, defaults) where
- files is a dict that maps file-name --> content-type
- defaults is a dict that maps extension --> content-type

No guarantees on accuracy of these content types!
Default	Extension.r   Nr   z/found content type for extension {0[0]}: {0[1]}r   OverridePartName/z-found content type for subfile {0[0]}: {0[1]}r@   )rB   rM   rN   r   r   r"   r$   r   rO   rP   r   rR   rS   dict)rx   defaultsfilesra   r+   	extensionr   rc   s           r/   get_content_typesXmlParser.get_content_typese  s    r6M	"mm,>?
88$$Y// $K 8I ++C00$-abM	OOYM0J$KLLL "**0&"*>@XX&&z22"kk*5G))#..")!"+LL';;}+E!FGLL "**0&r*;= @. E{DN**  	**+<==&&*:*:: 	s%   CE: /A5E: :
G4F>=F>>Gc              #   Z  #    U R                   (       d  [        R                  S5        U R                  (       d  gU R	                  5       (       a  gU R                  5       u  p[        U R                  5       nU R                   Hv  nUR                  S5      (       a  USS nSnXA;   a  X   nO2[        U5      S   nUR                  S5      (       a  USS nXb;   a  X&   n[        X45       nXEU4v   SSS5        Mx     SSS5        g! , (       d  f       M  = f! , (       d  f       g= f7f)a  retrieve subfiles that were found by iter_xml to be non-xml

also looks for content type info in the [Content_Types].xml subfile.

yields 3-tuples (filename, content_type, file_handle) where
content_type is based on filename or default for extension or is None,
and file_handle is a ZipSubFile. Caller does not have to care about
closing handle, will be closed even in error condition.

To handle binary parts of an xlsb file, use xls_parser.parse_xlsb_part
zQDid not iterate through complete file. Should run iter_xml() without args, first.Nr   r   r   )r   rO   rW   r   rB   r  r   rY   r$   r   rj   )rx   content_typescontent_defaultsr   r   rb   r  r\   s           r/   iter_non_xmlXmlParser.iter_non_xml  s       NN H I## *.*@*@*B'T]]#v//%%c**%abkG#+#0#9L ( 1! 4I ++C00$-abM	 4'7'B0F!77 10 0 $# 10 $#s7   A6D+8A4D,D3D?	D+
DD
D($D+)r   r   rY   r   r   )NFN)r   r   r   r   r   ry   rB   r   rM   r  r  r   r}   r1   r/   rA   rA     s*    #F*+#Z]~&+P&8r1   rA   c            
         [         R                  " SS5        [        [        R                  5      S:w  a  [        S5        g[        S[        [        R                  S   5      -   5        [        [        R                  S   5      n U R                  5        H6  u  pnUS:  d  M  [        SR                  US	U-  [        U5      5      5        M8     [        U R                  5       5       H?  u  nu  pn[        S
R                  X=(       d    S5      5        US:  d  M4  [        S5          O   [         R                  " 5         g)z
Test xml parsing; called when running this file as a script.

Prints every element found in input file (to be given as command line arg).
FrP   r3   z/To test this code, give me a single file as argzDetected type: r      z
{0} {1}{2}r?   z Non-XML subfile: {0} of type {1}unknownd   z...r   )r   enable_loggingr*   r4   argvprintrd   rA   rM   r   r0   	enumerater  end_logging)rZ   r   r+   r   r   rb   ra   s          r/   testr    s     eW-
388}@A 

hsxx{3
34 sxx{#F & 1u19-&&wuioNO !2 .7v7J7J7L-M))q1vg9z:	<3;&M .N r1   __main__)5r   __version__r4   oletools.common.log_helperr   oletools.common.io_encodingr   zipfiler   r   r   os.pathr   r   rC   
lxml.etreeetreer   ImportErrorxml.etree.cElementTreecElementTreeget_or_create_silent_loggerrO   rN   FILE_RELATIONSHIPSr%   r&   r'   r(   rE   rI   rK   rT   rU   rV   rG   rX   rJ   rL   DOCTYPE_WORD_XML2003DOCTYPE_EXCEL_XML2003r0   r;   rd   rh   objectrj   rt   rR   rA   r  r   exitr}   r1   r/   <module>r%     s9  X   1 - 3 3  	 	( 
	/	/	8 + "    
  A " !  !   % ' @%-`
$r@ r@j	#z 	#"8 8D> zHHTV ]  (''(s   B9 9C
C