
    ,hpQ                     6   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
mZmZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZ  ej<                  e      Z e jC                   ejD                                 G d	 d
ejF                        Z$y)    N)	constants)
Attachment)Named)FixedLengthPropVariableLengthProp)
Properties)dividegetEncodingNamehas_leninputToMsgpathinputToStringmsgpathToString	parseType	properHexverifyPropertyId
verifyTypewindowsUnicode)InvalidFileFormatErrorMissingEncodingErrorc                      e Zd ZdZdeddej                  fdZd$dZd Z	d Z
d$dZd$d	Zd%d
Zd&dZd'dZd&dZd Zd$dZd$dZd(dZd$dZd)dZd)dZd Zed        Zed        Zed        Zed        Zed        Zed        Zed        Z ed        Z!ed        Z"ed        Z#ed         Z$ed!        Z%ed"        Z&ed#        Z'y)*MSGFilez
    Parser for .msg files
     Nc           
         || _         || _        t        j                  |cxk  rt        j                  k  st        d       t        d      || _        |1t        j                  |       t        j                  d       || _        || _        	 t        j                  j                  | |       g }|dk7  }	|	rW	 t)        |d      }|j1                  d
d      }|j3                  d      }
|
d   dk(  r|
j5                          |
}|d   dk7  r|dz  }|| _        || _        |	r| j;                  |dd dgz   d      }||| _        yt?        |      rtA        |      dk  r|| _        yd| _        yd| _        y# t         $ r4}t        j#                  |       t%        |      dk(  rt'        |       d}~ww xY w#  	 dj+                  |      }n(#  t-        dt%        t/        |            z   d	z         xY wY /xY w)a  
        :param path: path to the msg file in the system or is the raw msg file.
        :param prefix: used for extracting embeded msg files
            inside the main one. Do not set manually unless
            you know what you are doing.
        :param attachmentClass: optional, the class the MSGFile object
            will use for attachments. You probably should
            not change this value unless you know what you
            are doing.
        :param filename: optional, the filename to be used by default when saving.
        :param overrideEncoding: optional, an encoding to use instead of the one
            specified by the msg file. Do not report encoding errors caused by this.
        zw`attachmentErrorBehavior` must be ATTACHMENT_ERROR_THROW, ATTACHMENT_ERROR_NOT_IMPLEMENTED, or ATTACHMENT_ERROR_BROKEN.Nz^You have chosen to override the string encoding. Do not report encoding errors caused by this.z#not an OLE2 structured storage filer   zutf-8/zInvalid prefix type: z7
(This was probably caused by you setting it manually).\z__substg1.0_3001Fprefixi   )!_MSGFile__path_MSGFile__attachmentClassr   ATTACHMENT_ERROR_THROWATTACHMENT_ERROR_BROKEN
ValueError!_MSGFile__attachmentErrorBehaviorcodecslookuploggerwarning_MSGFile__stringEncoding_MSGFile__overrideEncodingolefile	OleFileIO__init__IOErrorerrorstrr   r   join	TypeErrortypereplacesplitpop_MSGFile__prefix_MSGFile__prefixList_getStringStreamfilenamer   len)selfpathr   attachmentClassr:   overrideEncodingattachmentErrorBehavioreprefixltmp_conditiongs              Q/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/extract_msg/msg.pyr-   zMSGFile.__init__   s    !0004KpyOpOpp  W  X  X q  W  X  X)@&'MM*+NN{|$4D!"2	&&tT2 "`&vw7 ^^D#.FS!Au{GbzS ##,,WSb\=O<P-PY^,_H$DMT]4y4 $ $ DMK  	LLO1v>>,Q//	`` XXf-F`#$;c$v,>O$O$^%_ ` ` s<    E4 9F4 4	F1=/F,,F14G47G	G4	%G..G4c                     	 t        | |      S # t        $ r7 |r| j                  |      }n| j                  |      }t	        | ||       |cY S w xY w)z
        Ensures that the variable exists, otherwise will set it using the specified stream.
        After that, return said variable.
        If the specified stream is not a string stream, make sure to set :param string stream: to False.
        )getattrAttributeErrorr9   
_getStreamsetattr)r<   variablestreamIDstringStreamvalues        rE   
_ensureSetzMSGFile._ensureSet[   sU    	4** 	--h71D(E*L	s    =AAc                     	 t        | |      S # t        $ r- | j                  j                  |      }t	        | ||       |cY S w xY w)z
        Ensures that the variable exists, otherwise will set it using the named property.
        After that, return said variable.
        )rG   rH   namedgetNamedValuerJ   r<   rK   propertyNamerN   s       rE   _ensureSetNamedzMSGFile._ensureSetNamedk   sH    
	4** 	JJ,,\:ED(E*L	s    3AAc                     	 t        | |      S # t        $ rD 	 | j                  |   j                  }n# t        t        f$ r d}Y nw xY wt        | ||       |cY S w xY w)z
        Ensures that the variable exists, otherwise will set it using the property.
        After that, return said variable.
        N)rG   rH   mainPropertiesrN   KeyErrorrJ   rS   s       rE   _ensureSetPropertyzMSGFile._ensureSetPropertyw   sh    
	4** 	++L9??n- D(E*L	s/    	A2AAAAAAc                     | j                  ||      }| j                  |      r+| j                  |      5 }|j                         cddd       S t        j                  dj                  |             y# 1 sw Y   yxY w)z
        Gets a binary representation of the requested filename.

        This should ALWAYS return a bytes object (string in python 2)
        NzCStream "{}" was requested but could not be found. Returning `None`.)fix_pathexists
openstreamreadr'   infoformat)r<   r:   r   streams       rE   rI   zMSGFile._getStream   so     ==62;;x * %f{{}% % KK]ddemno	% %s   A44A=c                     | j                  ||      }| j                  rt        | j                  |dz   d            S | j                  |dz   d      }|dS |j	                  | j
                        S )a  
        Gets a string representation of the requested filename.

        Rather than the full filename, you should only feed this
        function the filename sans the type. So if the full name
        is "__substg1.0_001A001F", the filename this function
        should receive should be "__substg1.0_001A".

        This should ALWAYS return a string (Unicode in python 2)
        001FFr   001EN)r[   areStringsUnicoder   rI   decodestringEncoding)r<   r:   r   tmps       rE   r9   zMSGFile._getStringStream   so     ==62!!!$//(V2Ce/"TUU//(V"3e/DC;4KCJJt7J7J,KK    c                     t        |       |j                         }| j                  d|z   ||      \  }}|r|S | j                  ||      \  }}|r|S dS )ao  
        Gets the data for the specified id as the type that it is
        supposed to be. :param id: MUST be a 4 digit hexadecimal
        string.

        If you know for sure what type the data is before hand,
        you can specify it as being one of the strings in the
        constant FIXED_LENGTH_PROPS_STRING or
        VARIABLE_LENGTH_PROPS_STRING.
        __substg1.0_N)r   upper_getTypedStream_getTypedProperty)r<   id_typer   foundresults         rE   _getTypedDatazMSGFile._getTypedData   s_     	XXZ,,^b-@&%PvM 222u=ME6"6,,ri   c                    t        |       t        |       |j                         }|||z   fn| j                  D ]G  }|j	                  |      s| j                  |   }dt        |t              r|j                  fc S |fc S  y)ax  
        Gets the property with the specified id as the type that it
        is supposed to be. :param id: MUST be a 4 digit hexadecimal
        string.

        If you know for sure what type the property is before hand,
        you can specify it as being one of the strings in the
        constant FIXED_LENGTH_PROPS_STRING or
        VARIABLE_LENGTH_PROPS_STRING.
        TFN)r   r   rl   rW   
startswith
isinstancer   rN   )r<   
propertyIDrp   xprops        rE   rn   zMSGFile._getTypedProperty   s     	$5%%'
*/*;*u$&ATAT 	YA||J'**1-Jt_,MdjjXXSWXX	Y ri   c                    t        |       | j                  ||      }|||z   fn| j                         D ]  }|j                  |      s|j	                  d      dk(  s+| j                  |d      }t        |      dk(  r yg }|dd }|d   dk(  r0|d	v rt        |      d
z  }nQ|dk(  rt        |      dz  }n=|dv r	 | j                  |dd    j                  }nt!        dj                  ||            |dv rz| j#                  |dz   d      rt%        |      D ]V  }| j#                  |dz   t'        |d      z   d      s&|j)                  | j                  |dz   t'        |d      z   d             X nN|dv rJt+        ||t        j                  v rdn)|t        j                  v rd
n|t        j                  v rdnd      }|}dt-        t/        |d      || j0                  |      fc S  y#  t        j                  dj                  |             t        |      |t        j                  v rdn)|t        j                  v rd
n|t        j                  v rdndz  }Y gxY w)am  
        Gets the contents of the specified stream as the type that
        it is supposed to be.

        Rather than the full filename, you should only feed this
        function the filename sans the type. So if the full name
        is "__substg1.0_001A001F", the filename this function
        should receive should be "__substg1.0_001A".

        If you know for sure what type the stream is before hand,
        you can specify it as being one of the strings in the
        constant FIXED_LENGTH_PROPS_STRING or
        VARIABLE_LENGTH_PROPS_STRING.

        If you have not specified the type, the type this function
        returns in many cases cannot be predicted. As such, when
        using this function it is best for you to check the type
        that it returns. If the function returns None, that means
        it could not find the stream specified.
        N-r   Fr   TN1)101F101E   1102   )10021003100410051007101410401048iz8Could not find matching VariableLengthProp for stream {}      zThe stream specified is of type {}. We don't currently understand exactly how this type works. If it is mandatory that you have the contents of this stream, please create an issue labled "NotImplementedError: _getTypedStream {}".)r   r   r   z	-00000000Tru   )r   r[   slistDirrv   findrI   r;   rW   
realLengthr'   r/   r`   r   MULTIPLE_2_BYTESMULTIPLE_4_BYTESMULTIPLE_8_BYTESNotImplementedErrorExistsranger   appendr	   r   intrg   )	r<   r:   r   rp   ry   contentsextrasstreamsys	            rE   rm   zMSGFile._getTypedStream   s   * 	5==62(-(9(U"$t}} 	^A||H%!&&+*;??1e4x=A%%"#R5C< 00"%h-1"4&"%h-1"4"bbF&*&9&9!BC&&A&L&LG
 2  3[  3b  3b  ch  jo  3p  q  q 88;;q;>%*7^ e#';;q3w1a/H%#P$*MM$//!c'IVWYZOB[]b2c$de "bb!'A[A[8[1fkox  pJ  pJ  gJab  UZ  ^g  ^x  ^x  Ux  PQ  ~@  "B#*Ys5"~xATATV\]]]9	^: F"LL)c)j)jkl)mn&)(mUiF`F`=`kpt}  uO  uO  lOfg  Z_  cl  c}  c}  Z}  UV  CE  'FGs   ?G++A0Ic                      y)z
        FOR INTERNAL USE ONLY! DO NOT CALL MANUALLY!

        Function to allow things like attachments in subclasses to have their own named properties.
        N )r<   entryrp   names       rE   _registerNamedPropertyzMSGFile._registerNamedProperty  s     	ri   c           	         | j                         D ]n  }|d   j                  d      s|d   j                  d      s,t        dt        |d d       z          t        dj	                  | j                  |                   p y )Nr   rd   rc   zDirectory: zContents: {})listDirendswithprintr0   r`   rI   )r<   dir_s     rE   debugzMSGFile.debug  so    LLN 	DDBx  (DH,=,=f,Emc$s)n45n++DOOD,ABC	Dri   c                 H    | j                  ||      }| j                  |      S )z?
        Checks if :param inp: exists in the msg file.
        r[   r\   r<   inpr   s      rE   r   zMSGFile.Exists  s#     mmC({{3ri   c                 z    | j                  ||      }| j                  |dz         xs | j                  |dz         S )zM
        Checks if string stream :param inp: exists in the msg file.
        rc   rd   r   r   s      rE   sExistszMSGFile.sExists  s9     mmC({{3<(EDKKf,EEri   c                 n   t        |       t        |       |j                         }|| j                  }|r| j                  ng }||j                  |       t        |      }|||z   n|}d}g }	| j                         D ]n  }
t        |
      t        |      kD  s|
t        |         j                  d|z         s<|
t        |         |	vsM|dz  }|	j                  |
t        |                p |D ]:  }|j                  |      sd}|	D ]  }|j                  |      sd} n |r6|dz  }< |dkD  |fS )a  
        Determines if the stream with the provided id exists in the location specified.
        If no location is specified, the root directory is searched. The return of this
        function is 2 values, the first being a boolean for if anything was found, and
        the second being how many were found.

        Because of how this function works, any folder that contains it's own
        "__properties_version1.0" file should have this function called from it's class.
        r   rk      FT)r   r   rl   rW   
prefixListr   r   r   r;   rv   r   )r<   ro   locationrp   r   propertiesInstancer   usableidfound_numberfound_streamsitemry   already_foundr   s                 rE   ExistsTypedPropertyzMSGFile.ExistsTypedProperty!  sT    	5XXZ%!%!4!4(.T__B
h'#J/
!&!22:LLN 	@D4y3z?*J(33NX4MNSWX[\fXgShp}S} A%L!((c*o)>?		@
 $ 	&A||H% %& Azz!}(, % A%L	& q <//ri   c                 >    t        |      }|r| j                  |z   }|S )z
        Changes paths so that they have the proper
        prefix (should :param prefix: be True) and
        are strings rather than lists or tuples.
        )r   r7   r   s      rE   r[   zMSGFile.fix_pathG  s$     c"--#%C
ri   c                 t   | j                  ||      }| j                  dk(  r|S | j                  j                  d      }|d   dk(  r|j                          g }|D ]Z  }d}t	        |      t	        |      k  rd}|r't        t	        |            D ]  }||   ||   k7  sd} |sJ|j                  |       \ |S )z^
        Replacement for OleFileIO.listdir that runs at the current prefix directory.
        r   r   r   TF)listdirr7   r5   r6   r;   r   r   )	r<   r   storagestempr   outry   goodr   s	            rE   r   zMSGFile.listDirR  s     ||GX.==BK$$S)":JJL 		AD1vV$s6{+ %Atvay($% 

1		 
ri   c                 ^    | j                  ||      D cg c]  }t        |       c}S c c}w )z
        Replacement for OleFileIO.listdir that runs at the current prefix directory.
        Returns a list of strings instead of lists.
        )r   r   )r<   r   r   ry   s       rE   r   zMSGFile.slistDiri  s(    
 -1LL(,KLq"LLLs   *c                 ^    t        dj                  | j                  j                              )Nz,Saving is not yet supported for the {} class)r   r`   	__class____name__)r<   argskwargss      rE   savezMSGFile.savep  s&    !"P"W"WX\XfXfXoXo"pqqri   c                     	 | j                   S # t        $ re | j                  j                  d      r4| j                  d   j                  dz  dk7  rd| _         | j                   cY S d| _         | j                   cY S w xY w)zO
        Returns a boolean telling if the strings are unicode encoded.
        340D0003i   r   TF)_MSGFile__bStringsUnicoderH   rW   has_keyrN   r<   s    rE   re   zMSGFile.areStringsUnicodes  s|    
	*))) 	*""**:6''
399GCI-1D*111%*D")))	*s    AA<&A<;A<c                     | j                   S )zt
        Returns the Attachment class being used, should you need to use it externally for whatever reason.
        )r    r   s    rE   r>   zMSGFile.attachmentClass  s    
 %%%ri   c                     | j                   S )a<  
        The behavior to follow when an attachment raises an exception. Will be one
        of the following values:
        ATTACHMENT_ERROR_THROW: Don't catch exceptions.
        ATTACHMENT_ERROR_NOT_IMPLEMENTED: Catch NotImplementedError exceptions.
        ATTACHMENT_ERROR_BROKEN: Catch all exceptions.
        )r$   r   s    rE   r@   zMSGFile.attachmentErrorBehavior  s     ---ri   c                 &    | j                  dd      S )z1
        The class type of the MSG file.
        
_classTypez__substg1.0_001A)rO   r   s    rE   	classTypezMSGFile.classType  s    
 |-?@@ri   c                 &    | j                  dd      S )z;
        The specified importance of the msg file.
        _importance00170003rY   r   s    rE   
importancezMSGFile.importance  s    
 &&}jAAri   c                     	 | j                   S # t        $ r\ t        | j                  d      | j                  dk(  rt
        j                  nt
        j                        | _         | j                   cY S w xY w)zO
        Returns the Properties instance used by the MSGFile instance.
        z__properties_version1.0r   )_proprH   r   rI   r   r   TYPE_MESSAGETYPE_MESSAGE_EMBEDr   s    rE   rW   zMSGFile.mainProperties  s`    
	:: 	#DOO4M$N>BkkR>OI$:$:U^UqUqsDJ::	s    A"A32A3c                 r    	 | j                   S # t        $ r t        |       | _         | j                   cY S w xY w)zC
        The main named properties instance for this file.
        )_MSGFile__namedPropertiesrH   r   r   s    rE   rQ   zMSGFile.named  s:    
	*))) 	*%*4[D")))	*s    %66c                     | j                   S )zn
        Returns None is the encoding has not been overriden, otherwise returns
        the encoding.
        )r*   r   s    rE   r?   zMSGFile.overrideEncoding  s     &&&ri   c                     | j                   S )z
        Returns the message path if generated from a file,
        otherwise returns the data used to generate the
        Message instance.
        )r   r   s    rE   r=   zMSGFile.path  s     {{ri   c                     | j                   S )za
        Returns the prefix of the Message instance.
        Intended for developer use.
        )r7   r   s    rE   r   zMSGFile.prefix  s     }}ri   c                 @    t        j                  | j                        S )zf
        Returns the prefix list of the Message instance.
        Intended for developer use.
        )copydeepcopyr8   r   s    rE   r   zMSGFile.prefixList  s     }}T..//ri   c                 &    | j                  dd      S )z9
        The specified priority of the msg file.
        	_priority00260003r   r   s    rE   priorityzMSGFile.priority  s    
 &&{J??ri   c                 &    | j                  dd      S )z<
        The specified sensitivity of the msg file.
        _sensitivity00360003r   r   s    rE   sensitivityzMSGFile.sensitivity  s    
 &&~zBBri   c                 2   	 | j                   S # t        $ r | j                  rd| _         | j                   cY S | j                  j	                  d      st        d      | j                  d   j                  }t        |      | _         | j                   cY S w xY w)Nz	utf-16-le3FFD0003zEncoding property not found)r)   rH   re   rW   r   r   rN   r
   )r<   encs     rE   rg   zMSGFile.stringEncoding  s    	-((( 	- %%(3%,,, **22:>./LMM))*5;;(7(<%,,,	-s    (BABB)T)NT)Nr}   )NNTN)TF)(r   
__module____qualname____doc__r   r   r!   r-   rO   rU   rY   rI   r9   rs   rn   rm   r   r   r   r   r   r[   r   r   r   propertyre   r>   r@   r   r   rW   rQ   r?   r=   r   r   r   r   rg   r   ri   rE   r   r      s    ')JSWlp  MV  Mm  Mm A!F 
L&-((4lD F$0L	.Mr * * & & . . A A B B 	 	 * * ' '     0 0 @ @ C C - -ri   r   )%r%   r   loggingr+   extract_msgr   extract_msg.attachmentr   extract_msg.namedr   extract_msg.propr   r   extract_msg.propertiesr   extract_msg.utilsr	   r
   r   r   r   r   r   r   r   r   r   extract_msg.exceptionsr   r   	getLoggerr   r'   
addHandlerNullHandlerr,   r   r   ri   rE   <module>r      s}        ! - # @ - s  s  s  s O 
		8	$   %'%%' (e-g e-ri   