o
    UhI                     @   s   d 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
mZmZ ddlmZ ddlmZmZmZmZ ddlmZ d	d
lmZ d	dlmZmZmZ d	dlmZmZmZm Z m!Z! e"e#Z$dZ%dZ&dZ'dZ(g dZ)dGddZ*dGdee+ de,fddZ-de,fddZ.defddZ/dd Z0dd Z1d d! Z2d"d# Z3d$d% Z4d&d' Z5d(d) Z6d*d+ Z7d,d- Z8G d.d/ d/Z9G d0d1 d1Z:d2d3 Z;G d4d5 d5Z<G d6d7 d7Z=G d8d9 d9Z>G d:d; d;Z?d<d= Z@G d>d? d?eZAG d@dA dAeZBG dBdC dCeZCejDfdHdDdEZEe#dFkreE  dS dS )IzDHTTP server for dulwich that implements the git smart HTTP protocol.    N)Iterator)BytesIO)CallableClassVarOptional)parse_qs)ServerHandlerWSGIRequestHandler
WSGIServermake_server)	log_utils   )ReceivableProtocol)BaseRepoNotGitRepositoryRepo)DEFAULT_HANDLERSBackendDictBackendgenerate_info_refsgenerate_objects_info_packsz200 OKz404 Not Foundz403 Forbiddenz500 Internal Server Error))ExpireszFri, 01 Jan 1980 00:00:00 GMT)Pragmazno-cache)Cache-Controlz$no-cache, max-age=0, must-revalidatec                 C   s.   | d u rt   } dt| fdt| d fdgS )NDater   i3)r   zpublic, max-age=31536000)timedate_time_string)now r   _/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/web.pycache_forever_headersE   s   
r    	timestampreturnc           
      C   s^   g d}g d}| d u rt   } t | d d \}}}}}}}	d||	 ||| ||||f S )N)MonTueWedThuFriSatSun)NJanFebMarAprMayJunJulAugSepOctNovDec   z#%s, %02d %3s %4d %02d:%02d:%02d GMD)r   gmtime)
r!   weekdaysmonthsyearmonthdayhhmmsswdr   r   r   r   O   s    r   c                 C   s   d| j d|   d S )a  Extract the URL prefix from a regex match.

    Args:
      mat: A regex match object.
    Returns: The URL prefix, defined as the text before the match in the
        original string. Normalized to start with one leading slash and end
        with zero.
    /N)stringstartstrip)matr   r   r   
url_prefixt   s   	rF   c                 C   s   |  t|S )z>Get a Repo instance for the given backend and URL regex match.)open_repositoryrF   )backendrE   r   r   r   get_repo   s   rI   c                 c   s    |du r|  dV  dS z3z| t| 	 |d}|sn|V  qW n ty2   | dV  Y nw W |  dS W |  dS |  w )a!  Send a file-like object to the request output.

    Args:
      req: The HTTPGitRequest object to send output to.
      f: An open file-like object to send; will be closed.
      content_type: The MIME type for the file.
    Returns: Iterator over the contents of the file, as chunks.
    NzFile not foundTi (  zError reading file)	not_foundrespondHTTP_OKreadOSErrorerrorclose)reqfcontent_typedatar   r   r   	send_file   s(   	
rU   c                 C   s   |  dtjjS )NrA   )replaceospathsep)urlr   r   r   _url_to_path   s   r[   c                 C   8   |    t| }td| t| t|||dS )NzSending plain text file %s
text/plain)nocacher[   grouploggerinforU   rI   get_named_filerQ   rH   rE   rX   r   r   r   get_text_file   s   rd   c                 c   s    | d| d d}td| t||j}||s'| dV  d S z||  }W n t	y?   | 
dV  Y d S w |   | td |V  d S )Nr      asciizSending loose object %szObject not foundzError reading objectzapplication/x-git-loose-object)r_   encoder`   ra   rI   object_storecontains_looserJ   as_legacy_objectrN   rO   cache_foreverrK   rL   )rQ   rH   rE   sharh   rT   r   r   r   get_loose_object   s    

rm   c                 C   r\   )NSending pack file %sz application/x-git-packed-objectsrk   r[   r_   r`   ra   rU   rI   rb   rc   r   r   r   get_pack_file      rp   c                 C   r\   )Nrn   z$application/x-git-packed-objects-tocro   rc   r   r   r   get_idx_file   rq   rr   c              
   c   sB   t | jd }|dd gd }zt||}W n ty3 } z| t|V  W Y d }~d S d }~ww |r| js| j|	dd }|d u rO| 
dV  d S |   | td| d}tt j|}	||t|g|	ddd	}
|
jd
|	d d  |
jd  |
  d S |   | td td t|E d H  d S )NQUERY_STRINGservicer   rf   Unsupported serviceapplication/x-z-advertisementT)stateless_rpcadvertise_refss
   # service=   
r]   zEmulating dumb info/refs)r   environgetrI   r   rJ   strdumbhandlersrg   	forbiddenr^   rK   rL   r   r   rM   rF   protowrite_pkt_linehandler`   ra   r   )rQ   rH   rE   paramsrt   repoehandler_clswriter   handlerr   r   r   get_info_refs   s@   

r   c                 C   s,   |    | td td tt||S )Nr]   zEmulating dumb info/packs)r^   rK   rL   r`   ra   r   rI   )rQ   rH   rE   r   r   r   get_info_packs   s   
r   c                 c   sD    	 |   }t| d}| |d }|dkrd S |d d V  q)NT   re   r   )readlineintrstriprM   )rR   linelengthchunkr   r   r   _chunk_iter   s   r   c                   @   s   e Zd ZdddZdd ZdS )ChunkReaderr"   Nc                 C   s   t || _g | _d S N)r   _iter_buffer)selfrR   r   r   r   __init__  s   

zChunkReader.__init__c                 C   s~   t tt| j|k r)z| jt| j W n	 ty   Y nw t tt| j|k s
d| j}|d | }||d  g| _|S )N    )	summaplenr   appendnextr   StopIterationjoin)r   nrR   retr   r   r   rM   	  s   zChunkReader.readr"   N)__name__
__module____qualname__r   rM   r   r   r   r   r     s    
r   c                   @   s$   e Zd ZdZd	ddZd
ddZdS )_LengthLimitedFilea  Wrapper class to limit the length of reads from a file-like object.

    This is used to ensure EOF is read from the wsgi.input object once
    Content-Length bytes are read. This behavior is required by the WSGI spec
    but not implemented in wsgiref as of 2.5.
    r"   Nc                 C   s   || _ || _d S r   )_input_bytes_avail)r   input	max_bytesr   r   r   r     s   
z_LengthLimitedFile.__init__c                 C   s@   | j dkrdS |dks|| j kr| j }|  j |8  _ | j|S )Nr   r   r   )r   r   rM   )r   sizer   r   r   rM   !  s   
z_LengthLimitedFile.readr   )r   )r   r   r   __doc__r   rM   r   r   r   r   r     s    
r   c           
   
   c   s   |  d}td| | j|dd }|d u r$| dV  d S zt|| W n t	yF } z| 
t|V  W Y d }~d S d }~ww |   | td| d}| jddkrft| jd	 j}n| jd	 j}t||}||t|g|d
d}	|	  d S )NrA   zHandling service request for %srf   ru   rv   z-resultHTTP_TRANSFER_ENCODINGchunked
wsgi.inputT)rw   )r_   lstripr`   ra   r~   r{   rg   r   rI   r   rJ   r|   r^   rK   rL   rz   r   rM   r   rF   r   )
rQ   rH   rE   rt   r   r   r   rM   r   r   r   r   r   handle_service_request,  s,   
r   c                   @   s   e Zd ZdZ	ddeddfddZddd	Zeddfd
ede	e de	e
eeef   fddZdedefddZdedefddZdedefddZdddZdddZdS )HTTPGitRequestzClass encapsulating the state of a single git HTTP request.

    Attributes:
      environ: the WSGI environment for the request.
    FNr}   r"   c                 C   s(   || _ || _|| _|| _g | _g | _d S r   )rz   r}   r~   _start_response_cache_headers_headers)r   rz   start_responser}   r~   r   r   r   r   L  s   
zHTTPGitRequest.__init__c                 C   s   | j ||f dS )zAdd a header to the response.N)r   r   )r   namevaluer   r   r   
add_headerV  s   zHTTPGitRequest.add_headerstatusrS   headersc                 C   s@   |r| j | |r| j d|f | j | j | || j S )z9Begin a response with the given status and other headers.zContent-Type)r   extendr   r   r   )r   r   rS   r   r   r   r   rK   Z  s   zHTTPGitRequest.respondmessagec                 C   (   g | _ td| | td |dS )z;Begin a HTTP 404 response and return the text of a message.zNot found: %sr]   rf   )r   r`   ra   rK   HTTP_NOT_FOUNDrg   r   r   r   r   r   rJ   i     
zHTTPGitRequest.not_foundc                 C   r   )z;Begin a HTTP 403 response and return the text of a message.zForbidden: %sr]   rf   )r   r`   ra   rK   HTTP_FORBIDDENrg   r   r   r   r   r   p  r   zHTTPGitRequest.forbiddenc                 C   r   )z;Begin a HTTP 500 response and return the text of a message.z	Error: %sr]   rf   )r   r`   rO   rK   
HTTP_ERRORrg   r   r   r   r   rO   w  r   zHTTPGitRequest.errorc                 C   s
   t | _dS )z2Set the response to never be cached by the client.N)NO_CACHE_HEADERSr   r   r   r   r   r^   ~  s   
zHTTPGitRequest.nocachec                 C   s   t  | _dS )z4Set the response to be cached forever by the client.N)r    r   r   r   r   r   rk     s   zHTTPGitRequest.cache_forever)FNr   )r   r   r   r   boolr   r   rL   r|   r   listtuplerK   bytesrJ   r   rO   r^   rk   r   r   r   r   r   E  s0    




r   c                   @   s   e Zd ZU dZdedfededfededfededfededfededfe	ded	fe
ded
fededfededfei
Zeeeeejf eeeejgee f f  ed< 	ddeddfddZdd ZdS )HTTPGitApplicationzClass encapsulating the state of a git WSGI application.

    Attributes:
      backend: the Backend object backing this application
    GETz/HEAD$z/info/refs$z/objects/info/alternates$z/objects/info/http-alternates$z/objects/info/packs$z&/objects/([0-9a-f]{2})/([0-9a-f]{38})$z(/objects/pack/pack-([0-9a-f]{40})\.pack$z'/objects/pack/pack-([0-9a-f]{40})\.idx$POSTz/git-upload-pack$z/git-receive-pack$servicesFNr}   r"   c                 C   s8   || _ || _tt| _|| _|d ur| j| d S d S r   )rH   r}   dictr   r~   fallback_appupdate)r   rH   r}   r~   r   r   r   r   r     s   
zHTTPGitApplication.__init__c           
      C   s   |d }|d }t ||| j| jd}d }| j D ]\}}||kr"q||}	|	r2| j||f } nq|d u rH| jd urB| ||S |dgS ||| j|	S )N	PATH_INFOREQUEST_METHOD)r}   r~   z#Sorry, that method is not supported)	r   r}   r~   r   keyssearchr   rJ   rH   )
r   rz   r   rX   methodrQ   r   smethodspathrE   r   r   r   __call__  s&   

zHTTPGitApplication.__call__)FNN)r   r   r   r   recompilerd   r   r   rm   rp   rr   r   r   r   r   r   r|   Patternr   r   r   Matchr   r   __annotations__r   r   r   r   r   r   r   r     sH   
 

r   c                   @   "   e Zd ZdZdddZdd ZdS )	GunzipFilterzkWSGI middleware that unzips gzip-encoded requests before
    passing on to the underlying application.
    r"   Nc                 C   
   || _ d S r   appr   applicationr   r   r   r        
zGunzipFilter.__init__c                 C   sP   dd l }|dddkr"|jd |d dd|d< |d= d|v r"|d= | ||S )	Nr   HTTP_CONTENT_ENCODING gzipr   rb)filenamefileobjmodeCONTENT_LENGTH)r   r{   GzipFiler   )r   rz   r   r   r   r   r   r     s   

zGunzipFilter.__call__r   r   r   r   r   r   r   r   r   r   r   r         
r   c                   @   r   )	LimitedInputFilterzgWSGI middleware that limits the input length of a request to that
    specified in Content-Length.
    r"   Nc                 C   r   r   r   r   r   r   r   r     r   zLimitedInputFilter.__init__c                 C   s2   | dd}|rt|d t||d< | ||S )Nr   r   r   )r{   r   r   r   )r   rz   r   content_lengthr   r   r   r     s   zLimitedInputFilter.__call__r   r   r   r   r   r   r     r   r   c                  O   s   t | i |}tt|}|S )zpFactory function to create an instance of HTTPGitApplication,
    correctly wrapped with needed middleware.
    )r   r   r   )argskwargsr   wrapped_appr   r   r   make_wsgi_chain  s   r   c                   @   s.   e Zd ZdZd
ddZd
ddZd
dd	ZdS )ServerHandlerLoggerz@ServerHandler that uses dulwich's logger for logging exceptions.r"   Nc                 C      t jd|d d S Nz/Exception happened during processing of request)exc_infor`   	exceptionr   r   r   r   r   log_exception     
z!ServerHandlerLogger.log_exceptionc                 G      t j|g|R   d S r   r`   ra   r   formatr   r   r   r   log_message	     zServerHandlerLogger.log_messagec                 G      t j|  d S r   r`   rO   r   r   r   r   r   	log_error     zServerHandlerLogger.log_errorr   )r   r   r   r   r  r  r  r   r   r   r   r      s
    

r   c                   @   s8   e Zd ZdZdddZdddZddd	Zdd
dZdS )WSGIRequestHandlerLoggerzEWSGIRequestHandler that uses dulwich's logger for logging exceptions.r"   Nc                 C   r   r   r   r   r   r   r   r    r  z&WSGIRequestHandlerLogger.log_exceptionc                 G   r  r   r  r  r   r   r   r    r  z$WSGIRequestHandlerLogger.log_messagec                 G   r	  r   r
  r  r   r   r   r    r  z"WSGIRequestHandlerLogger.log_errorc                 C   sL   | j  | _|  sdS t| j | j|  |  }| |_|	| j
  dS )zHandle a single HTTP request.N)rfiler   raw_requestlineparse_requestr   wfile
get_stderrget_environrequest_handlerrunserverget_app)r   r   r   r   r   r     s   zWSGIRequestHandlerLogger.handler   )r   r   r   r   r  r  r  r   r   r   r   r   r    s    


r  c                   @   s   e Zd ZdddZdS )WSGIServerLoggerr"   Nc                 C   s   t d| dS )zHandle an error.z5Exception happened during processing of request from Nr   )r   requestclient_addressr   r   r   handle_error0  s   zWSGIServerLogger.handle_errorr   )r   r   r   r  r   r   r   r   r  /  s    r  c           	      C   s   ddl }| }|jdddddd |jd	d
dtddd || \}}t|dkr/|d }nt }t	  t
dt|i}t|}t|j|j|ttd}td|j|j |  dS )z,Entry point for starting an HTTP git server.r   Nz-lz--listen_addresslisten_address	localhostzBinding IP address.)destdefaulthelpz-pz--portporti@  zPort to listen on.)r  typer   r!  r   rA   )handler_classserver_classz'Listening for HTTP connections on %s:%d)optparseOptionParser
add_optionr   
parse_argsr   rW   getcwdr   default_logging_configr   r   r   r   r  r"  r  r  r`   ra   serve_forever)	argvr&  parseroptionsr   gitdirrH   r   r  r   r   r   main7  sJ   
r1  __main__r   r   )Fr   rW   r   sysr   collections.abcr   ior   typingr   r   r   urllib.parser   wsgiref.simple_serverr   r	   r
   r   dulwichr   protocolr   r   r   r   r   r  r   r   r   r   r   	getLoggerr   r`   rL   r   r   r   r   r    floatr|   r   rF   rI   rU   r[   rd   rm   rp   rr   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r-  r1  r   r   r   r   <module>   s`   


%#
BE	
-
