
    Zi                       S SK Jr   / SQ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	S SK
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S SK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S SKrS SKrS SKrS SKJr  S SKJrJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)J*r*  SSK+J,r,  SSK-J.r.  SS	K/J0r0J1r1J2r2J3r3J4r4J5r5J6r6  \)(       a  SS
K7J8r8  SSK9J:r:  \Rv                  " \<5      r=\=R}                  \R~                  " 5       5        \R                  " SS5        \(" S5      rAS;S jrBS;S jrCS<S jrDS<S jrES=S jrFS>S jrGS?S jrHS@S jrISAS jrJSBS jrKSCS jrLSDS jrMSES jrNSFS jrOSGS jrPSHS jrQSIS jrRSJS  jrSSKS! jrTSLS" jrUSMS# jrVSNS$ jrWSOS% jrXSPS& jrYSQS' jrZSRS( jr[SSS) jr\STS* jr]SJS+ jr^SJS, jr_S\R                  SS-S.4 SUS/ jjraSVS0 jrbSWS1 jrcSWS2 jrdSWS3 jreSXS4 jrfSYS5 jrgSZS6 jrhS[S7 jriS\S8 jrjS]S9 jrkS^S: jrlg)_    )annotations)&addNumToDiraddNumToZipDirbitwiseAdjustbitwiseAdjustedAndbytesToGuidceilDivcloneOleFilecreateZipOpendecodeRfc2047dictGetCasedKeydividefiletimeToDatetimefiletimeToUtcfindWkfromTimeStampgetCommandArgsguessEncodinghtmlSanitizeinputToBytesinputToMsgPathinputToStringisEncapsulatedRtfmakeWeakRefmsgPathToString	parseTypeprepareFilenameroundUprtfSanitizeHtmlrtfSanitizePlainsetupLoggingstripRtftryGetMimetypeunsignedToSignedInt	unwrapMsgunwrapMultipartvalidateHtmlverifyPropertyId
verifyTypeN)escape)AnyAnyStrCallableDictIterableListOptionalSequenceSupportsBytesTypeVarTYPE_CHECKINGUnion   )	constants)AttachmentType)ConversionErrorDependencyErrorExecutableNotFoundIncompatibleOptionsErrorInvalidPropertyIdErrorTZErrorUnknownTypeError)MSGFile)AttachmentBase   	DEVELOPER_Tc                    [        SS5       H>  n U R                  U R                  SU S3-   5      n[        R                  " U5        Us  $    g! [
         a  n SnAMS  SnAff = f)8
Attempt to create the directory with a '(n)' appended.
   d    ()N)range	with_namenameosmakedirs	Exception)dirNamei
newDirNamees       k/var/www/eduai.edurigo.com/question_generate/ques_gen_env/lib/python3.13/site-packages/extract_msg/utils.pyr   r   g   sf     1c]	 **7<<Bqc)+CDJKK
#	    		s   9A
A% A%c                  ^ [        SS5       Hn  nU R                  U R                  SU S3-   5      n[        U5      R	                  S5      S-   m[        U4S jUR                  5        5       5      (       a  Ml  Us  $    g)rG   rH   rI   rJ   rK   /c              3  D   >#    U  H  oR                  T5      v   M     g 7fN)
startswith).0xpathCompares     rV   	<genexpr>!addNumToZipDir.<locals>.<genexpr>|   s     Fo<<,,os    N)rL   rM   rN   strrstripanynamelist)rR   _ziprS   rT   r^   s       @rV   r   r   u   sq     1c]&&w||1#Qi'?@
*o,,S1C7FdmmoFFF	 
     c                j    US:  a  [        S5      eU [        U5      SSS2   R                  S5      -	  $ )aP  
Uses a given mask to adjust the location of bits after an operation like
bitwise AND.

This is useful for things like flags where you are trying to get a small
portion of a larger number. Say for example, you had the number ``0xED``
(``0b11101101``) and you needed the adjusted result of the AND operation
with ``0x70`` (``0b01110000``). The result of the AND operation
(``0b01100000``) and the mask used to get it (``0x70``) are given to this
function and the adjustment will be done automatically.

:param mask: MUST be greater than 0.

:raises ValueError: The mask is not greater than 0.
r7   Mask MUST be greater than 0N1
ValueErrorbinindexinpmasks     rV   r   r      s9      ax677#d)DbD/'',,,rf   c                n    US:  a  [        S5      eX-  [        U5      SSS2   R                  S5      -	  $ )z
Preforms the bitwise AND operation between :param inp: and :param mask: and
adjusts the results based on the rules of :func:`bitwiseAdjust`.

:raises ValueError: The mask is not greater than 0.
r7   rh   Nri   rj   rk   ro   s     rV   r   r      s;     ax677J3t9TrT?00555rf   c                   [         R                  R                  R                  U 5      nSUS   S SUS   S SUS   S SUS   S	S R	                  5       R                  5        SUS   SS	 R	                  5       R                  5        S
3$ )z&
Converts a bytes instance to a GUID.
{r   08X-r7   04XrH      N})r8   stST_GUIDunpackhexupper)
bytesInputguidValss     rV   r   r      s     ||##**:6HC (1+c!2!HQK3DAhqkRTSToFYFYF[FaFaFcEddefnopfqrsrtfufyfyf{  gB  gB  gD  fE  EG  H  Hrf   c                    X* -  * $ )z
Returns the ``int`` from the ceiling division of n / d.

ONLY use ``int``\s as inputs to this function.

For ``int``\s, this is faster and more accurate for numbers outside the
precision range of ``float``.
 )nds     rV   r	   r	      s     "W:rf   c                    SSK Jn  [        R                  " U 5       nU" 5       nUR	                  U5        SSS5        WR                  U5        g! , (       d  f       N = f)zq
Uses the ``OleWriter`` class to clone the specified OLE file into a new
location.

Mainly designed for testing.
r7   )	OleWriterN)
ole_writerr   olefile	OleFileIOfromOleFilewrite)
sourcePath
outputPathr   fwriters        rV   r
   r
      sH     &			:	&!1 
' LL	 
'	&s   A
Ac                   ^  SU 4S jjnU$ )z
Creates a wrapper for the open function of a ZipFile that will automatically
set the current date as the modified time to the current time.
c                   > US:X  aD  [         R                  " U [        R                  R                  5       R	                  5       S S 5      n T" X/UQ70 UD6$ )Nw   )zipfileZipInfodatetimenow	timetuple)rN   modeargskwargsfuncs       rV   _opencreateZipOpen.<locals>._open   sN    3;??4):):)>)>)@)J)J)LRa)PQDD0000rf   )rr   )r   r   s   ` rV   r   r      s    
1 Lrf   c                    U R                  SS5      n SR                  S [        R                  R	                  U 5       5       5      $ )z>
Decodes text encoded using the method specified in RFC 2047.

 c              3     #    U  HB  n[        US    [        5      (       a   US    R                  US   =(       d    S5      OUS    v   MD     g7f)r   r7   zraw-unicode-escapeN)
isinstancebytesdecoder\   r]   s     rV   r_    decodeRfc2047.<locals>.<genexpr>   sK      4A 6@!e5L5L!AaD001RSTURVV4s   A
A)replacejoinemailheaderdecode_header)encodeds    rV   r   r      sC    
 oofb)G 77 ++G4  rf   c                ~   ^  [        U4S jU R                  5        5       5      $ ! [         a    [        T5      ef = f)zT
Retrieves the key from the dictionary with the proper casing using a
caseless key.
c              3  n   >#    U  H*  oR                  5       TR                  5       :X  d  M&  Uv   M,     g 7frZ   )lower)r\   r]   keys     rV   r_   "dictGetCasedKey.<locals>.<genexpr>   s$     I1	SYY[0HQQs   %5	5)nextkeysStopIterationKeyError)_dictr   s    `rV   r   r      s8    
I

IJJ sms   "& <c                |    [        [        [        U 5      U5      5       Vs/ s H  o X-  XS-   -   PM     sn$ s  snf )a2  
Divides a string into multiple substrings of equal length.

If there is not enough for the last substring to be equal, it will simply
use the rest of the string. Can also be used for things like lists and
tuples.

:param string: The string to be divided.
:param length: The length of each division.
:returns: list containing the divided strings.

Example:

.. code-block:: python

    >>> a = divide('Hello World!', 2)
    >>> print(a)
    ['He', 'll', 'o ', 'Wo', 'rl', 'd!']
    >>> a = divide('Hello World!', 5)
    >>> print(a)
    ['Hello', ' Worl', 'd!']
r7   )rL   r	   len)stringlengthr]   s      rV   r   r      s=    . :?ws6{TZ?[9\]9\A6:fA./9\]]]s   9c           
         U S:  a  [         R                   R                  U 5      $ U S:X  a  SSKJn  U" SSSSS	5      nXl        U$ U S
:X  a  [
        R                  $ U S:  a:  SSKJn  U" SSSS5      n U[        R                  " [        U 5      S9-  nXl        U$ ['        [        U 5      5      $ ! [         ac    UR                  nU" UR                  UR                  UR                  UR                  UR                   UR"                  UR$                  5      n Nf = f! [(         a    e [*         a    [-        S[        U 5       SU  S35      ef = f)aZ  
Converts a filetime into a ``datetime``.

Some values have specialized meanings, listed below:

* ``915151392000000000``: December 31, 4500, representing a null time.
  Returns an instance of extract_msg.null_date.NullDate.
* ``915046235400000000``: 23:59 on August 31, 4500, representing a null
  time. Returns extract_msg.constants.NULL_DATE.
     }*{Gl    @G^er7   )NullDatei           ;   l    R&lel     bnei  )secondszTimestamp value of z (raw: z^) caused an exception. This was probably caused by the time stamp being too far in the future.)r   filetime2datetime	null_dater   filetimer8   	NULL_DATEr   	timedeltar   OverflowErrormaxyearmonthdayhourminutesecondmicrosecondr   r?   rQ   rl   )rawTimer   datems       rV   r   r     s^   &w'' ??44W==** ,D"b"b1D#MK**&&&))+D!Q*Dc**]75KLL $MK w!788 ! c HH!((TUTaTabc   w.}W/E.FggY  Wu  v  w  	wwsG   $D! D! D! D! 5 B1 D! D! 1A*DD! DD! !0Ec                    U S-
  S-  $ )z,
Converts a FILETIME into a unix timestamp.
r   g    cAr   rp   s    rV   r   r   @  s     $$
22rf   c                0   U (       af  [         R                  R                  U 5      (       a7  [         R                  " U [         R                  5      (       a  U $ [        S5      e[        S5      e[        R                  " S5      nU(       a  U$ [        S5      e)z
Attempt to find the path of the wkhtmltopdf executable.

:param path: If provided, the function will verify that it is executable
    and returns the path if it is.

:raises ExecutableNotFound: A valid executable could not be found.
zAPath provided was not a valid executable (execution bit not set).z6Path provided was not a valid executable (not a file).wkhtmltopdfzCould not find wkhtmltopdf.)rO   pathisfileaccessX_OKr<   shutilwhich)r   	candidates     rV   r   r   G  so     77>>$yyrww''()lmm$%]^^]+I
:
;;rf   c                     [         R                  " 5       n[        R                  R                  X5      $ ! [         a    [        S5      ef = f)zK
Returns a ``datetime`` from the UTC timestamp given the current timezone.
zzError occured using tzlocal. If you are seeing this, this is likely a problem with your installation ot tzlocal or tzdata.)tzlocalget_localzonerQ   r?   r   fromtimestamp)stamptzs     rV   r   r   a  sY    U""$ **555  U   S  U  	U	Us	   6 Ac           	        [         R                  " [        R                  SS9nUR	                  5       nUR	                  5       nUR	                  SS9nUR                  SSSSS	S
9  UR                  SSSSS
9  UR                  SSSSS
9  UR                  SSSSSSS9  UR                  SSSS9  UR                  SSSS9  UR                  SS S!S9  UR                  S"S#SS$S
9  UR                  S%S&SS'S
9  UR                  S(S)SS*S
9  UR                  S+S,SS-S
9  UR                  S.S/S0S9  UR                  S1S2S3S4S59  UR                  S6S7SS8S
9  UR                  S9S:S;S<S=9  UR                  S>S?SS@S
9  UR                  SASBSSCS
9  UR                  SDSESSFS
9  UR                  SGSHSSIS
9  UR                  SJSKSLS9  UR                  SMSNSSOS
9  UR                  SPSQSSRS
9  UR                  SSSTSSUS
9  UR                  SVSWSSXS
9  UR                  SYSZSS[S
9  UR                  S\S]SS^S
9  UR                  S_S`SSaS
9  UR                  SbScSdSSeS
9  UR                  SfSgShS9  UR                  SiSjSkSSlS
9  UR                  SmSnSSoS
9  UR                  SpSqSSrS
9  UR                  SsStSuSSvS
9  UR                  SwSxS3/ SySz9  UR                  U 5      nUR                  (       aA  UR                  R                  [        R                  R                  R                  5       5        UR                  (       a  UR                  (       a  [        S{5      eUR                   (       a  UR"                  =(       d    S|Ul        UR$                  (       a  / nUR$                   H  nUR'                  S}5      (       a	  S~USS -   nOUR'                  S5      (       a  SUS|S -   nUR)                  S5      n[+        U5      S|:X  a  UR                  U5        Ms  UR                  US   5        UR                  SR-                  US|S 5      5        M     Xel        UR.                  (       a*  SUl        SUl        SUl        SUl        SUl        SUl        UR<                  (       a  UR                  (       a  [        S5      eUR                  (       a  [        S5      e/ n	UR                   H  n
U	[<        R<                  " U
5      -  n	M     [+        U	5      S:X  a  [?        S5      eXl        UR                  (       a$  [+        UR                  5      S|:  a  [        S5      eUR"                  S:X  a  [@        RB                  Ul"        OSUR"                  S|:X  a  [@        RF                  Ul"        O-UR"                  S:X  a  [@        RH                  Ul"        OSUl"        UR                  (       a  URJ                  (       d  [?        S5      eU$ )aK  
Parse command-line arguments.

:raises IncompatibleOptionsError: Some options were provided that are
    incompatible.
:raises ValueError: Something about the options was invalid. This could mean
    an option was specified that requires another option or it could mean
    that an option was looking for data that was not found.
extract_msg)descriptionprogT)requiredz--use-content-idz--cidcid
store_truez_Save attachments by their Content ID, if they have one. Useful when working with the HTML body.)destactionhelpz--jsonjsonz&Changes to write output files as json.z--file-loggingfileLoggingz0Enables file logging. Implies --verbose level 1.z-vz	--verboseverbosecountr   zFTurns on console logging. Specify more than once for higher verbosity.)r   r   defaultr   z--loglogz&Set the path to write the file log to.)r   r   z--config
configPathz-Set the path to load the logging config from.z--outoutPathzJSet the folder to use for the program output. (Default: Current directory)z--use-filenameuseFilenamezBSets whether the name of each output is based on the MSG filename.z--dump-stdout
dumpStdoutz^Tells the program to dump the message body (plain text) to stdout. Overrides saving arguments.z--htmlhtmlzLSets whether the output should be HTML. If this is not possible, will error.z--pdfpdfz=Saves the body as a PDF. If this is not possible, will error.z	--wk-pathwkPathz+Overrides the path for finding wkhtmltopdf.z--wk-options	wkOptions*zSets additional options to be used in wkhtmltopdf. Should be a series of options and values, replacing the - or -- in the beginning with + or ++, respectively. For example: --wk-options "+O Landscape")r   nargsr   z--prepared-htmlpreparedHtmlzoWhen used in conjunction with --html, sets whether the HTML output should be prepared for embedded attachments.z	--charsetcharsetutf-8zMCharacter set to use for the prepared HTML in the added tag. (Default: utf-8))r   r   r   z--rawrawzKSets whether the output should be raw. If this is not possible, will error.z--rtfrtfzKSets whether the output should be RTF. If this is not possible, will error.z--allow-fallbackallowFallbackz[Tells the program to fallback to a different save type if the selected one is not possible.z--skip-body-not-foundskipBodyNotFoundzQSkips saving the body if the body cannot be found, rather than throwing an error.z--zipzipz%Path to use for saving to a zip file.z--save-header
saveHeaderz$Store the header in a separate file.z--attachments-onlyattachmentsOnlyz2Specify to only save attachments from an MSG file.z--skip-hidden
skipHiddenzJSkips any attachment marked as hidden (usually ones embedded in the body).z--no-folders	noFolderszvStores everything in the location specified by --out. Requires --attachments-only and is incompatible with --out-name.z--skip-embeddedskipEmbeddedz5Skips all embedded MSG files when saving attachments.z--extract-embeddedextractEmbeddedzUExtracts the embedded MSG files as MSG files instead of running their save functions.z--overwrite-existingoverwriteExistingzDisables filename conflict resolution code for attachments when saving a file, causing files to be overwriten if two attachments with the same filename are on an MSG file.z--skip-not-implementedz	--skip-niskipNotImplementedz[Skips any attachments that are not implemented, allowing saving of the rest of the message.z
--out-nameoutNamezaName to be used with saving the file output. Cannot be used if you are saving more than one file.z--globz
--wildcardglobzFInterpret all paths as having wildcards. Incompatible with --out-name.z--ignore-rtfdeignoreRtfDeErrorsz}Ignores all errors thrown from RTFDE when trying to save. Useful for allowing fallback to continue when an exception happens.z
--progressprogresszIShows what file the program is currently working on during it's progress.z-sz--stdinstdinz:Read file from stdin (only works with one file at a time).msgsmsgzAn MSG file to be parsed.)metavarr   r   r   z/--out-name is not compatible with --no-folders.r7   z++z--rH   N+rv    Fz1--out-name is not supported when using wildcards.z.--stdin is not supported with using wildcards.z;Could not find any MSG files using the specified wildcards.z;--out-name is not supported when saving multiple MSG files.rC   z4--no-folders requires the --attachments-only option.)&argparseArgumentParserr8   MAINDOCadd_mutually_exclusive_groupadd_argument
parse_argsr  r  appendsysbufferreadr  r  r=   r   r   r   r[   splitr   r   r   r   r   r  r   r   r   r  rl   loggingERRORlogLevelWARNINGINFOr
  )r   parser	outFormatinputFormat	inputTypeoptionsr   optionr%  	fileListsr   s              rV   r   r   o  s    $$93D3D][F335I557K33t3DI
*G%~  @ 8&E  G (}\O  Q k	'STe  g eE  G 
L  N ii  k (}\a  c l<}   8&k  m 7| _  a (J  L [ h  i )| O  P )Wl  n 7| m  o 7| m  o *z  | /6HQ]p  r eD  F l<C  E /6GP\ T  V l<i  k [ V  W )|T  V ,3D\t  v .5HQ] K  L 0+DXamz  | \	 A  B X|&e  g (/B< ]  ^ :li  k 4Y  [ 65R8  : %G}}CII,,11347,,&'XYY!//.Q 	''F  &&qr
*""3''vabz) LL%E5zQ  (  q*  %)!45 (  &
 #||??*+^__==*+[\\	LLD4(I ! y>QZ[[  3w||,q0&'dee !"==	A	"??	A	"<< !8!8OPPNrf   c                    SSK nSnS U R                  SSS5       5        He  nUR	                  5       R                  S5      (       a    g	UR	                  5       R                  S
5      (       d  MO  X R                  U5      S-   -  nMg      U(       a  UR                  U5      =nS   S:  a  gUS   $ ! [         a    [        S5      ef = f! [         a  n[        SU 35      eSnAff = f)a  
Analyzes the strings on an MSG file and attempts to form a consensus about the encoding based on the top-level strings.

Returns ``None`` if no consensus could be formed.

:raises DependencyError: ``chardet`` is not installed or could not be used
    properly.
r   NzECannot guess the encoding of an MSG file if chardet is not installed.rf   c              3  N   #    U  H  n[        U5      S :X  d  M  US   v   M     g7f)r7   r   Nr   r   s     rV   r_    guessEncoding.<locals>.<genexpr>A  s"     N>!#a&A+1>s   %%TF001f	utf-16-le001e   

confidenceg      ?encodingzFailed to detect encoding: )	chardetImportErrorr;   listDirr   endswith	getStreamdetectrQ   )r  r<  datarN   resultrU   s         rV   r   r   2  s    g DNs{{4>N::<  ((ZZ\""6**MM$'%//D OA'.."66EKj!!  geffg   A ;A3?@@As)   B3 !C .C 3C	
C)C$$C)c                    [        U 5      n U R                  SS5      R                  SS5      n [        R                  R                  R                  S U 5      n U $ )z
Santizes the input for injection into an HTML string.

Converts charactersinto forms that will not be misinterpreted, if
necessary.
r   
z<br/>c                <    S[        U R                  S5      5      -  $ )Nz&nbsp;r   )r   group)spacess    rV   <lambda>htmlSanitize.<locals>.<lambda>_  s    (SVWEY:Yrf   )
htmlEscaper   r8   reHTML_SAN_SPACEsubr   s    rV   r   r   Q  sQ     S/C ++fd
#
+
+D'
:C ,,
%
%
)
)+Y[^
_CJrf   c                    [        U [        5      (       a  U $ [        U [        5      (       a  U R                  U5      $ U c  g[	        U S5      (       a  [        U 5      $ [        S5      e)a  
Converts the input into bytes.

:raises ConversionError: The input cannot be converted.
:raises UnicodeEncodeError: The input was a str but the encoding was not
    valid.
:raises TypeError: The input has a __bytes__ method, but it failed.
:raises ValueError: Same as above.
rf   	__bytes__zCannot convert to bytes.)r   r   ra   encodehasattrr:   )objr;  s     rV   r   r   d  s]     #u
#szz(##
{sK  Sz
4
55rf   c                d   [        U [        [        45      (       a  SR                  U 5      n [	        U S5      n SU ;   d  SU ;   a  [        S5      eU R                  SS5      R                  S5       Vs/ s H  o(       d  M  UPM     nn[        S U 5       5      (       a  [        S5      eU$ s  snf )	zc
Converts the input into an msg path.

:raises ValueError: The path contains an illegal character.
rX   r  :!z1Illegal character ("!" or ":") found in MSG path.\c              3  >   #    U  H  n[        U5      S :  v   M     g7f)r   Nr4  r   s     rV   r_   !inputToMsgPath.<locals>.<genexpr>  s     
$13q6B;s   z5Path segments must not be greater than 31 characters.)	r   listtupler   r   rl   r   r%  rc   )rp   r]   rets      rV   r   r   z  s     #e}%%hhsm
W
%C
 czSCZLMMkk$,2237
=7117C
= 
$
$$$PQQJ >s   3
B-B-c                    [        U [        5      (       a  U $ [        U [        5      (       a  U R                  U5      $ U c  g[	        S5      e)z\
Converts the input into a string.

:raises ConversionError: The input cannot be converted.
r   zCannot convert to str type.)r   ra   r   r   r:   )bytesInputVarr;  s     rV   r   r     sJ     -%%	M5	)	)##H--		;<<rf   c                    SU ;   $ )z
Checks if the RTF data has encapsulated HTML.

Currently the detection is made to be *extremly* basic, but this will work
for now. In the future this will be fixed so that literal text in the body
of a message won't cause false detection.
s	   \fromhtmlr   r   s    rV   r   r     s     Crf   c                6    U c  g[         R                  " U 5      $ )zT
Attempts to return a weak reference to the object, returning None if not
possible.
N)weakrefref)rS  s    rV   r   r     s    
 {{{3rf   c                    U S:X  a  gU S:X  a  gU S:  a  U  S3$ U S:X  a  gU S-  S:X  a  U S-   S3$ U S	:  a  U S
:X  a  gSU S-
   S3$ U S-  S:X  a  U S-   S3$ U S-   SU S-   S3$ )z8
Converts the number of minutes into a duration string.
r   z0 hoursr7   z1 minute<   z minutesz1 hourz hoursx   =   z1 hour 1 minutez1 hour z hours 1 minutez hours r   )minutess    rV   minutesToDurationStrrh    s     !|	A	2(##	B	2	R-''	3b=%Wr\N(33	2	R-00R-"~X>>rf   c                r    [        U [        5      (       d  SR                  U 5      n U R                  SS5      $ )zT
Converts an MSG path (one of the internal paths inside an MSG file) into a
string.
rX   rW  )r   ra   r   r   r   s    rV   r   r     s/    
 c3hhsm;;tS!!rf   c           
     6  ^ Tn[        U5      nU S:X  a   U$ U S:X  a  US:w  a  [        R                  S5        gU S:X  a/  [        R                  R
                  R                  USS 5      S   $ U S:X  a/  [        R                  R                  R                  USS 5      S   $ U S:X  a/  [        R                  R                  R                  USS 5      S   $ U S	:X  a,  [        R                  R                  R                  U5      S   $ U S
:X  aC  [        R                  " [        R                  R                  R                  U5      S   5      S-  $ U S:X  aQ  [        R                  R                  R                  U5      S   n[        R                  [        R                  " US9-   $ U S:X  aB  SSKJnJn  [        R                  R                  R                  USS 5      S   n U" U5      nU$ U S:X  a2  [        R                  R
                  R                  USS 5      S   S:g  $ U S:X  a  [)        S5      eU S:X  a,  [        R                  R*                  R                  U5      S   $ U S:X  a  UR-                  U5      $ U S:X  a  UR-                  S5      $ U S:X  a7  [        R                  R*                  R                  U5      S   n[/        U5      $ U S:X  a  [1        U5      $ U S:X  aO  [        R                  R
                  R                  USS 5      S   n	US   S:X  a  SSKJn
  U
" U5      $ XSU	S-    4$ U S:X  a  [)        S 5      eU S!:X  a  [)        S"5      eU S#:X  a  U$ U S$-  S$:X  Ga  U S%;   a  U Vs/ s H  oR-                  U5      SS& PM     nn[6        R                  " S'[        U5       S(3T5      n[        U5      nX:  a'  [        R                  S)U S*US:w  a  S+OS, S-U S.35        [9        U5       H?  u  pX   [        U5      :w  d  M  [        R                  S/X    S-[        U5       S.35        MA     U$ U S0:X  a  [:        R<                  " U5      n[?        U4S1 j[A        [        T5      S2-  5       5       5      n[        U5      nX:  a'  [        R                  S)U S*US:w  a  S+OS, S-U S.35        [9        U5       H?  u  pX   [        U5      :w  d  M  [        R                  S/X    S-[        U5       S.35        MA     U$ U S3;   Ga  T[        U5      :w  a0  [        R                  S)T S4TS:X  a  S5OS6 S-[        U5       S.35        U S7:X  a  [?        S8 U 5       5      $ U S9:X  a  [?        S: U 5       5      $ U S;:X  a  [?        S< U 5       5      $ U S=:X  a  [?        S> U 5       5      $ U S?:X  a  S@ U 5       n[?        SA U 5       5      $ U SB:X  a  [?        SC U 5       5      $ U SD:X  a  [?        SE U 5       5      $ U SF:X  a  [?        SG U 5       5      $  U$ [)        SHU  SIU  SJ35      eU$ ! [&         aO    [        R                  SU S35         [        R                  SU" U5       S35         U$ ! [&         a      U$ f = ff = fs  snf )Ka  
Converts the data in :param stream: to a much more accurate type, specified
by :param _type:.

:param _type: The data's type.
:param stream: The data to be converted.
:param encoding: The encoding to be used for regular strings.
:param extras: Used in the case of types like PtypMultipleString. For that
    example, extras should be a list of the bytes from rest of the streams.

:raises NotImplementedError: The type has no current support. Most of these
    types have no documentation in [MS-OXMSG].
r   r7   s           z1Property type is PtypNull, but is not equal to 0.NrH   rx      rC   r   i'     days
   )	ErrorCodeErrorCodeTypezEError type found that was not from Additional Error Codes. Value was z+. You should report this to the developers.z$REPORT TO DEVELOPERS: Error type of z was found.      zmCurrent version of extract-msg does not support the parsing of PtypObject/PtypEmbeddedTable in this function.      r   r7  @   H      )ServerID   zParsing for type 0x00FD (PtypRestriction) has not yet been implmented. If you need this type, please create a new issue labeled "NotImplementedError: parseType 0x00FD PtypRestriction".   zParsing for type 0x00FE (PtypRuleAction) has not yet been implmented. If you need this type, please create a new issue labeled "NotImplementedError: parseType 0x00FE PtypRuleAction".i  i   )i  i  ri   <rS   z,Error while parsing multiple type. Expected z streamsr   z, got z. Ignoring.z3Error while parsing multiple type. Expected length i  c              3     >#    U  H=  n[         R                  R                  R                  TUS -  US -  S-    5      S   v   M?     g7f)   rk  r   Nr8   rz   
ST_LE_UI32r|   )r\   posstreams     rV   r_   parseType.<locals>.<genexpr>B  sB     x`wY\ILL33::6#a%Aa;PQRST`ws   AAr  )            @  H  z entryiesr  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr   N)r8   rz   
ST_LE_UI16r|   r   s     rV   r_   r  N  *     R6aY\\44;;A>qA6   9;r  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr  r  r   s     rV   r_   r  P  r  r  r  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr  )r8   rz   	ST_LE_F32r|   r   s     rV   r_   r  R  *     Q&QY\\33::1=a@&r  r  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr  r8   rz   	ST_LE_F64r|   r   s     rV   r_   r  T  r  r  r  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr  r  r   s     rV   r_   r  V  s*     Nv!),,0077:1=vr  c              3  l   #    U  H*  n[         R                  [        R                  " US 9-   v   M,     g7f)rm  N)r8   PYTPFLOATINGTIME_STARTr   r   )r\   amounts     rV   r_   r  W  s*     wpvflY==@R@RZ`@aapvs   24r  c              3  z   #    U  H1  n[         R                  R                  R                  U5      S    v   M3     g7fr  )r8   rz   
ST_LE_UI64r|   r   s     rV   r_   r  Y  r  r  r  c              3     #    U  H:  n[        [        R                  R                  R	                  U5      S    5      v   M<     g7fr  )r   r8   rz   r  r|   r   s     rV   r_   r  [  s5     aZ`UV]9<<+B+B+I+I!+LQ+OPPZ`s   AAr  c              3  8   #    U  H  n[        U5      v   M     g 7frZ   )r   r   s     rV   r_   r  ]  s     <V[^^Vs   zParsing for type zw has not yet been implmented. If you need this type, please create a new issue labeled "NotImplementedError: parseType z".)!r   loggerwarningr8   rz   r  r|   r  r  r  decimalDecimal	ST_LE_I64r  r   r   enumsrp  rq  rl   NotImplementedErrorr  r   r   r   structures.misc_idry  struct	enumeratecopydeepcopyr[  rL   )_typer  r;  extrasvaluelengthExtrasrp  rq  r   r   ry  r]   r\  lengthslengthLengthsr  valuess    `               rV   r   r     s#    Ev;Lb La 
&77NNNO	&||&&--eBQi8;;	&||&&--eBQi8;;	&||%%,,U2AY7::	&||%%,,U3A66	&	 6 6 = =e DaHIEQQ	&&&--e4Q7//(2D2DE2RRR	&3''..uRay9!<
	!%(E 	&||&&--eBQi8;q@@	&
 "  #R  S  	S	&||&&--e4Q77	&||H%%	&||K((	&,,))007:!'**	&5!!	&''..uRay9!<8q=4E?"519-..	&!  #]  ^  	^	&!  #[  \  	\	&	6	!$$4:;Fq88H%cr*FC;mmaCzOV<GLM+!Mm_\ckx|}k}dg  DF  dG  GM  NZ  M[  [f   g  h!&):Q'NN%XY`YcXddjknopkqjrr}#~ * Jf_--'Cx`efijpfquvfv`wxxGLM+!Mm_\ckx|}k}dg  DF  dG  GM  NZ  M[  [f   g  h!&):Q'NN%XY`YcXddjknopkqjrr}#~ * JVVV$!MfXUZbhlmbm[^sxZyy  AD  EK  AL  @M  MX   Y  ZR6RRRR6RRRQ&QQQQ&QQQNvNwpvwwwR6RRRaZ`aaa<V<<<  L &(9%  Ax  y~  x  A  'B  C  CLs  	NNbchbi  jU  V  W!EiPUFVEWWbcd   	` <s0   )X: =Z:#ZZ  
Z
ZZZc                N    SR                  S U  5       5      R                  5       $ )zU
Adjusts :param filename: so that it can succesfully be used as an actual
file name.
r   c              3  4   #    U  H  oS ;  d  M
  Uv   M     g7f)z
\/:*?"<>| Nr   )r\   rS   s     rV   r_   "prepareFilename.<locals>.<genexpr>i  s     Ih3H*H11hs   		)r   strip)filenames    rV   r   r   c  s"     77IhIIOOQQrf   c                    XU -
  U-  -   $ )z@
Rounds :param inp: up to the nearest multiple of :param mult:.
r   )rp   mults     rV   r   r   l  s     *$$$rf   c                   U (       d  gSnU  H  nS[        U5      s=::  a  S:  a.  O  O+US:X  a  US-  nM)  US:X  a  US-  nM6  US;   a  US	-  nX-  nMG  [        U5      S:  d  S[        U5      s=::  a  S
::  a  O  OUS[        U5      S 3-  nM  UR                  S5      nUSR                  S [        R                  " S[        U5      S-   S3U5       5       5      -  nM     U$ )z>
Sanitizes input to an RTF stream that has encapsulated HTML.
r          r|  z'{\*\htmltag84 &lt;}\htmlrtf <\htmlrtf0 >z&{\*\htmltag84 &gt;}\htmlrtf >\htmlrtf0rW  rt   ry   rW     \'02Xr7  c              3  .   #    U  H  nS U S3v   M     g7fz\u?Nr   r   s     rV   r_   "rtfSanitizeHtml.<locals>.<genexpr>       [2ZQA3aj2Z   rH   hordrQ  r   r  r|   r   rp   outputcharencs       rV   r   r   s  s     FT S  s{DDCC++dNFY^sc$i636CIc?++F ++k*Cbgg[&--!CHPQM?RS@TVY2Z[[[F) , Mrf   c                   U (       d  gSnU  H  nS[        U5      s=::  a  S:  a  O  OUS;   a  US-  nX-  nM-  [        U5      S:  d  S[        U5      s=::  a  S::  a  O  OUS[        U5      S 3-  nMi  UR                  S	5      nUSR                  S
 [        R                  " S[        U5      S-   S3U5       5       5      -  nM     U$ )z(
Sanitizes input to a plain RTF stream.
r   r  r  r  rW  r  r  r  r7  c              3  .   #    U  H  nS U S3v   M     g7fr  r   r   s     rV   r_   #rtfSanitizePlain.<locals>.<genexpr>  r  r  r|  rH   r  r  r  s       rV   r    r      s     FT S ''$NFY^sc$i636CIc?++F ++k*Cbgg[&--!CHPQM?RS@TVY2Z[[[F  Mrf   FEXTRACT_MSG_LOG_CFGc                   [         R                  " [        5      R                  S-  S-  n[        R
                  S:X  a  SnUS-  nO[        R
                  S:X  a  SnUS-  nU (       a  [         R                  " U 5      OUn U [         R                  " S	5      [         R                  " S
5      [         R                  " S5      U/nSnU H  n	U	R                  5       (       d  M  U	n  O   [        R                  " US5      n
U
(       a^  [        R                  R                  U
5      (       a:  [        R                  R                  U
5      (       a  [         R                  " U
5      nU(       dj  [        S5        [        S5        [        [        USS 5      5        [        R                  " US9  [        R                  " S[        R
                   S35        g[        US5       n[         R"                  " U5      nSSS5        WS    H  nSUS   U   ;   d  M  U(       a  [        R                  R%                  [        R                  R'                  U(       a  UO
US   U   S   5      5      =US   U   S'   n[         R                  " U5      R                  nUR                  (       d  [        R(                  " U5        M  M  WUS   U   S'   M      [        R*                  R-                  U5        [        R0                  " 5       R3                  U5        g! , (       d  f       GN$= f! [.         a   n[        S5        [        U5         SnAN\SnAff = f)a  
Setup logging configuration

:param defaultPath: Default path to use for the logging configuration file.
:param defaultLevel: Default logging level.
:param env_key: Environment variable name to search for, for setting logfile
    path.
:param enableFileLogging: Whether to use a file to log or not.

:returns: ``True`` if the configuration file was found and applied,
    ``False`` otherwise
rB  zlogging-configntNULzlogging-nt.jsonposixz	/dev/nullzlogging-posix.jsonzlogging.jsonz../logging.jsonz../../logging.jsonNz.Unable to find logging.json configuration filezMake sure a valid logging configuration file is referenced in the defaultPath argument, is inside the extract_msg install location, or is available at one of the following file-paths:r7   )levelzThe extract_msg logging configuration was not found - using a basic configuration.Please check the extract_msg installation directory for "logging-z.json".Frthandlersr  zDFailed to configure the logger. Did your installation get messed up?T)pathlibPath__file__parentrO   rN   existsgetenvr   r   printra   r&  basicConfigr  openr   load
expanduser
expandvarsrP   config
dictConfigrl   	getLoggersetLevel)defaultPathdefaultLevellogfileenableFileLoggingenv_keyshippedConfignullpathsr   r   r  r   r  r]   tmprU   s                   rV   r!   r!     s    LL*11F:=MMM	ww$**	G	--/:',,{+K 	^$&')*E D
D 
 IIgt$E&&277>>%+@+@||E">? - 	. 	c%)nL1 \\^\c\c[ddkm 	n	dD	Q1 
 J
+A.. :<'':L:LGG&&'wvj?QRS?TU_?`a;c cz"1%j1Cll3'..zzKK$ " 59z"1%j1  !!&)
   .+ 
	   TUas$   !LL' 
L$'
M1MMc                f   [         R                  R                  R                  [        U 5      n [         R                  R
                  R                  [        U 5      n [         R                  R                  R                  SU 5      n [         R                  R                  R                  SU 5      n U $ )zc
Cleans up RTF before sending it to RTFDE.

Attempts to find common sections of RTF data that will
rf   )r8   rL  RTF_BODY_STRIP_PRE_OPENrN  _stripRtfOpenHelperRTF_BODY_STRIP_PRE_CLOSE_stripRtfCloseHelperRTF_BODY_STRIP_INIT)rtfBodys    rV   r"   r"     s     ll22667JGTGll33778LgVGll..223@G ll..223@G Nrf   c                d    U R                  S5      =nR                  S5      S:  a  U$ SU;   a  U$ g)N   \g<0>s	   \htmlrtf0r7      \fs   \htmlrtf}\htmlrtf0 )expandr   matchr\  s     rV   r  r    s7    ||I&&--m<q@
}
#rf   c                6    SU R                  S5      =n;   a  U$ g)Nr  r  s   \htmlrtf{\htmlrtf0 )r   r  s     rV   r  r    s     i00#1
#rf   c                    U R                   nUR                  S5      UR                  S5      :w  d  UR                  S5      S:X  a  U$ UR                  S5      S:w  d  UR                  S5      S:w  a  U$ U$ )N   {   }r   s   \{ri   s   \})r   r   find)r  ress     rV   _stripRtfHelperr	    sh    
,,C yy#))D/)SYYt_-A
 xx2&!1R!7
 Jrf   c                Z   U(       a  U$ U R                   [        L aG   SSKn[        U R                  [
        [        45      (       a  UR                  U R                  SS9$  U$ U$ ! [         a    [        R                  S5         U$ [         a    [        R                  S5         U$ f = f)a  
Uses an optional dependency to try and get the mimetype of an attachment.

If the mimetype has already been found, the optional dependency does not
exist, or an error occurs in the optional dependency, then the provided
mimetype is returned.

:param att: The attachment to use for getting the mimetype.
:param mimetype: The mimetype acquired directly from an attachment stream.
    If this value evaluates to ``False``, the function will try to
    determine it.
r   NT)mimez]Mimetype not found on attachment, and `mime` dependency not installed. Won't try to generate.zCError occured while using python-magic. This error will be ignored.)dataTyper   magicr   rB  ra   from_bufferr=  r  inforQ   	exception)attmimetyper  s      rV   r#   r#   2  s      ||u		d#((S%L11(($(?? 2 O8O  	zKKxy
 O  	dbcO	ds   AA& &B*B*)B*c                    U S:  a  [        S5      eU S:  a  [        S5      e[        R                  R                  R	                  [        R                  R
                  R                  U 5      5      S   $ )zn
Convert the bits of an unsigned int (32-bit) to a signed int.

:raises ValueError: The number was not valid.
l    zValue is too large.r   zValue is already signed.)rl   r8   rz   
ST_SBO_I32r|   ST_SBO_UI32pack)uInts    rV   r$   r$   S  s`     j.//ax344<<""))),,*B*B*G*G*MNqQQrf   c                .   SSK Jn  / nU /n/ n/ n[        R                  " U 45      n[	        U5      S:  a  UR                  5       nUR                   H  nUR                  [        R                  [        R                  4;  a  UR                  U5        MD  UR                  U5        UR                  UR                  5        UR                  UR                  5        M     [        Xq5      (       a  XWR                  -  n[	        U5      S:  a  M  UUUUS.$ )a  
Takes a recursive message-attachment structure and unwraps it into a linear
dictionary for easy iteration.

Dictionary contains 4 keys: "attachments" for main message attachments, not
including embedded MSG files, "embedded" for attachments representing
embedded MSG files, "msg" for all MSG files (including the original in the
first index), and "raw_attachments" for raw attachments from signed
messages.
r7   )MessageSignedBaser   )attachmentsembeddedr  raw_attachments)msg_classesr  collectionsdequer   popleftr  typer9   MSGSIGNED_EMBEDDEDr!  rB  r   rawAttachments)	r  r  r  msgFilesr  r  	toProcesscurrentItemr  s	            rV   r%   r%   `  s     / KuHH
C !!3&)I
i.1
  '')**C xx 2 2N4R4RSS""3' $)  * + k55---C) i.1
. #	 rf   c                6   [         R                  R                  [         R                  R                  S.n[        U [         R                  R                  5      (       aQ  U R                  [         R                  R                  :X  a  U nO[         R                  " U R                  5       40 UD6nO[        U [         R                  R                  5      (       a&  [         R                  " U R                  5       40 UD6nOr[        U [        5      (       a  [         R                  " U 40 UD6nOE[        U [        5      (       a  [         R                  " U 40 UD6nO[        S[        U 5       S35      e/ n[        R                  " U45      n[!        U5      S:  a  UR#                  5       nUR%                  5       S:X  a_  UR'                  5       n[        U[(        5      (       a  UR+                  U5        O9[,        R.                  " S5        UR1                  U5        OUR1                  U5        [!        U5      S:  a  M  / nSnSn	U GHJ  n
SU
R3                  5       U
R5                  5       U
S.nU
R7                  5       n[        U[        5      (       a  O[        U[         R                  R                  5      (       a  UR                  5       nON[        U[        5      (       a!  UR9                  U
R;                  S	5      5      nO[        S
[        U5       S35      eXS'   US   (       a  UR1                  U5        M  US   S:X  a!  U(       a  [<        R/                  S5        UnGM   US   S:X  d  GM,  U	(       a  [<        R/                  S5        Un	GMM     UUU	S.$ )a  
Unwraps a recursive multipart structure into a dictionary of linear lists.

Similar to unwrapMsg, but for multipart. The dictionary contains 3 keys:
"attachments" which contains a list of ``dict``\s containing processed
attachment data as well as the Message instance associated with it,
"plain_body" which contains the plain text body, and "html_body" which
contains the HTML body.

For clarification, each instance of processed attachment data is a ``dict``
with keys identical to the args used for the ``SignedAttachment``
constructor. This makes it easy to expand for use in constructing a
``SignedAttachment``. The only argument missing is "msg" to ensure this function will not require one.

:param mp: The bytes that make up a multipart, the string that makes up a
    multipart, or a ``Message`` instance from the ``email`` module created
    from the multipart data to unwrap. If providing a ``Message`` instance,
    prefer it to be an instance of ``EmailMessage``. If you are doing so,
    make sure it's policy is default.
)_classpolicyzUnsupported type "z" provided to unwrapMultipart.r   	multipartzJFound multipart node that did not return a list. Appending as a data node.N)rB  rN   r  noder  z=Attempted to get bytes for attachment, but could not convert z
 to bytes.rB  rN   r  z
text/plainz.Found multiple candidates for plain text body.z	text/htmlz(Found multiple candidates for HTML body.)r  
plain_body	html_body)r   messageEmailMessager*  r   r   message_from_bytesas_bytesMessager   ra   message_from_string	TypeErrorr!  r  r  r   r   get_content_maintypeget_payloadrZ  extendr&  r  r!  get_filenameget_content_typeget_contentrQ  get_content_charsetr  )mp	genKwargs	mpMessage	dataNodesr&  r'  payloadr  	plainBodyhtmlBodyr,  
attachmentrB  s                rV   r&   r&     s   . --,,,,&&I
 "emm001199,,,I00L)LI	B--	.	.,,R[[]HiH		B		,,R=9=		B		--b>I>	,T"XJ6TUVV I!!9,/I i.1
'') ++-<!--/G '4((  ) lm  - [)! i.1
. KIH %%'--/	

 !dE""emm3344==?Dc"" ;;t77@AD [\`ae\f[ggqrss!6 fz*
#|3OPI
#{2IJHQ V # rf   c                    [         R                  " U SUS9nUR                  S5      (       a  UR                  S5      (       d  gg)z
Checks whether the HTML is considered valid.

To be valid, the HTML must, at minimum, contain an ``<html>`` tag, a
``<body>`` tag, and closing tags for each.
zhtml.parser)from_encodingr   bodyFT)bs4BeautifulSoupr  )r   r;  bss      rV   r'   r'     s7     
		4	IB776??"''&//rf   c                    [        U [        5      (       d  [        S5      e[        U 5      S:w  a  [        S5      e [	        U S5        g! [
         a    [        S5      ef = f)z
Determines whether a property ID is valid for certain functions.

Property IDs MUST be a 4 digit hexadecimal string. Property is valid if no
exception is raised.

:raises InvalidPropertyIdError: The ID is not a 4 digit hexadecimal number.
z'ID was not a 4 digit hexadecimal stringrk     N)r   ra   r>   r   intrl   )ids    rV   r(   r(   +  s`     b#$%NOO
2w!|$%NOOPB P$%NOOPs   A	 	Ac                |    U b9  U [         R                  ;  a$  U [         R                  ;  a  [        SU  S35      eggg)z|
Verifies that the type is valid.

Raises an exception if it is not.

:raises UnknownTypeError: The type is not recognized.
NzUnknown type .)r8   VARIABLE_LENGTH_PROPS_STRINGFIXED_LENGTH_PROPS_STRINGr@   )r  s    rV   r)   r)   >  sI     ???eS\SvSvFv"]5'#;<< Gw? rf   )rR   zpathlib.PathreturnzOptional[pathlib.Path])rp   rM  rq   rM  rS  rM  )r   r   rS  ra   )r   rM  r   rM  rS  rM  )rS  None)rS  r-   )r   ra   rS  ra   )r   zDict[str, Any]r   ra   rS  ra   )r   r,   r   rM  rS  zList[AnyStr])r   rM  rS  datetime.datetime)rp   rM  rS  floatrZ   )r   rV  rS  rU  )r   zSequence[str]rS  zargparse.Namespace)r  rA   rS  Optional[str])rp   ra   rS  ra   )rS  z&Union[bytes, None, str, SupportsBytes]r;  ra   rS  r   )rp   zconstants.MSG_PATHrS  z	List[str])r^  zOptional[Union[str, bytes]]r;  ra   rS  ra   )rp   r   rS  bool)rS  zOptional[_T]rS  z#Optional[weakref.ReferenceType[_T]])rg  rM  rS  ra   )rp   zUnion[str, Iterable[str]]rS  ra   )r  rM  r  zUnion[int, bytes]r;  ra   r  zSequence[bytes])r  ra   rS  ra   )rp   rM  r  rM  rS  rM  )r  rX  rS  rX  )r  r   rS  r   )r  zre.MatchrS  r   )r  rB   r  Union[str, None]rS  rY  )r  rM  rS  rM  )r  rA   rS  zDict[str, List])r=  z(Union[bytes, str, email.message.Message]rS  r.   )r   r   r;  rW  rS  rX  )rN  ra   rS  rT  )r  rW  rS  rT  )m
__future__r   __all__r  r  r  r   r  email.headerr   email.messageemail.policyr  r   r&  logging.configrO   r  rL  r   r  r"  ra  r   rH  r   r   r   r*   rK  typingr+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r   r8   r  r9   
exceptionsr:   r;   r<   r=   r>   r?   r@   msg_classes.msgrA   r  rB   r  __name__r  
addHandlerNullHandleraddLevelNamerE   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rh  r   r   r   r   r   r    WARNr!   r"   r  r  r	  r#   r$   r%   r&   r'   r(   r)   r   rf   rV   <module>rh     s   "
'T             	  	   
   
   %   
  !   (+			8	$   '%%' (   Q $T]	-*	6H	 $	^41wh3<46@FA>&6,4=   ?2"CLR%@0  $GLLDlq1K6:K\($$(B
R:z~B
P&
=rf   