U
    n5{i)A  ã                   @   sœ   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mZ ddlmZ dd	d
„ZG dd„ dejƒZG dd„ deƒZG dd„ deƒZdS )z
Authoritative resolvers.
é    N)Údefer)ÚcommonÚdnsÚerror)Úfailure)ÚexecfileÚnativeString)ÚFilePathú/tmp/twisted-names.serialc              	   C   sÌ   t  d¡}t d¡}z4tj | ¡sFt| dƒ�}| |d ¡ W 5 Q R X W 5 t |¡ X t| ƒ�}| ¡  	¡ \}}W 5 Q R X ||krŽt
|ƒd p�d}t| dƒ�}| d||f ¡ W 5 Q R X |d|f  }|S )	aÛ  
    Return a monotonically increasing (across program runs) integer.

    State is stored in the given file.  If it does not exist, it is
    created with rw-/---/--- permissions.

    This manipulates process-global state by calling C{os.umask()}, so it isn't
    thread-safe.

    @param filename: Path to a file that is used to store the state across
        program runs.
    @type filename: L{str}

    @return: a monotonically increasing number
    @rtype: L{str}
    z%Y%m%dé   Úwz 0é   r   z%s %dz%02d)ÚtimeÚstrftimeÚosÚumaskÚpathÚexistsÚopenÚwriteÚreadlineÚsplitÚint)ÚfilenameÚserialÚoÚfZ
serialFileZ
lastSerialZzoneID© r   ú;/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/names/authority.pyÚ	getSerial   s    


r   c                   @   sp   e Zd ZdZejejejfZej	ej
fZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zddd„Zddd„Zdd„ ZdS )ÚFileAuthoritya­  
    An Authority that is loaded from a file.

    This is an abstract class that implements record search logic. To create
    a functional resolver, subclass it and override the L{loadFile} method.

    @ivar _ADDITIONAL_PROCESSING_TYPES: Record types for which additional
        processing will be done.

    @ivar _ADDRESS_TYPES: Record types which are useful for inclusion in the
        additional section generated during additional processing.

    @ivar soa: A 2-tuple containing the SOA domain name as a L{bytes} and a
        L{dns.Record_SOA}.

    @ivar records: A mapping of domains (as lowercased L{bytes}) to records.
    @type records: L{dict} with L{bytes} keys
    Nc                 C   s    t j | ¡ |  |¡ i | _d S ©N)r   ÚResolverBaseÚ__init__ÚloadFileÚ_cache©Úselfr   r   r   r   r#   V   s    
zFileAuthority.__init__c                 C   s
   || _ d S r!   )Ú__dict__)r'   Ústater   r   r   Ú__setstate__[   s    zFileAuthority.__setstate__c                 C   s   dS )ab  
        Load DNS records from a file.

        This method populates the I{soa} and I{records} attributes. It must be
        overridden in a subclass. It is called once from the initializer.

        @param filename: The I{filename} parameter that was passed to the
        initilizer.

        @returns: L{None} -- the return value is ignored
        Nr   r&   r   r   r   r$   ^   s    zFileAuthority.loadFilec              
   c   sn   || D ]`}|j | jkr|jjj}| j | ¡ d¡D ]2}|j| jkr4t	j
||jt	j|jpZ||dd�V  q4qdS )aW  
        Find locally known information that could be useful to the consumer of
        the response and construct appropriate records to include in the
        I{additional} section of that response.

        Essentially, implement RFC 1034 section 4.3.2 step 6.

        @param answer: A L{list} of the records which will be included in the
            I{answer} section of the response.

        @param authority: A L{list} of the records which will be included in
            the I{authority} section of the response.

        @param ttl: The default TTL for records for which this is not otherwise
            specified.

        @return: A generator of L{dns.RRHeader} instances for inclusion in the
            I{additional} section.  These instances represent extra information
            about the records in C{answer} and C{authority}.
        r   T©ÚauthN)ÚtypeÚ_ADDITIONAL_PROCESSING_TYPESÚpayloadÚnameÚrecordsÚgetÚlowerÚTYPEÚ_ADDRESS_TYPESr   ÚRRHeaderÚINÚttl)r'   ZanswerÚ	authorityr8   Úrecordr0   Úrecr   r   r   Ú_additionalRecordsk   s    
     ÿz FileAuthority._additionalRecordsc                 C   sÄ  g }g }g }g }t | jd j| jd jƒ}	| j | ¡ ¡}
|
�r€|
D ]¾}|jdk	rZ|j}n|	}|jt	j
kr¢| ¡ | jd  ¡ kr¢| t	j||jt	j||dd�¡ n4|j|ks¶|t	jkrÖ| t	j||jt	j||dd�¡ |jt	jkrD| t	j||jt	j||dd�¡ qD|�s|}|  |||	¡}|�r.| |¡ n
| |¡ |�sp|�sp| t	j| jd t	jt	j|| jd dd�¡ t |||f¡S t	 || jd ¡�rªt t t	 |¡¡¡S t t t |¡¡¡S dS )a   
        Determine a response to a particular DNS query.

        @param name: The name which is being queried and for which to lookup a
            response.
        @type name: L{bytes}

        @param cls: The class which is being queried.  Only I{IN} is
            implemented here and this value is presently disregarded.
        @type cls: L{int}

        @param type: The type of records being queried.  See the types defined
            in L{twisted.names.dns}.
        @type type: L{int}

        @param timeout: All processing is done locally and a result is
            available immediately, so the timeout value is ignored.

        @return: A L{Deferred} that fires with a L{tuple} of three sets of
            response records (to comprise the I{answer}, I{authority}, and
            I{additional} sections of a DNS response) or with a L{Failure} if
            there is a problem processing the query.
        r   Nr   Fr+   T)ÚmaxÚsoaÚminimumÚexpirer1   r2   r3   r8   r4   r   ÚNSÚappendr6   r7   ZALL_RECORDSÚCNAMEr<   ÚextendÚSOAr   ÚsucceedZ_isSubdomainOfÚfailr   ÚFailureZAuthoritativeDomainErrorr   ÚDomainError)r'   r0   Úclsr-   ÚtimeoutZcnamesÚresultsr9   Ú
additionalÚdefault_ttlZdomain_recordsr:   r8   ZadditionalInformationr   r   r   Ú_lookup‰   s`    
"ÿÿÿ  ÿ
     ÿÿzFileAuthority._lookupé
   c           
      C   s  t  |¡}| jd  ¡ | ¡ k�rt| jd j| jd jƒ}| jd jd k	rZ| jd j}n|}t j| jd t j	t j
|| jd dd�g}| j ¡ D ]T\}}|D ]F}|jd k	r²|j}	n|}	|jt j	krœ| t j||jt j
|	|dd�¡ qœq�| |d ¡ t |ddf¡S t t t  |¡¡¡S )Nr   r   Tr+   r   )r   ÚdomainStringr>   r3   r=   r?   r@   r8   r6   rE   r7   r1   Úitemsr4   rB   r   rF   rG   r   rH   rI   )
r'   r0   rK   rN   Zsoa_ttlrL   ÚkÚrr;   r8   r   r   r   Ú
lookupZoneâ   s6    
     ÿÿ
ÿzFileAuthority.lookupZonec                 C   sb   g g g   }}}|D ]B}|d r|  |d d ¡ |  |d d ¡ |  |d d ¡ q|||fS )Nr   r   é   )rD   )r'   rL   Zansr,   ÚaddÚresr   r   r   Ú_cbAllRecordsþ   s    zFileAuthority._cbAllRecords)N)rP   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   rC   ZMXrA   r.   ÚAZAAAAr5   r>   r1   r#   r*   r$   r<   rO   rU   rY   r   r   r   r   r    ;   s   
Y
r    c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚPySourceAuthorityzC
    A FileAuthority that is built up from Python source code.
    c                 C   s|   |   ¡ i  }}t|||ƒ d|kr.td| ƒ‚i | _|d D ]:}t|d tjƒrV|| _| j |d  	¡ g ¡ 
|d ¡ q<d S )NÚzonezNo zone defined in r   r   )ÚsetupConfigNamespacer   Ú
ValueErrorr1   Ú
isinstancer   Z
Record_SOAr>   Ú
setdefaultr3   rB   )r'   r   ÚgÚlÚrrr   r   r   r$     s    zPySourceAuthority.loadFilec                    s   ‡ fdd„}|S )Nc                    s   t  | ¡ˆ ||ŽfS r!   )r   rQ   )r0   ÚargÚkw©r-   r   r   ÚwrapRecordFunc  s    z4PySourceAuthority.wrapRecord.<locals>.wrapRecordFuncr   )r'   r-   rk   r   rj   r   Ú
wrapRecord  s    zPySourceAuthority.wrapRecordc                 C   sN   i }t j ¡ }dd„ |D ƒD ],}tt |ƒ}|  |¡}|||tdƒd … < q|S )Nc                 S   s   g | ]}|  d ¡r|‘qS )ÚRecord_)Ú
startswith)Ú.0Úxr   r   r   Ú
<listcomp>"  s     
 z:PySourceAuthority.setupConfigNamespace.<locals>.<listcomp>rm   )r   r(   ÚkeysÚgetattrrl   Úlen)r'   rT   rR   r:   r-   r   r   r   r   ra     s    


z&PySourceAuthority.setupConfigNamespaceN)rZ   r[   r\   r]   r$   rl   ra   r   r   r   r   r_     s   r_   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )ÚBindAuthorityz™
    An Authority that loads U{BIND zone files
    <https://en.wikipedia.org/wiki/Zone_file>}.

    Supports only C{$ORIGIN} and C{$TTL} directives.
    c                 C   sJ   t |ƒ}t| ¡ d ƒ| _| ¡  d¡}|  |¡}|  |¡}|  |¡ dS )z}
        Load records from C{filename}.

        @param filename: file to read from
        @type filename: L{bytes}
        ó   .TN)	r	   r   ÚbasenameÚoriginZ
getContentÚ
splitlinesÚstripCommentsÚcollapseContinuationsÚ
parseLines)r'   r   ÚfpÚlinesr   r   r   r$   1  s    

zBindAuthority.loadFilec                 C   s   dd„ dd„ |D ƒD ƒS )z«
        Strip comments from C{lines}.

        @param lines: lines to work on
        @type lines: iterable of L{bytes}

        @return: C{lines} sans comments.
        c                 s   s2   | ]*}|  d ¡dkr|p(|d|  d ¡… V  qdS )ó   ;éÿÿÿÿN)Úfind)ro   Úar   r   r   Ú	<genexpr>K  s   ÿz.BindAuthority.stripComments.<locals>.<genexpr>c                 S   s   g | ]}|  ¡ ‘qS r   )Ústrip)ro   Úbr   r   r   rq   M  s     z/BindAuthority.stripComments.<locals>.<listcomp>r   )r'   r~   r   r   r   rz   B  s    	þzBindAuthority.stripCommentsc              
   C   s°   g }d}|D ]Ž}|dkrP|  d¡dkr2| |¡ qš| |d|  d¡… ¡ d}q|  d¡dkr†|d  d|d|  d¡…  7  < d}q|d  d| 7  < qtddd	„ |D ƒƒS )
zÄ
        Transform multiline statements into single lines.

        @param lines: lines to work on
        @type lines: iterable of L{bytes}

        @return: iterable of continuous lines
        r   ó   (r€   Nr   ó   )ó    c                 s   s   | ]}|  ¡ V  qd S r!   )r   )ro   Úliner   r   r   rƒ   h  s     z6BindAuthority.collapseContinuations.<locals>.<genexpr>)r�   rB   Úfilter)r'   r~   rf   r)   r‰   r   r   r   r{   P  s    	"z#BindAuthority.collapseContinuationsc                 C   s�   d}| j }i | _|D ]p}|d dkr4t |d ¡}q|d dkrJ|d }q|d dkr`tdƒ‚q|d dkrvtd	ƒ‚q|  |||¡ q|| _ d
S )zs
        Parse C{lines}.

        @param lines: lines to work on
        @type lines: iterable of L{bytes}
        i0*  r   s   $TTLr   s   $ORIGINs   $INCLUDEz"$INCLUDE directive not implementeds	   $GENERATEz#$GENERATE directive not implementedN)rx   r1   r   Zstr2timeÚNotImplementedErrorÚparseRecordLine)r'   r~   r8   rx   r‰   r   r   r   r|   j  s    


zBindAuthority.parseLinesc                 C   sf   |  d¡s |d |dd…  }n|dd… }t| d|› �dƒ}|rR|||||ƒ ntd|›d�ƒ‚dS )a  
        Add a record to our authority.  Expand domain with origin if necessary.

        @param owner: origin?
        @type owner: L{bytes}

        @param ttl: time to live for the record
        @type ttl: L{int}

        @param domain: the domain for which the record is to be added
        @type domain: L{bytes}

        @param type: record type
        @type type: L{str}

        @param cls: record class
        @type cls: L{str}

        @param rdata: record data
        @type rdata: L{list} of L{bytes}
        rv   Nr€   Úclass_zRecord class ú not supported)Úendswithrs   r‹   )r'   Úownerr8   r-   ÚdomainrJ   Úrdatar   r   r   r   Ú	addRecord…  s    
zBindAuthority.addRecordc                 C   sl   t tdt|ƒ› �dƒ}|rT||Ž }||_| j | ¡ g ¡ |¡ |dkrh||f| _nt	dt|ƒ›d�ƒ‚dS )a>  
        Simulate a class IN and recurse into the actual class.

        @param ttl: time to live for the record
        @type ttl: L{int}

        @param type: record type
        @type type: str

        @param domain: the domain
        @type domain: bytes

        @param rdata:
        @type rdata: bytes
        rm   NrE   zRecord type rŽ   )
rs   r   r   r8   r1   rd   r3   rB   r>   r‹   )r'   r8   r-   r‘   r’   r:   rT   r   r   r   Úclass_IN¥  s    ÿzBindAuthority.class_INc                 C   sz  dd„ t j ¡ D ƒ}dd„ t j ¡ D ƒ}||B }d}|}|d dkrV|dd… }|}n,|d  ¡ s‚|d |kr‚|d }|dd… }|d  ¡ sš|d |kr¤|}	|}n|d }	|dd… }|d |krþ|d }|dd… }|d  ¡ rüt|d ƒ}|dd… }nH|d  ¡ �rFt|d ƒ}|dd… }|d |k�rF|d }|dd… }|d }
|dd… }|  ||t|
ƒ|	t|ƒ|¡ dS )	aƒ  
        Parse a C{line} from a zone file respecting C{origin} and C{ttl}.

        Add resulting records to authority.

        @param origin: starting point for the zone
        @type origin: L{bytes}

        @param ttl: time to live for the record
        @type ttl: L{int}

        @param line: zone file line to parse; split by word
        @type line: L{list} of L{bytes}
        c                 S   s   h | ]}|  d ¡’qS ©Úascii©Úencode)ro   Zqcr   r   r   Ú	<setcomp>Ñ  s     z0BindAuthority.parseRecordLine.<locals>.<setcomp>c                 S   s   h | ]}|  d ¡’qS r•   r—   )ro   Zqtr   r   r   r™   Ò  s     s   INr   ó   @r   N)r   ZQUERY_CLASSESÚvaluesZQUERY_TYPESÚisdigitr   r“   r   )r'   rx   r8   r‰   ZqueryClassesZ
queryTypesÚmarkersrJ   r�   r‘   r-   r’   r   r   r   rŒ   Â  s>    zBindAuthority.parseRecordLineN)rZ   r[   r\   r]   r$   rz   r{   r|   r“   r”   rŒ   r   r   r   r   ru   )  s    ru   )r
   )r]   r   r   Ztwisted.internetr   Ztwisted.namesr   r   r   Ztwisted.pythonr   Ztwisted.python.compatr   r   Ztwisted.python.filepathr	   r   r"   r    r_   ru   r   r   r   r   Ú<module>   s   
' N!