
    Zi
                         S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKr\R                  R                  \R                  R                  \R                  R                  \5      5      5      r\R                  R                  \R                  R                  \S5      5      r\\R                  ;  a  \R                  R#                  S\5        SSKJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  Sr\R<                  S   S:  a  \r Sr!Sr"Sq#\!\"4 V s/ s H  n SU -  PM
     sn r$\!\"4 V s/ s H  n SU -  PM
     sn r%\!\"4 V s/ s H  n SU -  PM
     sn r&\!\"4 V s/ s H  n SU -  PM
     sn r'\!\"4 V s/ s H  n SU -  PM
     sn r(\!\"4 V s/ s H  n SU -  PM
     sn r)\!\"4 V s/ s H  n SU -  PM
     sn r*Sr+Sr,\RZ                  " S\R\                  5      r/Sr0Sr1Sr2\1r3S\-  r4Sr5\Rl                  " S 5      r7 " S! S"\Rp                  5      r9S# r:SBS$ jr;S% r<S&r=S'r>S(r?S)r@S* rAS+ rBS, rCSBS- jrDS. rE\RZ                  " S/5      rF\G" S0 \, 5       5      rH\RZ                  " S15      rIS2 rJS3 rK " S4 S5\R                  5      rMS6rNSBS7 jrOS8rP\RZ                  " S95      rQS:rRS; rSS< rT\QrUS= rVSBS> jrWSCS? jrXSBS@ jrY\ZSA:X  a  \R                  " \Y" 5       5        ggs  sn f s  sn f s  sn f s  sn f s  sn f s  sn f s  sn f )Da?  
msodde.py

msodde is a script to parse MS Office documents
(e.g. Word, Excel, RTF), to detect and extract DDE links.

Supported formats:
- Word 97-2003 (.doc, .dot), Word 2007+ (.docx, .dotx, .docm, .dotm)
- Excel 97-2003 (.xls), Excel 2007+ (.xlsx, .xlsm, .xlsb)
- RTF
- CSV (exported from / imported into Excel)
- XML (exported from Word 2003, Word 2007+, Excel 2003, (Excel 2007+?)

Author: Philippe Lagadec - http://www.decalage.info
License: BSD, see source code or documentation

msodde is part of the python-oletools package:
http://www.decalage.info/python/oletools
    )print_functionNz..)ooxml)
xls_parser)rtfobj)is_ppt)crypto)ensure_stdout_handles_unicode)
log_helperz0.60.2   z<http://schemas.openxmlformats.org/wordprocessingml/2006/mainz4http://schemas.microsoft.com/office/word/2003/wordmlFz{%s}instrTextz{%s}fldSimplez{%s}fldCharz{%s}pz{%s}rz	{%s}instrz{%s}fldCharType)zword/document.xmlzword/endnotes.xmlzword/footnotes.xmlzword/header1.xmlzword/footer1.xmlzword/header2.xmlzword/footer2.xmlzword/comments.xml)-)
CREATEDATEr   r    hsdatetime)DATEr   r   r   hlsr   )EDITTIMEr   r   r   r   numeric)	PRINTDATEr   r   r   r   r   )SAVEDATEr   r   r   r   r   )TIMEr   r   r   r   r   )AUTHORr      r   r   string)COMMENTSr   r   r   r   r   )DOCPROPERTYr   r   r   r   zstring/numeric/datetime)FILENAMEr   r   r   pr   )FILESIZEr   r   r   kmr   )KEYWORDSr   r   r   r   r   )LASTSAVEDBYr   r   r   r   r   )NUMCHARSr   r   r   r   r   )NUMPAGESr   r   r   r   r   )NUMWORDSr   r   r   r   r   )SUBJECTr   r   r   r   r   )TEMPLATEr   r   r   r   r   )TITLEr   r   r   r   r   )ADVANCEr   r   dlruxyr   r   )SYMBOLr   r   fsahjur   )FORMCHECKBOXr   r   r   r   r   )FORMDROPDOWNr   r   r   r   r   )FORMTEXTr   r   r   r   r   )INDEXr   r   bcdefghklpszryr   )TAr   r   clrsbir   )TCr   r   flnr   )TOAr   r   bcdeglsfhpr   )TOCr   r   abcdflnopsthuwxzr   )XEr   r   frtyr5   r   )BIBLIOGRAPHYr   r   lfmr   r   )CITATIONr   r   lfspvmntyr   )NOTEREFr   r   r   r;   r   )PAGEREFr   r   r   hpr   )QUOTEr   r   r   r   r   )STYLEREFr   r   r   lnprtwr   )LISTNUMr   r   lsr   r   )PAGEr   r   r   r   r   )REVNUMr   r   r   r   r   )SECTIONr   r   r   r   r   )SECTIONPAGESr   r   r   r   r   )SEQr   r   rschnr   )USERADDRESSr   r   r   r   r   )USERINITIALSr   r   r   r   r   )USERNAMEr   r   r   r   r   z^\s*dde(auto)?\s+zonly ddezexclude blacklistedzkeep allzmsodde %s - http://decalage.info/python/oletools
THIS IS WORK IN PROGRESS - Check updates regularly!
Please report any issue at https://github.com/decalage2/oletools/issues
warningmsoddec                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ArgParserWithBanner   z&Print banner before showing any error c                 J   > [        [        5        [        [        U ]  U5        g N)printBANNERsuperr[   error)selfmessage	__class__s     i/var/www/eduai.edurigo.com/question_generate/ques_gen_env/lib/python3.13/site-packages/oletools/msodde.pyrb   ArgParserWithBanner.error   s    f!4.w7     )__name__
__module____qualname____firstlineno____doc__rb   __static_attributes____classcell__re   s   @rf   r[   r[      s    18 8rh   r[   c                     [         R                  R                  U 5      (       d%  [        R                  " SR                  U 5      5      eU $ )z;called by argument parser to see whether given file exists zFile {0} does not exist.)ospathexistsargparseArgumentTypeErrorformat)filenames    rf   existing_filerz      s:    77>>(##(()C*0&*:< 	<Orh   c           	         [        SS9nUR                  SS[        SS9  UR                  SSS	S
S9  UR                  SSS	S9  UR                  SSSS[        SS9  UR                  SS[        SSS9  UR                  SSS9nUR                  SSSS [        S!S"9  UR                  S#S$SS [        S%S"9  UR                  S&S'SS [        S(S"9  UR                  [        S)9  UR                  U 5      $ )*zBparse command line arguments (given ones or per default sys.argv) z@A python tool to detect and extract DDE links in MS Office files)descriptionfilepathzpath of the file to be analyzedFILE)helptypemetavarz-jz--json
store_truez.Output in json format. Do not use with -ldebug)actionr   z--nounquotezdon't unquote values)r   r   z-lz
--loglevelloglevelstorezElogging level debug/info/warning/error/critical (default=%(default)s))destr   defaultr   z-pz
--passwordappendz^if encrypted office files are encountered, try decryption with this password. May be repeated.)r   r   r   z0Filter which OpenXML field commands are returnedzOnly applies to OpenXML (e.g. docx) and rtf, not to OLE (e.g. .doc). These options are mutually exclusive, last option found on command line overwrites earlier ones.)titler|   z-dz
--dde-onlystore_constfield_filter_modez"Return only DDE and DDEAUTO fields)r   r   constr   z-fz--filterz&Return all fields except harmless onesz-az--all-fieldsz1Return all fields, irrespective of their contentsr   )r[   add_argumentrz   DEFAULT_LOG_LEVELstradd_argument_groupFIELD_FILTER_DDEFIELD_FILTER_BLACKLISTFIELD_FILTER_ALLset_defaultsFIELD_FILTER_DEFAULT
parse_args)cmd_line_argsparserfilter_groups      rf   process_argsr     se     .H IF

)J*F  <
h|M  O
,B+  -
lG 15  6 lXO  P ,,@L - ML
 dL#6>N#G  I dJ}#6$:#K  M dN=#6>N$.  / *>?]++rh   c                    [         R                  SR                  U 5      5        U R                  5       R	                  5       R                  S5      (       a  U $ U R                  5       R	                  5       R                  S5      (       a  U $ g)zmcheck if field instructions start with DDE

expects unicode input, returns unicode output (empty if not dde) zprocessing field '{0}'ddez d d e r   )loggerdebugrx   lstriplower
startswith)datas    rf   process_doc_fieldr   9  sj     LL,33D9:{{}''//{{}''(>??rh            i  c                    SnSnSn/ nSnSn US-  nU R                  S5      n[        U5      S:X  a  GO?[        U5      nU[        :X  a-  U(       a  U(       a  [        R                  S5        SnSnSnSnMj  U(       d  Ms  U[        :X  a  U(       a  [        R                  S	5        SnOU[        :X  a*  [        U5      nU(       a  UR                  U5        SnSnSnOU(       d  U(       a  O[        U5      [        :  a+  [        R                  S
R                  [        5      5        SnOGUS:X  a  U[        U5      -  nO2US;   a  US-  nO&US:  a  US-  nOUS:  a  U[        U5      -  nOUS-  nGMf  U(       a  [        R                  S5        [        R                  SR                  U[        U5      5      5        U$ )zfind dde links in single word ole stream

since word ole file stream are subclasses of io.BytesIO, they are buffered,
so reading char-wise is not that bad performanc-wise FNTr   r   z#big field was not a field after allr   z*unexpected field: has multiple separators!z*field exceeds max size of {0}. Ignore rest)
      
    ?   z(Checked {0} characters, found {1} fields)readlenordOLE_FIELD_STARTr   r   OLE_FIELD_SEPOLE_FIELD_ENDr   r   OLE_FIELD_MAX_SIZErx   unichr)	stream
have_starthave_sepfield_contentsresult_partsmax_size_exceededidxchar
new_results	            rf   process_doc_streamr   L  s    JHNL
C
q{{1~t9>t9D?"/BCJH % N = IJH]"*>:J##J/ JH!N !^$'99I$f%78:$(! &,.!%'$&&,.$&q t :;
LL;&c,/02 rh   c           
         [         R                  S5        / n[        U R                  5       GH)  u  p#USL nU(       a  U R	                  U5      nUR
                  [        R                  :H  n[         R                  SR                  X$(       a  SOUR                  U(       a  SR                  UR                  5      OSR                  UR
                  5      5      5        U(       d  M  [        U R                  UR                  UR                  5      5      nU(       a'  [         R                  SUR                  < SU< 35        UR                  U5        GM,     S	R                  U5      $ )
ae  
find dde links in word ole (.doc/.dot) file

Checks whether files is ppt and returns empty immediately in that case
(ppt files cannot contain DDE-links to my knowledge)

like process_xml, returns a concatenated unicode string of dde links or
empty if none were found. dde-links will still begin with the dde[auto] key
word (possibly after some whitespace)
process_docNzdirentry {:2d} {}: {}z[orphan]zis stream of size {}zno stream ({})zstream : r   )r   r   	enumerate
direntries_load_direntry
entry_typeolefileSTGTY_STREAMrx   namesizer   _open
isectStartextendjoin)olelinkssiddirentry	is_orphan	is_stream	new_partss          rf   r   r     s    LLE"3>>2$	))#.H''7+?+??	,fS	*x}} ) 4::8==I-44X5H5HIK	L
 9*		(--x}}=?IyIJLL#! 3& ::erh   c                 r   / nSn [         R                  " U 5      nUR                  5        H  n[        U[         R                  5      (       d  M$  UR                  5        H  n[        U[         R                  5      (       d  M$  UR                  [         R                  R                  [         R                  R                  4;   d  Mh  UR                  UR                  R                  SS5      5        M     M     SR                  U5      Ub  UR                  5         $ $ ! Ub  UR                  5         f f = f)z!find dde links in excel ole file N r   )r   XlsFileiter_streams
isinstanceWorkbookStreamiter_recordsXlsRecordSupBooksupport_link_typeLINK_TYPE_OLE_DDELINK_TYPE_EXTERNALr   	virt_pathreplacer   close)r}   resultxls_filer   records        rf   process_xlsr     s    FH%%h/++-Ffj&?&?@@ --/!&**E*EFF++"33EE"33FF0H H MM&"2"2":":9d"KL 0 . zz&!NN  8NN  s   B>D  AD   D6c                    [         R                  " U 5      n/ nSnSnUR                  [        [        -   S9 GH  u  pgnUS:X  a  SnUR
                  [        ;   aj  UR                  R                  [        S   5      =(       d"    UR                  R                  [        S   5      n	U	b  UR                  [        U	5      5        M  U GH/  n
SnU
R
                  [        ;   a;  U
 H/  nUR
                  [        ;   d  UR
                  [        ;   d  M-  Un  O   Uc  MT  OU
nUc  [         R                  " U S5      eUR                  R                  [        S   5      =(       d"    UR                  R                  [        S   5      nUb1  US:X  a  US-  nUS:X  a   US-  nUS	;   a  UR                  U5        SnSnUR
                  [        ;   d  GM  UR                   c  GM  U[        UR                   5      -  nGM2     GM     ["        R%                  S
R'                  U5      5        U[(        S4;   a  UnOU[*        :X  a/  U Vs/ s H!  n[,        R/                  U5      (       d  M  UPM#     nnOWU[0        :X  a3  U Vs/ s H%  n[3        UR5                  5       5      (       a  M#  UPM'     nnO[7        SR'                  U5      5      eSR9                  U5      $ s  snf s  snf )z6find dde-links (and other fields) in Word 2007+ files r   r   )tagsr   Nz Got "None"-Element from iter_xmlbeginend)r   r   zfiltering with mode "{0}"#Unexpected field_filter_mode: "{0}"r   )r   	XmlParseriter_xmlTAG_W_PTAG_W_FLDSIMPLEtagattribgetATTR_W_INSTRr   unquoteTAG_W_RTAG_W_FLDCHARTAG_W_INSTRTEXTBadOOXMLATTR_W_FLDCHARTYPEtextr   r   rx   r   r   FIELD_DDE_REGEXmatchr   field_is_blacklistedstrip
ValueErrorr   )r}   r   r   
all_fieldslevelddetext_subsdepthattrib_instr	curr_elemelemchildattrib_typeclean_fieldsfields                   rf   process_docxr    s   __X&FJEG //w/H/IA:E88&;;??<?; <;;??<?; '!!',"78 ID}}'&EyyM1!II8$	 '
 <   !|nnX%GI I ++//*<Q*?@ A++//*<Q*?@ &')QJE%'QJE'"))'2"% ! xx?*tyy/D7499--C  J` LL,334EFG-t44!	.	.+5 9:%*007 : 9	4	4+5 D:%3EKKMB : D > &!235 	5 ::l##9Ds    K"K9"KKc                     SU ;  d  [         (       a  U $ U R                  5       R                  S5      nSnUSS  H  n [        [	        U5      5      nX$-  nM     U$ ! [
         a    Un Nf = f)z0TODO: document what exactly is happening here...rI   r   r   r   N)	NO_QUOTESr  splitchrintr  )r  partsddestrpart	characters        rf   r   r     sw    eyyKKM$EFab		CII 	  M  	I	s   AA+*A+z"[^"]*"|\S+c              #   F   #    U  H  oS    R                  5       v   M     g7f)r   N)r   ).0r  s     rf   	<genexpr>r  .  s     K?%1X^^--?s   !z^\\[\w#*@]$c                 4   [         R                  U 5      nU(       d  g [        R                  US   R	                  5       5      n[        R                  SR                  U [        U   5      5        [        U   u  p4pVpxSn	USS  H  n
U
S   S:X  a    O	U	S-  n	M     X:  a&  [        R                  SR                  XU 5      5        gXU-   :  a&  [        R                  SR                  XXP5      5        gSn/ nUSU	-   S  GH  n
U(       a8  U(       a+  X;  a&  [        R                  S	R                  X5      5          gSn/ nMC  [        R                  U
5      (       d&  [        R                  S
R                  X5      5          gU
S   nX;   a  M  X;   a  SnM  US:X  a
  SU;   a  SnM  US:X  a
  SU;   a  SnM  US:X  a"  SnUSS/-  nSU;   a  U/ SQ-  nSU;   a  / nM  M  [        R                  SR                  X5      5          g   g! [
         a     gf = f)a  Check if given field contents matches any in FIELD_BLACKLIST

A complete parser of field contents would be really complicated, so this
function has to make a trade-off. There may be valid constructs that this
simple parser cannot comprehend. Most arguments are not tested for validity
since that would make this test much more complicated. However, if this
parser accepts some field contents, then office is very likely to not
complain about it, either.
Fr   z.trying to match "{0}" to blacklist command {1}r   N\z7too few args: found {0}, but need at least {1} in "{2}"z;too many args: found {0}, but need at most {1}+{2} in "{3}"z,Found invalid switch argument "{0}" in "{1}"z%expected switch, found "{0}" in "{1}"T#r   @r   *
CHARFORMATMERGEFORMATr   )CapsFirstCapLowerUpperzunexpected switch {0} in "{1}")FIELD_WORD_REGEXfindallFIELD_BLACKLIST_CMDSindexr   r  r   r   rx   FIELD_BLACKLISTFIELD_SWITCH_REGEXr   )contentswordsr,  r  nargs_requirednargs_optionalsw_with_argsw_solo	sw_formatnargsword
expect_argarg_choicesswitchs                 rf   r  r  2  s2    $$X.E$**58>>+;< LLB&?5#9:< %
  GA~G Eab	7d?
  OfUH=	?.. fUNM	O  JKagh 7L$fT46JK#))$//LLA &02a"Js]yI5Js]zY6Js]JL-88K9$EEI%  & LL: &24E  J   s   &H
 

HHc                    / n[         R                  " U 5      nUR                  5        H  u  p4nUR                  R	                  5       nUS:X  d  UR                  S5      (       d  M>  / nSUR                  ;   a  UR                  UR                  S   5        SUR                  ;   a  UR                  UR                  S   5        UR                  SR                  U5      5        [        R                  SU< SU< S[        U5      < 35        M     UR                  5        H  u  pn
 [        R                  S	R                  X5      5        [        R                   " XU5       H  n[        R                  S
R                  X5      5        [#        U[        R$                  5      (       d  MH  UR&                  [        R$                  R(                  :X  d  Mr  UR                  UR*                  S-   UR,                  -   5        M     M     SR                  U5      $ ! [.         a  nU	R1                  S5      (       d  U	R1                  S5      (       a  [        R2                  nO=U	R1                  S5      (       d  U	S:X  a  [        R                  nO[        R                  nU" SR                  X[5        U5      5      5         SnAGM  SnAff = f)z;process an OOXML excel file (e.g. .xlsx or .xlsb or .xlsm) ddelinkz}ddelink
ddeServiceddeTopicr   zFound tag "z
" in file r   z1Parsing non-xml subfile {0} with content type {1}z{0}: {1}zapplication/vnd.ms-excel.zapplication/vnd.ms-office.zimage/zKapplication/vnd.openxmlformats-officedocument.spreadsheetml.printerSettingsz/Failed to parse {0} of content type {1} ("{2}")Nr   )r   r   r   r   r   endswithr   r   r   r   r   repriter_non_xmlinforx   r   parse_xlsb_partr   XlsbBeginSupBook	link_typeLINK_TYPE_DDEstring1string2	Exceptionr   rX   r   )r}   	dde_linksr   subfilenamer  r  r   	link_infosubfilecontent_typehandler   exclog_funcs                 rf   process_xlsxrR    s&   I__X&F & 11hhnn)s||J77It{{*  \!:;T[[(  Z!89TYYy12LLCdS\o^_ !2 *0)<)<)>%v	?KKK68$44V5<>Z..w?@fj&A&ABB(("33AAB$$V^^c%9FNN%JK>	 *?6 ::i  !  	?&&'BCC&&'CDD!>>((22l474 "<<!;;FfWCH=? ?	?s&   *A?H-&H/H
K%BKKc                   >   ^  \ rS rSrSrU 4S jrS rS rS rSr	U =r
$ )RtfFieldParseri  z:
Specialized RTF parser to extract fields such as DDEAUTO
c                 :   > [         [        U ]  U5        / U l        g r^   )ra   rT  __init__fields)rc   r   re   s     rf   rV  RtfFieldParser.__init__  s    nd,T2rh   c                 j    UR                   S:X  a#  [        R                  SUR                  -  5        g g )N   fldinstz!*** Start field data at index %Xh)cwordr   r   start)rc   destinations     rf   open_destinationRtfFieldParser.open_destination  s2    
*LL<&,,- . +rh   c                 h   UR                   S:X  a  [        R                  SU R                  -  5        [        R                  SUR                  -  5        UR                  R                  S S5      R                  5       n[        R                  SU-  5        U R                  R                  U5        g g )NrZ  z!*** Close field data at index %XhzField text: %rs   
zCleaned Field text: %r)	r[  r   r   r,  r   	translater  rW  r   )rc   r]  field_cleans      rf   close_destination RtfFieldParser.close_destination  s    
*LL<tzzIJLL)K,<,<<=%**44T7CIIKKLL1K?@KK{+ +rh   c                 d    U R                   =R                  UR                  5       SS -  sl        g )Nr      )current_destinationr   group)rc   matchobjects     rf   control_symbolRtfFieldParser.control_symbol  s+     	  %%):):)<Qq)AA%rh   )rW  )rj   rk   rl   rm   rn   rV  r^  rc  rj  ro   rp   rq   s   @rf   rT  rT    s#    
.
,B Brh   rT  s   {\rtc                    / n[         U R                  5       -   nU R                  5         [        U5      nUR	                  5         UR
                   Vs/ s H  oUR                  S5      PM     nn[        R                  SR                  U[        U5      5      5        U[        S4;   a  UnOU[        :X  a/  U Vs/ s H!  n[        R                  U5      (       d  M  UPM#     nnOWU[        :X  a3  U Vs/ s H%  n[!        UR#                  5       5      (       a  M#  UPM'     nnO[%        SR                  U5      5      eSR'                  U5      $ s  snf s  snf s  snf )z+find dde links or other fields in rtf file asciiz+found {1} fields, filtering with mode "{0}"Nr   r   )	RTF_STARTr   r   rT  parserW  decoder   r   rx   r   r   r   r   r   r   r  r  r  r   )file_handler   r  r   	rtfparserr  r  s          rf   process_rtfrs    s9   J{''))Dt$IOO5>5E5EF5EE,,w'5EJF
LL>&*C
O<>-t44!	.	.+5 9:%*007 : 9	4	4+5 D:%3EKKMB : D > &!235 	5 ::l### G9Ds   E:EE3"EEi   z\s*"?[=+-@](.+)\|(.+)!(.*)\s*z,	 ;|^c                    / n[         R                  R                  S::  a
  [        SS9nO	[        SS9n[	        U 40 UD6 n[        U[        5      u  pUR                  5       [        :  nU(       au  U(       dn  [        R                  S5        UR                  S5        [        R                  UR                  S5      nU H"  n UR                  S5        [        X75      u  pM$     U(       a  U(       d  [        R                  S	5        UR                  S5        ["        R%                  UR'                  [        5      5      n	U	(       a1  UR)                  S
R+                  U	R-                  5       SS 5      5        SSS5        SR+                  U5      $ ! [        R                   a)    [        R                  SR!                  U5      5         GM  f = f! , (       d  f       N_= f)a  find dde in csv text

finds text parts like =cmd|'/k ..\..\..\Windows\System32\calc.exe'! or
=MSEXCEL|'\..\..\..\Windows\System32\regsvr32 [...]

Hoping here that the :py:class:`csv.Sniffer` determines quote and delimiter
chars the same way that excel does. Tested to some extend in unittests.

This can only find DDE-links, no other "suspicious" constructs (yet).

Cannot deal with unicode files yet (need more than just use uopen()).
rf  rb)moder   )newlinez*small file, no results; try all delimitersr   z(failed to csv-parse with delimiter {0!r}z5last attempt: take whole file as single unquoted cellr   Nr   )sysversion_infomajordictopenprocess_csv_dialectCSV_DELIMITERStellCSV_SMALL_THRESHr   r   seekr   	delimitercsvErrorrx   CSV_DDE_FORMATr   r   r   r   groups)
r}   resultsopen_argrq  dialectis_smallother_delimdelimr  r   s
             rf   process_csvr    s}    G
"T?#	h	#(	#{.{NK##%(88GLLEFQ(001B1BBGK$1$$Q'!4[!HJGQ % GLL   !Q"(()9)9:J)KLEtyy);<=3 
$6 ::g yy 1LL!K"(&-1 11 
$	#s2    BGF"BG8GGGG
G!c           	         [         R                  " 5       R                  U R                  [        5      US9nSUl        [        R                  SR                  UR                  UR                  5      5        U R                  S5        / n[         R                  " X5      nU H[  nU HR  n[        R                  U5      nU(       d  M!  UR                  SR!                  UR#                  5       SS 5      5        MT     M]     X24$ )z<helper for process_csv: process with a specific csv dialect )
delimitersFz=sniffed csv dialect with delimiter {0!r} and quote char {1!r}r   r   Nrf  )r  Sniffersniffr   r  strictr   r   rx   r  	quotecharr  readerr  r   r   r   r  )rq  r  r  r  r  rowcellr   s           rf   r}  r}  /  s     kkm!!+"2"23C"D-7 " 9GGN
LL (&**G,=,=>@
 Q GZZ-FD"((.Eutyy);<=	   rh   c                    / n[         R                  " U 5      nUR                  5        GH!  u  p4nUR                  R	                  5       nUS:w  a  UR                  S5      (       d  M?  SnUR                  5        HN  nUR	                  5       S:X  d&  UR	                  5       R                  S5      (       d  M=  UR                  U5      n  O   Uc  M  [        R                  SR                  U5      5        [        R                  " [        U5      nU(       d  M  UR                  SR                  UR!                  5       SS 5      5        GM$     S	R                  U5      $ )
zfind dde links in xml files created with excel 2003 or excel 2007+

TODO: did not manage to create dde-link in the 2007+-xml-format. Find out
      whether this is possible at all. If so, extend this function
r  z}cellNformulaz}formulazfound cell with formula {0}r   rf  r   )r   r   r   r   r   r?  keysr   r   r   rx   rer   XML_DDE_FORMATr   r   r  )	r}   rJ  r   r  r  r   r  keyr   s	            rf   process_excel_xmlr  L  s	    I__X&Foo'
hhnn&=g!6!699;Cyy{i'399;+?+?
+K+K((3-  ?3::7CD15TYYu||~bq'9:; ( ::i  rh   c                    [         R                  " U 5      (       a  [        R                  S5        [        R
                  " U 5      (       a   [        R                  S5        [        U 5      $ [        U 5      (       a  [        R                  S5        g[        R                  S5        [         R                  " U SS9 n[        U5      sSSS5        $ [        U S5       nUR                  S	5      [        :X  a)  [        R                  S
5        [        X15      sSSS5        $  SSS5         [        R                  " U 5      n[        R                  SR!                  U5      5        U[        R$                  :X  a   [        R                  S5        ['        U 5      $ U[        R(                  [        R*                  4;   a   [        R                  S5        [-        U 5      $ U[        R.                  [        R0                  4;   a   [        R                  S5        [3        U 5      $ Uc   [        R                  S5        [5        U 5      $ [        R                  S5        [3        X5      $ ! , (       d  f       GN= f! , (       d  f       GN[= f! ["         a1  n[        R                  SR!                  U5      5        Sn SnAGNYSnAff = f)z1decides which of the process_* functions to call z3Is OLE. Checking streams to see whether this is xlsz Process file as excel 2003 (xls)zis ppt - cannot have DDEr   zProcess file as word 2003 (doc)N)path_encodingru     zProcess file as rtfzDetected file type: {0}z'Exception trying to xml-parse file: {0}z"Process file as excel 2007+ (xlsx)z)Process file as xml from excel 2003/2007+z(Process file as xml from word 2003/2007+zProcess file as csvz!Process file as word 2007+ (docx))r   	isOleFiler   r   r   is_xlsr   r   	OleFileIOr   r|  r   rn  rs  r   get_typerx   rI  DOCTYPE_EXCELrR  DOCTYPE_EXCEL_XMLDOCTYPE_EXCEL_XML2003r  DOCTYPE_WORD_XMLDOCTYPE_WORD_XML2003r  r  )r}   r   r   rq  doctyperP  s         rf   process_filer  f  s   ""JKX&&LL;<x(((LL3467xt<s# =< 
h	A)+LL./{>	 
	+ 
..*.55g>?
 %%%%9:H%%5**E,G,GHH@A **5))5+E+EFF?@H%%*+8$$
LL4544= =< 
	  >EEcJKs0   <I#9I5*:J #
I25
J
K&J==Kc                    Sn [        U 40 UD6n[        R                  " U 5      (       d  U$  U[        R                  :  a  [        R                  " X 5      eSnUc  [        R                  nO[        U5      [        R                  -   n [        R                  S5        [        R                  " X5      nU(       d+  [        R                  S5        [        R                  " U 5      e[        R                  S5        [        XQUS	-   40 UD6n [        R                   " U5        U$ ! [         a4    [        R                  SSS9  [        R                  " U 5      (       d  e  GN5f = f! [         a    [        R                  S
SS9   U$ f = f!  [        R                   " U5        f ! [         a    [        R                  S
SS9   f f = f= f)a  
Process a file that might be encrypted.

Calls :py:func:`process_file` and if that fails tries to decrypt and
process the result. Based on recommendation in module doc string of
:py:mod:`oletools.crypto`.

:param str filepath: path to file on disc.
:param passwords: list of passwords (str) to try for decryption or None
:param int crypto_nesting: How many decryption layers were already used to
                           get the given file.
:param kwargs: same as :py:func:`process_file`
:returns: same as :py:func:`process_file`
r   zIgnoring exception:T)exc_infoNzTrying to decrypt filez4Decrypt failed, run with debug output to get detailszAnalyze decrypted filer   z*Ignoring exception closing decrypted file:)r  r   is_encryptedrI  r   r   MAX_NESTING_DEPTHMaxCryptoNestingReachedDEFAULT_PASSWORDSlistdecryptrb   WrongEncryptionPasswordrB  process_maybe_encryptedrs   unlink)r}   	passwordscrypto_nestingkwargsr   decrypted_files         rf   r  r    s   " Fh1&1""8,,M - 111,,^FFN,,	Of&>&>>	(-.<LLOP00::,-()7)9E=CE	(IIn% M=  *T:""8,, -6  	(LLE"&  (M	(	(IIn% 	(LLE"&  (	(sT   (D& BF E' &:E$#E$'F	F	G	F%$G	%GG	GG	c                    [        U 5      n[        R                  " UR                  UR                  [
        R                  S9  UR                  (       a  Sq[        R                  [        5        [        R                  SUR                  -  5        SnSn [        UR                  UR                  UR                  S9nSn[        R                  S	5        UR'                  5        H  n[        R                  US
S9  M     [        R(                  " 5         U$ ! [          a(  n[        R#                  [%        U5      5         SnANSnAff = f)zMain function, called if this file is called as a script

Optional argument: command line arguments to be forwarded to ArgumentParser
in process_args. Per default (cmd_line_args=None), sys.argv is used. Option
mainly added for unit-testing
)r   TzOpening file: %sr   r   r   r   Nz
DDE Links:zdde-link)r   )r   r
   enable_loggingjsonr   rx  stdout	nounquoter  r   	print_strr`   r}   r  passwordr   rI  	exceptionr   
splitlinesend_logging)r   argsr   return_coderP  links         rf   mainr    s    &D
 diiszzJ~~	
V
'$--78DK#&MM4=="446  \"!J/ "   #S""#s   +D 
E#EE__main__r^   )Nr   )\rn   
__future__r   rv   rs   rx  r  r  r   rt   normpathabspathdirname__file___thismodule_dirr   _parent_dirinsertoletoolsr   r   r   oletools.ppt_record_parserr   r   oletools.common.io_encodingr	   oletools.common.log_helperr
   __version__ry  r  r   NS_WORDNS_WORD_2003r  r   r   r   r   r   r   r   	LOCATIONSr-  compileIr   r   r   r   r   r`   r   get_or_create_silent_loggerr   ArgumentParserr[   rz   r   r   r   r   r   r   r   r   r   r  r   r)  tupler+  r.  r  rR  	RtfParserrT  rn  rs  r  r  r~  r  r}  r  r  r  r  r  rj   exit)nss   0rf   <module>r     s[  ` &  	 
 	 
  ''""277??277??83L#MNggrww||OTBCchhHHOOA{#    -  E 18 " A!F
 IE	3:L2IJ2IB?R'2IJ3:L2IJ2IB?R'2IJ/6.EF.E#.EF#*L"9
:"9B7R<"9
:#*L"9
:"9B7R<"9
:,3\+BC+BRb +BC8?7NO7N'",7NO 6	AF **12448  .  - 
 
   
	/	/	9
8(11 8#,p
  L^ F.D$N" ::n- K?KK ZZ/ Rj,!^BV%% B>  	$8   <= -`4  !4)5^4n%P zHHTV _ KJF
:
:COs*   K4K"K'$K,<K1K6,K;