509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3

  \;;  ã               @   sè   d Z dgZddlZddlZddlZejdƒZejdƒZG dd„ deƒZ	dd	„ Z
d
d„ Zdd„ ZG dd„ dƒZG dd„ dƒZG dd„ dƒZG dd„ dƒZG dd„ dƒZd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 )'a&  
Middleware to check for obedience to the WSGI specification.

Some of the things this checks:

* Signature of the application and start_response (including that
  keyword arguments are not used).

* Environment checks:

  - Environment is a dictionary (and not a subclass).

  - That all the required keys are in the environment: REQUEST_METHOD,
    SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
    wsgi.multithread, wsgi.multiprocess, wsgi.run_once

  - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
    environment (these headers should appear as CONTENT_LENGTH and
    CONTENT_TYPE).

  - Warns if QUERY_STRING is missing, as the cgi module acts
    unpredictably in that case.

  - That CGI-style variables (that don't contain a .) have
    (non-unicode) string values

  - That wsgi.version is a tuple

  - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
    restrictive?)

  - Warns if the REQUEST_METHOD is not known (@@: probably too
    restrictive).

  - That SCRIPT_NAME and PATH_INFO are empty or start with /

  - That at least one of SCRIPT_NAME or PATH_INFO are set.

  - That CONTENT_LENGTH is a positive integer.

  - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
    be '/').

  - That wsgi.input has the methods read, readline, readlines, and
    __iter__

  - That wsgi.errors has the methods flush, write, writelines

* The status is a string, contains a space, starts with an integer,
  and that integer is in range (> 100).

* That the headers is a list (not a subclass, not another kind of
  sequence).

* That the items of the headers are tuples of strings.

* That there is no 'status' header (that is used in CGI, but not in
  WSGI).

* That the headers don't contain newlines or colons, end in _ or -, or
  contain characters codes below 037.

* That Content-Type is given if there is content (CGI often has a
  default content type, but WSGI does not).

* That no Content-Type is given when there is no content (@@: is this
  too restrictive?)

* That the exc_info argument to start_response is a tuple or None.

* That all calls to the writer are with strings, and no other methods
  on the writer are accessed.

* That wsgi.input is used properly:

  - .read() is called with zero or one argument

  - That it returns a string

  - That readline, readlines, and __iter__ return strings

  - That .close() is not called

  - No other methods are provided

* That wsgi.errors is used properly:

  - .write() and .writelines() is called with a string

  - That .close() is not called, and no other methods are provided.

* The response iterator:

  - That it is not a string (it should be a list of a single string; a
    string will work, but perform horribly).

  - That .__next__() returns a string

  - That the iterator is not iterated over until start_response has
    been called (that can signal either a server or application
    error).

  - That .close() is called (doesn't raise exception, only prints to
    sys.stderr, because we only know it isn't called when the object
    is garbage collected).
Ú	validatoré    Nz^[a-zA-Z][a-zA-Z0-9\-_]*$z[\000-\037]c               @   s   e Zd ZdZdS )ÚWSGIWarningz:
    Raised in response to WSGI-spec-related warnings
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú(/usr/lib64/python3.6/wsgiref/validate.pyr   y   s   r   c             G   s   | st |Ž ‚d S )N)ÚAssertionError)ZcondÚargsr   r   r	   Úassert_~   s    r   c             C   s(   t | ƒtkr| S tdj|t| ƒƒƒ‚d S )Nz!{0} must be of type str (got {1}))ÚtypeÚstrr
   ÚformatÚrepr)ÚvalueÚtitler   r   r	   Úcheck_string_type‚   s    r   c                s   ‡ fdd„}|S )a®  
    When applied between a WSGI server and a WSGI application, this
    middleware will check for WSGI compliancy on a number of levels.
    This middleware does not modify the request or response in any
    way, but will raise an AssertionError if anything seems off
    (except for a failure to close the application iterator, which
    will be printed to stderr -- there's no way to raise an exception
    at that point).
    c                 s’   t t| ƒdkdƒ t | dƒ | \}‰ t|ƒ g ‰‡ ‡fdd„}t|d ƒ|d< t|d ƒ|d< ˆ||ƒ}t |d k	oz|dkd	ƒ t|ƒ t|ˆƒS )
Né   zTwo arguments requiredzNo keyword arguments allowedc                 s’   t t| ƒdkpt| ƒdkd| f ƒ t | dƒ | d }| d }t| ƒdkrV| d }nd }t|ƒ t|ƒ t||ƒ t|ƒ ˆjd ƒ tˆ | Ž ƒS )Nr   é   zInvalid number of arguments: %szNo keyword arguments allowedr   é   )r   ÚlenÚcheck_statusÚcheck_headersÚcheck_content_typeÚcheck_exc_infoÚappendÚWriteWrapper)r   ÚkwÚstatusÚheadersÚexc_info)Ústart_responseÚstart_response_startedr   r	   Ústart_response_wrapperŸ   s    


z;validator.<locals>.lint_app.<locals>.start_response_wrapperz
wsgi.inputzwsgi.errorsFz>The application must return an iterator, if only an empty list)r   r   Úcheck_environÚInputWrapperÚErrorWrapperÚcheck_iteratorÚIteratorWrapper)r   r   Úenvironr$   Úiterator)Úapplication)r"   r#   r	   Úlint_app”   s    
zvalidator.<locals>.lint_appr   )r,   r-   r   )r,   r	   r   ˆ   s    )c               @   s<   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )r&   c             C   s
   || _ d S )N)Úinput)ÚselfÚ
wsgi_inputr   r   r	   Ú__init__Á   s    zInputWrapper.__init__c             G   s0   t t|ƒdkƒ | jj|Ž }t t|ƒtkƒ |S )Nr   )r   r   r.   Úreadr   Úbytes)r/   r   Úvr   r   r	   r2   Ä   s    zInputWrapper.readc             G   s0   t t|ƒdkƒ | jj|Ž }t t|ƒtkƒ |S )Nr   )r   r   r.   Úreadliner   r3   )r/   r   r4   r   r   r	   r5   Ê   s    zInputWrapper.readlinec             G   sN   t t|ƒdkƒ | jj|Ž }t t|ƒtkƒ x|D ]}t t|ƒtkƒ q2W |S )Nr   )r   r   r.   Ú	readlinesr   Úlistr3   )r/   r   ÚlinesÚliner   r   r	   r6   Ð   s    
zInputWrapper.readlinesc             c   s    x| j ƒ }|sd S |V  qW d S )N)r5   )r/   r9   r   r   r	   Ú__iter__Ø   s
    zInputWrapper.__iter__c             C   s   t ddƒ d S )Nr   z input.close() must not be called)r   )r/   r   r   r	   Úcloseß   s    zInputWrapper.closeN)	r   r   r   r1   r2   r5   r6   r:   r;   r   r   r   r	   r&   ¿   s   r&   c               @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )r'   c             C   s
   || _ d S )N)Úerrors)r/   Úwsgi_errorsr   r   r	   r1   ä   s    zErrorWrapper.__init__c             C   s    t t|ƒtkƒ | jj|ƒ d S )N)r   r   r   r<   Úwrite)r/   Úsr   r   r	   r>   ç   s    zErrorWrapper.writec             C   s   | j jƒ  d S )N)r<   Úflush)r/   r   r   r	   r@   ë   s    zErrorWrapper.flushc             C   s   x|D ]}| j |ƒ qW d S )N)r>   )r/   Úseqr9   r   r   r	   Ú
writelinesî   s    
zErrorWrapper.writelinesc             C   s   t ddƒ d S )Nr   z!errors.close() must not be called)r   )r/   r   r   r	   r;   ò   s    zErrorWrapper.closeN)r   r   r   r1   r>   r@   rB   r;   r   r   r   r	   r'   â   s
   r'   c               @   s   e Zd Zdd„ Zdd„ ZdS )r   c             C   s
   || _ d S )N)Úwriter)r/   Zwsgi_writerr   r   r	   r1   ÷   s    zWriteWrapper.__init__c             C   s   t t|ƒtkƒ | j|ƒ d S )N)r   r   r3   rC   )r/   r?   r   r   r	   Ú__call__ú   s    zWriteWrapper.__call__N)r   r   r   r1   rD   r   r   r   r	   r   õ   s   r   c               @   s   e Zd Zdd„ Zdd„ ZdS )ÚPartialIteratorWrapperc             C   s
   || _ d S )N)r+   )r/   Úwsgi_iteratorr   r   r	   r1      s    zPartialIteratorWrapper.__init__c             C   s   t | jd ƒS )N)r)   r+   )r/   r   r   r	   r:     s    zPartialIteratorWrapper.__iter__N)r   r   r   r1   r:   r   r   r   r	   rE   þ   s   rE   c               @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )r)   c             C   s    || _ t|ƒ| _d| _|| _d S )NF)Úoriginal_iteratorÚiterr+   ÚclosedÚcheck_start_response)r/   rF   rJ   r   r   r	   r1   	  s    
zIteratorWrapper.__init__c             C   s   | S )Nr   )r/   r   r   r	   r:     s    zIteratorWrapper.__iter__c             C   sT   t | j dƒ t| jƒ}t|ƒtk	r4t dd|f ƒ | jd k	rPt | jdƒ d | _|S )NzIterator read after closedFz$Iterator yielded non-bytestring (%r)zjThe application returns and we started iterating over its body, but start_response has not yet been called)r   rI   Únextr+   r   r3   rJ   )r/   r4   r   r   r	   Ú__next__  s    

zIteratorWrapper.__next__c             C   s    d| _ t| jdƒr| jjƒ  d S )NTr;   )rI   ÚhasattrrG   r;   )r/   r   r   r	   r;     s    zIteratorWrapper.closec             C   s"   | j stjjdƒ t| j dƒ d S )Nz/Iterator garbage collected without being closed)rI   ÚsysÚstderrr>   r   )r/   r   r   r	   Ú__del__#  s
    zIteratorWrapper.__del__N)r   r   r   r1   r:   rL   r;   rP   r   r   r   r	   r)     s
   r)   c          	   C   sì  t t| ƒtkdt| ƒ| f ƒ x d,D ]}t || kd|f ƒ q$W x*d-D ]"}t || kd||dd … f ƒ qFW d| kr€tjdtƒ xF| jƒ D ]:}d|kr˜qŠt t| | ƒtkd|t| | ƒ| | f ƒ qŠW t t| d ƒtkd| d f ƒ t | d d.kd| d  ƒ t	| d ƒ t
| d ƒ | d d/k�r<tjd!| d  tƒ t | jd"ƒ �pX| d" jd#ƒd$| d"  ƒ t | jd%ƒ �p‚| d% jd#ƒd&| d%  ƒ | jd'ƒ�rºt t| d' ƒd(kd)| d'  ƒ | jd"ƒ�sÔt d%| kd*ƒ t | jd"ƒd#kd+ƒ d S )0Nz:Environment is not of the right type: %r (environment: %r)ÚREQUEST_METHODÚSERVER_NAMEÚSERVER_PORTúwsgi.versionú
wsgi.inputúwsgi.errorsúwsgi.multithreadúwsgi.multiprocessúwsgi.run_oncez$Environment missing required key: %rÚHTTP_CONTENT_TYPEÚHTTP_CONTENT_LENGTHz8Environment should not have the key: %s (use %s instead)é   ZQUERY_STRINGz’QUERY_STRING is not in the WSGI environment; the cgi module will use sys.argv when this variable is missing, so application errors are more likelyÚ.z9Environmental variable %s is not a string: %r (value: %r)z#wsgi.version should be a tuple (%r)zwsgi.url_schemeÚhttpÚhttpszwsgi.url_scheme unknown: %rÚGETÚHEADÚPOSTÚOPTIONSÚPATCHÚPUTÚDELETEÚTRACEzUnknown REQUEST_METHOD: %rZSCRIPT_NAMEú/z$SCRIPT_NAME doesn't start with /: %rZ	PATH_INFOz"PATH_INFO doesn't start with /: %rZCONTENT_LENGTHr   zInvalid CONTENT_LENGTH: %rzgOne of SCRIPT_NAME or PATH_INFO are required (PATH_INFO should at least be '/' if SCRIPT_NAME is empty)zOSCRIPT_NAME cannot be '/'; it should instead be '', and PATH_INFO should be '/')	rQ   rR   rS   rT   rU   rV   rW   rX   rY   )rZ   r[   )r^   r_   )r`   ra   rb   rc   rd   re   rf   rg   )r   r   ÚdictÚwarningsÚwarnr   Úkeysr   ÚtupleÚcheck_inputÚcheck_errorsÚgetÚ
startswithÚint)r*   Úkeyr   r   r	   r%   *  s`      

r%   c             C   s*   x$dD ]}t t| |ƒd| |f ƒ qW d S )Nr2   r5   r6   r:   z-wsgi.input (%r) doesn't have the attribute %s)r2   r5   r6   r:   )r   rM   )r0   Úattrr   r   r	   rn   k  s    

rn   c             C   s*   x$dD ]}t t| |ƒd| |f ƒ qW d S )Nr@   r>   rB   z.wsgi.errors (%r) doesn't have the attribute %s)r@   r>   rB   )r   rM   )r=   rt   r   r   r	   ro   q  s    

ro   c             C   sv   t | dƒ} | jd dƒd }tt|ƒdkd| ƒ t|ƒ}t|dkd| ƒ t| ƒdk sb| d d	krrtjd
|  tƒ d S )NÚStatusr   r   r   z)Status codes must be three characters: %réd   zStatus code is invalid: %ré   ú zjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation)r   Úsplitr   r   rr   rj   rk   r   )r   Zstatus_codeZ
status_intr   r   r	   r   w  s    

r   c             C   s  t t| ƒtkd| t| ƒf ƒ i }xð| D ]è}t t|ƒtkd|t|ƒf ƒ t t|ƒdkƒ |\}}t|dƒ}t|dƒ}t |jƒ dkd| ƒ d ||jƒ < t d|ko¨d	|kd
| ƒ t tj|ƒd| ƒ t |j	dƒ oÞ|j	dƒ d| ƒ t
j|ƒr(t dd|t
j|ƒjdƒf ƒ q(W d S )Nz%Headers (%r) must be of type list: %rz1Individual headers (%r) must be of type tuple: %rr   zHeader namezHeader valuer   zyThe Status header cannot be used; it conflicts with CGI script, and HTTP status is not given through headers (value: %r).Ú
ú:z,Header names may not contain ':' or '\n': %rzBad header name: %rú-Ú_z#Names may not end in '-' or '_': %rr   z#Bad header value: %r (bad char: %r))r   r   r7   rm   r   r   ÚlowerÚ	header_reÚsearchÚendswithÚbad_header_value_reÚgroup)r    Zheader_namesÚitemÚnamer   r   r   r	   r   …  s0    





r   c             C   s~   t | dƒ} t| jd dƒd ƒ}d
}x@|D ]8\}}t |dƒ}|jƒ dkr(||krRd S tdd| ƒ q(W ||krztdd	| ƒ d S )Nru   r   r   éÌ   é0  zHeader namezcontent-typezJContent-Type header found in a %s response, which must not return content.z,No Content-Type header found in headers (%s))r†   r‡   )r   rr   ry   r~   r   )r   r    ÚcodeZNO_MESSAGE_BODYr…   r   r   r   r	   r      s    

r   c             C   s*   t | d kpt| ƒtkd| t| ƒf ƒ d S )Nz exc_info (%r) is not a tuple: %r)r   r   rm   )r!   r   r   r	   r   °  s    r   c             C   s   t t| ttfƒ dƒ d S )NzwYou should not return a string as your application iterator, instead return a single-item list containing a bytestring.)r   Ú
isinstancer   r3   )r+   r   r   r	   r(   µ  s    r(   )r   Ú__all__ÚrerN   rj   Úcompiler   r‚   ÚWarningr   r   r   r   r&   r'   r   rE   r)   r%   rn   ro   r   r   r   r   r(   r   r   r   r	   Ú<module>n   s.   

7#		#A