
    Ϫf]                     ,   d Z ddlZddlZddlmZ ddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZmZ d Zdd	Z G d
 d      Z ee       G d de             Z ee
j(                         G d d             Z ee       G d de             Z G d de      Z ee
j(                         G d d             Z G d dej4                        Z ee       G d de             Z ee
j(                         G d d             Z ee       G d de             Zy)zD
Support for aliases(5) configuration files.

@author: Jp Calderone
    N)implementer)deferprotocolreactor)smtp)IAlias)failurelogc                 x   |j                  dd      D cg c]  }|j                          }}t        |      dk7  rd}||f}t        j                  ||z         y|\  }}	| j                  |j                         g       j                  t        t        j                  |	j                  d                   yc c}w )a  
    Parse a line from an aliases file.

    @type result: L{dict} mapping L{bytes} to L{list} of L{bytes}
    @param result: A dictionary mapping username to aliases to which
        the results of parsing the line are added.

    @type line: L{bytes}
    @param line: A line from an aliases file.

    @type filename: L{bytes}
    @param filename: The full or relative path to the aliases file.

    @type lineNo: L{int}
    @param lineNo: The position of the line within the aliases file.
    :      z+Invalid format on line %d of alias file %s.,N)	splitstriplenr
   err
setdefaultextendmapstr)
resultlinefilenamelineNoppartsfmtarguseraliass
             4/usr/lib/python3/dist-packages/twisted/mail/alias.pyhandler#      s    " !%

3 231QWWY3E3
5zQ;x c	e$**,+223syy%++cBR3ST 4s   B7c                    i }d}|t        |      }d}nt        |dd      }d}d}	 |D ]q  }|dz  }|j                         }|j                         j	                  d      r8|j	                  d	      s|j	                  d
      r||z   }`|rt        ||||       |}s 	 |r|j                          	 |rt        ||||       |j                         D ]  \  }}	t        |	| |      ||<    |S # |r|j                          w w xY w)a  
    Load a file containing email aliases.

    Lines in the file should be formatted like so::

         username: alias1, alias2, ..., aliasN

    Aliases beginning with a C{|} will be treated as programs, will be run, and
    the message will be written to their stdin.

    Aliases beginning with a C{:} will be treated as a file containing
    additional aliases for the username.

    Aliases beginning with a C{/} will be treated as the full pathname to a file
    to which the message will be appended.

    Aliases without a host part will be assumed to be addresses on localhost.

    If a username is specified multiple times, the aliases for each are joined
    together as if they had all been on one line.

    Lines beginning with a space or a tab are continuations of the previous
    line.

    Lines beginning with a C{#} are comments.

    @type domains: L{dict} mapping L{bytes} to L{IDomain} provider
    @param domains: A mapping of domain name to domain object.

    @type filename: L{bytes} or L{None}
    @param filename: The full or relative path to a file from which to load
        aliases. If omitted, the C{fp} parameter must be specified.

    @type fp: file-like object or L{None}
    @param fp: The file from which to load aliases. If specified,
        the C{filename} parameter is ignored.

    @rtype: L{dict} mapping L{bytes} to L{AliasGroup}
    @return: A mapping from username to group of aliases.
    FTnamez	<unknown>r    r   # 	)	opengetattrrstriplstrip
startswithr#   closeitems
AliasGroup)
domainsr   fpr   r/   iprevr   uas
             r"   loadAliasFiler8   3   s   R FE	z(^2v{3	AD 
	DFA;;=D{{}'',%)>d{6415
	 HHJvtXq) .1q'1-q	.M HHJ s   A6C+ +D c                   $    e Zd ZdZd Zd ZddZy)	AliasBasez
    The default base class for aliases.

    @ivar domains: See L{__init__}.

    @type original: L{Address}
    @ivar original: The original address being aliased.
    c                 F    || _         t        j                  |      | _        y)z
        @type domains: L{dict} mapping L{bytes} to L{IDomain} provider
        @param domains: A mapping of domain name to domain object.

        @type original: L{bytes}
        @param original: The original address being aliased.
        N)r2   r   Addressoriginal)selfr2   r=   s      r"   __init__zAliasBase.__init__   s     X.    c                 H    | j                   | j                  j                     S )z
        Return the domain associated with original address.

        @rtype: L{IDomain} provider
        @return: The domain for the original address.
        )r2   r=   domainr>   s    r"   rB   zAliasBase.domain   s     ||DMM0011r@   Nc                 b    |i }t        |       |v ryd|t        |       <   | j                         S aY  
        Map this alias to its ultimate destination.

        @type aliasmap: L{dict} mapping L{bytes} to L{AliasBase}
        @param aliasmap: A mapping of username to alias or group of aliases.

        @type memo: L{None} or L{dict} of L{AliasBase}
        @param memo: A record of the aliases already considered in the
            resolution process.  If provided, C{memo} is modified to include
            this alias.

        @rtype: L{IMessage <smtp.IMessage>} or L{None}
        @return: A message receiver for the ultimate destination or None for
            an invalid destination.
        N)r   createMessageReceiverr>   aliasmapmemos      r"   resolvezAliasBase.resolve   s9      <Dt9SY))++r@   N)__name__
__module____qualname____doc__r?   rB   rJ    r@   r"   r:   r:   {   s    	/2,r@   r:   c                   0    e Zd ZdZd ZdefdZd ZddZy)	AddressAliasz
    An alias which translates one email address into another.

    @type alias : L{Address}
    @ivar alias: The destination address.
    c                 d    t        j                  | g|  t        j                  |      | _        y)aQ  
        @type alias: L{Address}, L{User}, L{bytes} or object which can be
            converted into L{bytes}
        @param alias: The destination address.

        @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain}
            provider, (1) L{bytes}
        @param args: Arguments for L{AliasBase.__init__}.
        N)r:   r?   r   r<   r!   )r>   r!   argss      r"   r?   zAddressAlias.__init__   s'     	4'$'\\%(
r@   returnc                 "    d| j                    dS )z
        Build a string representation of this L{AddressAlias} instance.

        @rtype: L{bytes}
        @return: A string containing the destination address.
        z	<Address >)r!   rC   s    r"   __str__zAddressAlias.__str__   s     4::,a((r@   c                 f    | j                         j                  t        | j                              S )z
        Create a message receiver which delivers a message to
        the destination address.

        @rtype: L{IMessage <smtp.IMessage>} provider
        @return: A message receiver.
        )rB   existsr   r!   rC   s    r"   rF   z"AddressAlias.createMessageReceiver   s#     {{}##C

O44r@   Nc           	         |i }t        |       |v ryd|t        |       <   	  | j                         j                  t        j                  | j
                  ddd      |             S # t        j                  $ r Y nw xY w| j
                  j                  |v r)|| j
                  j                     j                  ||      S yrE   )	r   rB   rZ   r   Userr!   SMTPBadRcptlocalrJ   rG   s      r"   rJ   zAddressAlias.resolve   s      <Dt9SY	V4;;=''		$**dD$(OQUVXX 		::x'DJJ,,-55hEEs   AA' 'A=<A=rK   )	rL   rM   rN   rO   r?   r   rX   rF   rJ   rP   r@   r"   rR   rR      s"    )) )5r@   rR   c                   4    e Zd ZdZd Zd Zd Zd ZdefdZ	y)	FileWrappera  
    A message receiver which delivers a message to a file.

    @type fp: file-like object
    @ivar fp: A file used for temporary storage of the message.

    @type finalname: L{bytes}
    @ivar finalname: The name of the file in which the message should be
        stored.
    c                 D    t        j                         | _        || _        y)z
        @type filename: L{bytes}
        @param filename: The name of the file in which the message should be
            stored.
        N)tempfileTemporaryFiler3   	finalname)r>   r   s     r"   r?   zFileWrapper.__init__  s     ((*!r@   c                 @    | j                   j                  |dz          y)z
        Write a received line to the temporary file.

        @type line: L{bytes}
        @param line: A received line of the message.
        
N)r3   writer>   r   s     r"   lineReceivedzFileWrapper.lineReceived  s     	dTk"r@   c                    | j                   j                  dd       	 t        | j                  d      }|5  |j                  | j                   j                                | j                   j                          ddd       t        j                  | j                        S # t        $ r* t        j                  t        j                               cY S w xY w# 1 sw Y   ^xY w)ac  
        Handle end of message by writing the message to the file.

        @rtype: L{Deferred <defer.Deferred>} which successfully results in
            L{bytes}
        @return: A deferred which succeeds with the name of the file to which
            the message has been stored or fails if the message cannot be
            saved to the file.
        r   r7   N)r3   seekr*   rd   BaseExceptionr   failr	   Failurerg   readr/   succeed)r>   fs     r"   eomReceivedzFileWrapper.eomReceived  s     	Q	1T^^S)A  	GGDGGLLN#GGMMO	 }}T^^,,  	1::goo/00	1	 	s   B! AC!0CCC c                 F    | j                   j                          d| _         y)zG
        Close the temporary file when the connection is lost.
        N)r3   r/   rC   s    r"   connectionLostzFileWrapper.connectionLost-  s     	r@   rU   c                 "    d| j                    dS )z
        Build a string representation of this L{FileWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing the file name of the message.
        z<FileWrapper rW   )rd   rC   s    r"   rX   zFileWrapper.__str__4  s     t~~.a00r@   N
rL   rM   rN   rO   r?   ri   rr   rt   r   rX   rP   r@   r"   r`   r`      s'    	"#-,1 1r@   r`   c                   (    e Zd ZdZd ZdefdZd Zy)	FileAliasz_
    An alias which translates an address to a file.

    @ivar filename: See L{__init__}.
    c                 >    t        j                  | g|  || _        y)a"  
        @type filename: L{bytes}
        @param filename: The name of the file in which to store the message.

        @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain}
            provider, (1) L{bytes}
        @param args: Arguments for L{AliasBase.__init__}.
        N)r:   r?   r   )r>   r   rT   s      r"   r?   zFileAlias.__init__F  s     	4'$' r@   rU   c                 "    d| j                    dS )z
        Build a string representation of this L{FileAlias} instance.

        @rtype: L{bytes}
        @return: A string containing the name of the file.
        z<File rW   )r   rC   s    r"   rX   zFileAlias.__str__R  s     a((r@   c                 ,    t        | j                        S )z
        Create a message receiver which delivers a message to the file.

        @rtype: L{FileWrapper}
        @return: A message receiver which writes a message to the file.
        )r`   r   rC   s    r"   rF   zFileAlias.createMessageReceiver[  s     4==))r@   N)rL   rM   rN   rO   r?   r   rX   rF   rP   r@   r"   rx   rx   >  s    
!) )*r@   rx   c                       e Zd ZdZy)ProcessAliasTimeoutzb
    An error indicating that a timeout occurred while waiting for a process
    to complete.
    N)rL   rM   rN   rO   rP   r@   r"   r}   r}   e  s    r@   r}   c                   R    e Zd ZdZdZdZdZeZddZd Z	d Z
d Zd	 Zd
 ZdefdZy)MessageWrapperaF  
    A message receiver which delivers a message to a child process.

    @type completionTimeout: L{int} or L{float}
    @ivar completionTimeout: The number of seconds to wait for the child
        process to exit before reporting the delivery as a failure.

    @type _timeoutCallID: L{None} or
        L{IDelayedCall <twisted.internet.interfaces.IDelayedCall>} provider
    @ivar _timeoutCallID: The call used to time out delivery, started when the
        connection to the child process is closed.

    @type done: L{bool}
    @ivar done: A flag indicating whether the child process has exited
        (C{True}) or not (C{False}).

    @type reactor: L{IReactorTime <twisted.internet.interfaces.IReactorTime>}
        provider
    @ivar reactor: A reactor which will be used to schedule timeouts.

    @ivar protocol: See L{__init__}.

    @type processName: L{bytes} or L{None}
    @ivar processName: The process name.

    @type completion: L{Deferred <defer.Deferred>}
    @ivar completion: The deferred which will be triggered by the protocol
        when the child process exits.
    F<   Nc                     || _         || _        t        j                         | _        | j                  | j                  _        | j                  j                  | j                         ||| _        yy)a  
        @type protocol: L{ProcessAliasProtocol}
        @param protocol: The protocol associated with the child process.

        @type process: L{bytes} or L{None}
        @param process: The process name.

        @type reactor: L{None} or L{IReactorTime
            <twisted.internet.interfaces.IReactorTime>} provider
        @param reactor: A reactor which will be used to schedule timeouts.
        N)	processNamer   r   Deferred
completiononEndaddBoth_processEndedr   )r>   r   processr   s       r"   r?   zMessageWrapper.__init__  s[     # ..*"oo 2 23"DL r@   c                 p    d| _         | j                  "| j                  j                          d| _        y|S )a  
        Record process termination and cancel the timeout call if it is active.

        @type result: L{Failure <failure.Failure>}
        @param result: The reason the child process terminated.

        @rtype: L{None} or L{Failure <failure.Failure>}
        @return: None, if the process end is expected, or the reason the child
            process terminated, if the process end is unexpected.
        TN)done_timeoutCallIDcancel)r>   r   s     r"   r   zMessageWrapper._processEnded  s:     	* &&("&D Mr@   c                 n    | j                   ry| j                  j                  j                  |dz          y)z
        Write a received line to the child process.

        @type line: L{bytes}
        @param line: A received line of the message.
        Nrf   )r   r   	transportrg   rh   s     r"   ri   zMessageWrapper.lineReceived  s*     99%%dTk2r@   c                     | j                   sY| j                  j                  j                          | j                  j                  | j                  | j                        | _        | j                  S )z
        Disconnect from the child process and set up a timeout to wait for it
        to exit.

        @rtype: L{Deferred <defer.Deferred>}
        @return: A deferred which will be called back when the child process
            exits.
        )
r   r   r   loseConnectionr   	callLatercompletionTimeout_completionCancelr   r   rC   s    r"   rr   zMessageWrapper.eomReceived  sU     yyMM##224"&,,"8"8&&(>(>#D r@   c                    d| _         | j                  j                  j                  d       t	        d| j
                   d      }d| j                  _        | j                  j                  t        j                  |             y)z
        Handle the expiration of the timeout for the child process to exit by
        terminating the child process forcefully and issuing a failure to the
        L{completion} deferred.
        NKILLzNo answer after z seconds)r   r   r   signalProcessr}   r   r   r   errbackr	   rn   )r>   excs     r"   r   z MessageWrapper._completionCancel  sf     #--f5!$4T5K5K4LH"UV" 45r@   c                      y)z9
        Ignore notification of lost connection.
        NrP   rC   s    r"   rt   zMessageWrapper.connectionLost  s    r@   rU   c                 "    d| j                    dS )z
        Build a string representation of this L{MessageWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing the name of the process.
        z<ProcessWrapper rW   )r   rC   s    r"   rX   zMessageWrapper.__str__  s     "$"2"2!3155r@   NN)rL   rM   rN   rO   r   r   r   r   r?   r   ri   rr   r   rt   r   rX   rP   r@   r"   r   r   l  sH    < DNG#*,	3 
6
6 6r@   r   c                       e Zd ZdZdZd Zy)ProcessAliasProtocolz
    A process protocol which errbacks a deferred when the associated
    process ends.

    @type onEnd: L{None} or L{Deferred <defer.Deferred>}
    @ivar onEnd: If set, a deferred on which to errback when the process ends.
    Nc                 T    | j                   | j                   j                  |       yy)z
        Call an errback.

        @type reason: L{Failure <failure.Failure>}
        @param reason: The reason the child process terminated.
        N)r   r   )r>   reasons     r"   processEndedz!ProcessAliasProtocol.processEnded  s%     ::!JJv& "r@   )rL   rM   rN   rO   r   r   rP   r@   r"   r   r     s     E'r@   r   c                   2    e Zd ZdZeZd ZdefdZd Zd Z	y)ProcessAliasa6  
    An alias which is handled by the execution of a program.

    @type path: L{list} of L{bytes}
    @ivar path: The arguments to pass to the process. The first string is
        the executable's name.

    @type program: L{bytes}
    @ivar program: The path of the program to be executed.

    @type reactor: L{IReactorTime <twisted.internet.interfaces.IReactorTime>}
        and L{IReactorProcess <twisted.internet.interfaces.IReactorProcess>}
        provider
    @ivar reactor: A reactor which will be used to create and timeout the
        child process.
    c                     t        j                  | g|  |j                         | _        | j                  d   | _        y)aX  
        @type path: L{bytes}
        @param path: The command to invoke the program consisting of the path
            to the executable followed by any arguments.

        @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain}
            provider, (1) L{bytes}
        @param args: Arguments for L{AliasBase.__init__}.
        r   N)r:   r?   r   pathprogram)r>   r   rT   s      r"   r?   zProcessAlias.__init__  s3     	4'$'JJL	yy|r@   rU   c                 "    d| j                    dS )z
        Build a string representation of this L{ProcessAlias} instance.

        @rtype: L{bytes}
        @return: A string containing the command used to invoke the process.
        z	<Process rW   )r   rC   s    r"   rX   zProcessAlias.__str__.  s     499+Q''r@   c                 <    | j                   j                  |||      S )aP  
        Spawn a process.

        This wraps the L{spawnProcess
        <twisted.internet.interfaces.IReactorProcess.spawnProcess>} method on
        L{reactor} so that it can be customized for test purposes.

        @type proto: L{IProcessProtocol
            <twisted.internet.interfaces.IProcessProtocol>} provider
        @param proto: An object which will be notified of all events related to
            the created process.

        @type program: L{bytes}
        @param program: The full path name of the file to execute.

        @type path: L{list} of L{bytes}
        @param path: The arguments to pass to the process. The first string
            should be the executable's name.

        @rtype: L{IProcessTransport
            <twisted.internet.interfaces.IProcessTransport>} provider
        @return: A process transport.
        )r   spawnProcess)r>   protor   r   s       r"   r   zProcessAlias.spawnProcess7  s    0 ||((>>r@   c                     t               }t        || j                  | j                        }| j	                  || j                  | j
                         |S )z
        Launch a process and create a message receiver to pass a message
        to the process.

        @rtype: L{MessageWrapper}
        @return: A message receiver which delivers a message to the process.
        )r   r   r   r   r   r   )r>   r   ms      r"   rF   z"ProcessAlias.createMessageReceiverQ  sA     !"1dllDLL9!T\\4995r@   N)
rL   rM   rN   rO   r   r?   r   rX   r   rF   rP   r@   r"   r   r   
  s)    " G$( (?4r@   r   c                   4    e Zd ZdZd Zd Zd Zd ZdefdZ	y)	MultiWrapperz
    A message receiver which delivers a single message to multiple other
    message receivers.

    @ivar objs: See L{__init__}.
    c                     || _         y)z
        @type objs: L{list} of L{IMessage <smtp.IMessage>} provider
        @param objs: Message receivers to which the incoming message should be
            directed.
        N)objs)r>   r   s     r"   r?   zMultiWrapper.__init__h  s     	r@   c                 H    | j                   D ]  }|j                  |        y)z
        Pass a received line to the message receivers.

        @type line: L{bytes}
        @param line: A line of the message.
        N)r   ri   )r>   r   os      r"   ri   zMultiWrapper.lineReceivedp  s#      	!ANN4 	!r@   c                     t        j                  | j                  D cg c]  }|j                          c}      S c c}w )aG  
        Pass the end of message along to the message receivers.

        @rtype: L{DeferredList <defer.DeferredList>} whose successful results
            are L{bytes} or L{None}
        @return: A deferred list which triggers when all of the message
            receivers have finished handling their end of message.
        )r   DeferredListr   rr   r>   r   s     r"   rr   zMultiWrapper.eomReceivedz  s-     !!DII"Fq1==?"FGG"Fs   <c                 F    | j                   D ]  }|j                           y)zQ
        Inform the message receivers that the connection has been lost.
        N)r   rt   r   s     r"   rt   zMultiWrapper.connectionLost  s#      	A	r@   rU   c                 >    dt        t        | j                        dS )z
        Build a string representation of this L{MultiWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing a list of the message receivers.
        z<GroupWrapper rW   )r   r   r   rC   s    r"   rX   zMultiWrapper.__str__  s      C 36a88r@   Nrv   rP   r@   r"   r   r   _  s(    !	H9 9r@   r   c                   :    e Zd ZdZeZd Zd ZdefdZ	d Z
d	dZy)
r1   aL  
    An alias which points to multiple destination aliases.

    @type processAliasFactory: no-argument callable which returns
        L{ProcessAlias}
    @ivar processAliasFactory: A factory for process aliases.

    @type aliases: L{list} of L{AliasBase} which implements L{IAlias}
    @ivar aliases: The destination aliases.
    c                    t        j                  | g|  g | _        |rn|j                         j	                         }|j                  d      rh	 t        |dd       }|5  dj                  |D cg c]  }|j	                          c}      }ddd       |j                  |j                  d             n|j                  d      r0| j                  j                   | j                  |dd g|        n|j                  d      r[t        j                   j#                  |      rt        j                  d	       nK| j                  j                  t%        |g|        n%| j                  j                  t'        |g|        |rmyyc c}w # 1 sw Y   xY w# t        $ r t        j                  d|dd        Y >w xY w)
a  
        Create a group of aliases.

        Parse a list of alias strings and, for each, create an appropriate
        alias object.

        @type items: L{list} of L{bytes}
        @param items: Aliases.

        @type args: n-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain}
            provider, (1) L{bytes}
        @param args: Arguments for L{AliasBase.__init__}.
        r   r   Nr(   r   zInvalid filename in alias file |/z Directory delivery not supported)r:   r?   aliasespopr   r.   r*   joinr   r   rl   r
   r   appendprocessAliasFactoryosr   isdirrx   rR   )r>   r0   rT   addrrq   ls         r"   r?   zAliasGroup.__init__  st    	4'$'99;$$&Ds#2T!"XA  @"xxA(>q(>?@LLC1%##$<D$<$<T!"X$M$MN%77==&GG>?LL''	$(>(>?##L$=$=>'  )?@ @ % LGG=d12h\JKLs0   F" !F1F
FFF"$G	G	c                 ,    t        | j                        S )z
        Return the number of aliases in the group.

        @rtype: L{int}
        @return: The number of aliases in the group.
        )r   r   rC   s    r"   __len__zAliasGroup.__len__  s     4<<  r@   rU   c                 Z    ddj                  t        t        | j                              z  S )z
        Build a string representation of this L{AliasGroup} instance.

        @rtype: L{bytes}
        @return: A string containing the aliases in the group.
        z<AliasGroup [%s]>z, )r   r   r   r   rC   s    r"   rX   zAliasGroup.__str__  s#     #diiC0F&GHHr@   c                 n    t        | j                  D cg c]  }|j                          c}      S c c}w )a,  
        Create a message receiver for each alias and return a message receiver
        which will pass on a message to each of those.

        @rtype: L{MultiWrapper}
        @return: A message receiver which passes a message on to message
            receivers for each alias in the group.
        )r   r   rF   )r>   r7   s     r"   rF   z AliasGroup.createMessageReceiver  s*     M1Q446MNNMs   2Nc                     |i }g }| j                   D ]#  }|j                  |j                  ||             % t        t	        d|            S )a  
        Map each of the aliases in the group to its ultimate destination.

        @type aliasmap: L{dict} mapping L{bytes} to L{AliasBase}
        @param aliasmap: A mapping of username to alias or group of aliases.

        @type memo: L{None} or L{dict} of L{AliasBase}
        @param memo: A record of the aliases already considered in the
            resolution process.  If provided, C{memo} is modified to include
            this alias.

        @rtype: L{MultiWrapper}
        @return: A message receiver which passes the message on to message
            receivers for the ultimate destination of each alias in the group.
        N)r   r   rJ   r   filter)r>   rH   rI   rr7   s        r"   rJ   zAliasGroup.resolve  sN      <D 	0AHHQYYx./	0F4O,,r@   rK   )rL   rM   rN   rO   r   r   r?   r   r   rX   rF   rJ   rP   r@   r"   r1   r1     s3    	 '$?L!I I	O-r@   r1   r   )rO   r   rb   zope.interfacer   twisted.internetr   r   r   twisted.mailr   twisted.mail.interfacesr   twisted.pythonr	   r
   r#   r8   r:   rR   IMessager`   rx   	Exceptionr}   r   ProcessProtocolr   r   r   r1   rP   r@   r"   <module>r      sU   
  & 5 5  * 'U6EP3, 3,l VC9 C CL T]]B1 B1 B1J V#*	 #* #*L)  T]]D6 D6 D6N'833 ', VQ9 Q Qh T]]39 39 39l Vf- f- f-r@   