U
    dd-                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlm	Z	 ddl
mZ ddlmZmZ ddlmZmZmZ ejrd dl mZ G d	d
 d
ZG dd deZG dd deZG dd deZG dd deZG dd dejZdS )    N)	b64encode)parse_http_list   )ProtocolError)RequestResponse)to_bytesto_strunquote)_Hashc                   @   sj   e Zd ZdZdZdZeejee	df dddZ
eejee	df dddZeejee	f dd	d
ZdS )Autha  
    Base class for all authentication schemes.

    To implement a custom authentication scheme, subclass `Auth` and override
    the `.auth_flow()` method.

    If the authentication scheme does I/O such as disk access or network calls, or uses
    synchronization primitives such as locks, you should override `.sync_auth_flow()`
    and/or `.async_auth_flow()` instead of `.auth_flow()` to provide specialized
    implementations that will be used by `Client` and `AsyncClient` respectively.
    FNrequestreturnc                 c   s
   |V  dS )a  
        Execute the authentication flow.

        To dispatch a request, `yield` it:

        ```
        yield request
        ```

        The client will `.send()` the response back into the flow generator. You can
        access it like so:

        ```
        response = yield request
        ```

        A `return` (or reaching the end of the generator) will result in the
        client returning the last response obtained from the server.

        You can dispatch as many requests as is necessary.
        N selfr   r   r   //tmp/pip-unpacked-wheel-fkuvgui5/httpx/_auth.py	auth_flow"   s    zAuth.auth_flowc                 c   sb   | j r|  | |}t|}|V }| jr4|  z||}W q  tk
rZ   Y q^Y q X q dS )z
        Execute the authentication flow synchronously.

        By default, this defers to `.auth_flow()`. You should override this method
        when the authentication scheme does I/O and/or uses concurrency primitives.
        N)requires_request_bodyreadr   nextrequires_response_bodysendStopIterationr   r   Zflowresponser   r   r   sync_auth_flow:   s    	
zAuth.sync_auth_flowc                 C  sn   | j r| I dH  | |}t|}|V }| jr@| I dH  z||}W q& tk
rf   Y qjY q&X q&dS )z
        Execute the authentication flow asynchronously.

        By default, this defers to `.auth_flow()`. You should override this method
        when the authentication scheme does I/O and/or uses concurrency primitives.
        N)r   Zareadr   r   r   r   r   r   r   r   r   async_auth_flowS   s    	
zAuth.async_auth_flow)__name__
__module____qualname____doc__r   r   r   typing	Generatorr   r   r   AsyncGeneratorr   r   r   r   r   r      s   r   c                   @   sH   e Zd ZdZejegef ddddZeejee	df dddZ
dS )	FunctionAuthz
    Allows the 'auth' argument to be passed as a simple callable function,
    that takes the request, and returns a new, modified request.
    N)funcr   c                 C   s
   || _ d S NZ_func)r   r'   r   r   r   __init__s   s    zFunctionAuth.__init__r   c                 c   s   |  |V  d S r(   r)   r   r   r   r   r   v   s    zFunctionAuth.auth_flow)r   r    r!   r"   r#   Callabler   r*   r$   r   r   r   r   r   r   r&   m   s   r&   c                   @   sv   e Zd ZdZejeef ejeef dddZe	ej
e	edf dddZejeef ejeef ed	d
dZdS )	BasicAuthzy
    Allows the 'auth' argument to be passed as a (username, password) pair,
    and uses HTTP Basic authentication.
    usernamepasswordc                 C   s   |  ||| _d S r(   )_build_auth_header_auth_headerr   r.   r/   r   r   r   r*      s    zBasicAuth.__init__Nr   c                 c   s   | j |jd< |V  d S )NAuthorization)r1   headersr   r   r   r   r      s    zBasicAuth.auth_flowr.   r/   r   c                 C   s,   d t|t|f}t| }d| S N   :zBasic joinr   r   decoder   r.   r/   Zuserpasstokenr   r   r   r0      s    zBasicAuth._build_auth_header)r   r    r!   r"   r#   Unionstrbytesr*   r   r$   r   r   r0   r   r   r   r   r,   z   s     r,   c                   @   sf   e Zd ZdZeje dddZeej	ee
df dddZejeef ejeef ed	d
dZdS )	NetRCAuthzT
    Use a 'netrc' file to lookup basic auth credentials based on the url host.
    )filec                 C   s   t  || _d S r(   )netrc_netrc_info)r   rA   r   r   r   r*      s    zNetRCAuth.__init__Nr   c                 c   sN   | j |jj}|d ks |d s(|V  n"| j|d |d d|jd< |V  d S )N   r   r-   r3   )rC   authenticatorsurlhostr0   r4   )r   r   Z	auth_infor   r   r   r      s     zNetRCAuth.auth_flowr5   c                 C   s,   d t|t|f}t| }d| S r6   r8   r;   r   r   r   r0      s    zNetRCAuth._build_auth_header)r   r    r!   r"   r#   Optionalr>   r*   r   r$   r   r   r=   r?   r0   r   r   r   r   r@      s    r@   c                	   @   s  e Zd ZU ejejejejejejejejdZe	j
ee	jegdf f ed< e	jeef e	jeef ddddZee	jeedf dd	d
ZeeeddddZededddZeeedddZe	j
eef edddZe	je ee	je dddZdS )
DigestAuth)MD5zMD5-SESSSHAzSHA-SESSzSHA-256zSHA-256-SESSzSHA-512zSHA-512-SESSr   _ALGORITHM_TO_HASH_FUNCTIONNr5   c                 C   s$   t || _t || _d | _d| _d S )Nr   )r   	_username	_password_last_challenge_nonce_countr2   r   r   r   r*      s    

zDigestAuth.__init__r   c                 c   s   | j r| || j |jd< |V }|jdks4d|jkr8d S |jdD ]}| drD q`qDd S | |||| _ d| _| || j |jd< |V  d S )Nr3   i  zwww-authenticatezdigest r   )	rO   r0   r4   status_codeZget_listlower
startswith_parse_challengerP   )r   r   r   auth_headerr   r   r   r      s&     
 
zDigestAuth.auth_flow_DigestAuthChallenge)r   r   rU   r   c              
   C   s   | d\}}}| dks ti }t|D ]$}| dd\}	}
t|
||	< q,zh|d  }|d  }|dd}d	|kr|d	  nd
}d|kr|d  nd
}t	|||||dW S  t
k
r } zd}t||d|W 5 d
}~X Y nX d
S )z
        Returns a challenge from a Digest WWW-Authenticate header.
        These take the form of:
        `Digest realm="realm@host.com",qop="auth,auth-int",nonce="abc",opaque="xyz"`
         digest=r   realmnonce	algorithmrJ   opaqueNqop)rZ   r[   r\   r]   r^   z(Malformed Digest WWW-Authenticate headerr   )	partitionrR   AssertionErrorr   stripsplitr
   encodegetrV   KeyErrorr   )r   r   r   rU   scheme_fieldsZheader_dictfieldkeyvaluerZ   r[   r\   r]   r^   excmessager   r   r   rT      s,        zDigestAuth._parse_challenge)r   	challenger   c              	      s^  | j |j   ttd fdd}d| j|j| jf}|jj	}d|j
 |f}||}d| j }| | j|j}	|  jd7  _||}
|j dr|d|
|j|	f}
| j|j|d}|d kr|
|j|g}n|j||	||g}d|}| j|j|j||d|
|f|j d	}|jr2|j|d
< |rPd|d< ||d< |	|d< d| | S )N)datar   c                    s    |    S r(   )	hexdigestrd   )rp   Z	hash_funcr   r   rX     s    z-DigestAuth._build_auth_header.<locals>.digestr7   s   %08xr   z-sessr_   )r.   rZ   r[   urir   r\   r]      authr^   nccnoncezDigest )rL   r\   upperr?   r9   rM   rZ   rN   rF   raw_pathmethodrd   rP   _get_client_noncer[   rR   endswith_resolve_qopr^   r]   _get_header_value)r   r   ro   rX   A1pathA2HA2Znc_valuerv   HA1r^   Zdigest_dataZ
key_digestZformat_argsr   rr   r   r0      s>    


zDigestAuth._build_auth_header)nonce_countr[   r   c                 C   sL   t | }||7 }|t  7 }|td7 }t| d d  S )N      )	r>   rd   timectimeosurandomhashlibsha1rq   )r   r   r[   sr   r   r   rz   ,  s
    zDigestAuth._get_client_nonce)header_fieldsr   c           
      C   sb   d}d}d}d}t | D ]@\}\}}|dkr8|d7 }||krD|n|}	||	|t|7 }q|S )N)r\   r^   ru   z{}="{}"z{}={} r   z, )	enumerateitemsformatr	   )
r   r   ZNON_QUOTED_FIELDSZQUOTED_TEMPLATEZNON_QUOTED_TEMPLATEheader_valueirj   rl   templater   r   r   r}   4  s    zDigestAuth._get_header_value)r^   r   r   c                 C   sR   |d krd S t d|}d|kr$dS |dgkr6tdd|d}t||dd S )Ns   , ?rt   s   auth-intz.Digest auth-int support is not yet implementedzUnexpected qop value "z" in digest authr_   )rerc   NotImplementedErrorr   )r   r^   r   Zqopsrn   r   r   r   r|   F  s    
zDigestAuth._resolve_qop)r   r    r!   r   md5r   sha256sha512rL   r#   Dictr>   r+   r?   __annotations__r=   r*   r   r$   r   r   rT   r0   intrz   r}   rH   r|   r   r   r   r   rI      s:   
$     / rI   c                   @   sB   e Zd ZU eed< eed< eed< eje ed< eje ed< dS )rV   rZ   r[   r\   r]   r^   N)r   r    r!   r?   r   r>   r#   rH   r   r   r   r   rV   V  s
   
rV   )r   rB   r   r   r   r#   base64r   urllib.requestr   _exceptionsr   Z_modelsr   r   _utilsr   r	   r
   TYPE_CHECKINGr   r   r&   r,   r@   rI   
NamedTuplerV   r   r   r   r   <module>   s&   [ *