
    dH                        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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  ej        e           Z!dZ"dZ#dZ$dZ%g dZ&d6dZ'd6de	e(         de)fdZ*de)fdZ+defdZ,d Z-d Z.d Z/d Z0d Z1d Z2d Z3d Z4d Z5 G d  d!          Z6 G d" d#          Z7d$ Z8 G d% d&          Z9 G d' d(          Z: G d) d*          Z; G d+ d,          Z<d- Z= G d. d/e          Z> G d0 d1e          Z? G d2 d3e          Z@ejA        fd4ZBe d5k    r eB             dS dS )7zDHTTP server for dulwich that implements the git smart HTTP protocol.    N)BytesIO)ListOptionalTuple)parse_qs)ServerHandlerWSGIRequestHandler
WSGIServermake_server)	log_utils   )ReceivableProtocol)BaseRepoNotGitRepositoryRepo)DEFAULT_HANDLERS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                 x    | t          j                     } dt          |           fdt          | dz             fdgS )NDater   i3)r   zpublic, max-age=31536000)timedate_time_string)nows    O/home/feoh/.local/pipx/venvs/poetry/lib/python3.11/site-packages/dulwich/web.pycache_forever_headersr   :   sE    
{ikk	!#&&'	$S8^4455     	timestampreturnc                     g d}g d}| t          j                     } t          j        |           d d         \  }}}}}}}	d||	         |||         ||||fz  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wds
             r   r   r   D   s     A@@H  F IKK	'+{9'='=bqb'A$D%b"b"0u


4  r    c                 p    d| j         d|                                                              d          z   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)mats    r   
url_prefixrH   i   s0     MciikkM*005555r    c                 F    |                      t          |                    S )z>Get a Repo instance for the given backend and URL regex match.)open_repositoryrH   )backendrG   s     r   get_reporL   u   s    "":c??333r    c              #   ^  K   ||                      d          V  dS 	 |                     t          |           	 |                    d          }|sn|V  n'# t          $ r |                     d          V  Y nw xY w|                                 dS # |                                 w xY 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datas       r   	send_filerY   z   s       	ymm,-----
G\***	66%==D JJJ		  . . .ii,-------. 	
									s)   9A B !A=:B <A==B B,c                 L    |                      dt          j        j                  S )NrC   )replaceospathsep)urls    r   _url_to_pathr`      s    ;;sBGK(((r    c                    |                                   t          |                                          }t                              d|           t          | t          ||                              |          d          S )NzSending plain text file %s
text/plain)nocacher`   grouploggerinforY   rL   get_named_filerU   rK   rG   r]   s       r   get_text_fileri      sc    KKMMM		$$D
KK,d333S(7C00??EE|TTTr    c              #   0  K   |                     d          |                     d          z                       d          }t                              d|           t	          ||          j        }|                    |          s|                     d          V  d S 	 ||                                         }n(# t          $ r | 
                    d          V  Y d S w xY w|                                  |                     t          d           |V  d S )Nr      asciizSending loose object %szObject not foundzError reading objectzapplication/x-git-loose-object)rd   encodere   rf   rL   object_storecontains_looserN   as_legacy_objectrR   rS   cache_foreverrO   rP   )rU   rK   rG   sharn   rX   s         r   get_loose_objectrs      s     99Q<<#))A,,&
.
.w
7
7C
KK)3///GS))6L&&s++ mm./////C 1133   ii.///// KK9:::
JJJJJs    B; ;!C C c                    |                                   t          |                                          }t                              d|           t          | t          ||                              |          d          S )NSending pack file %sz application/x-git-packed-objectsrq   r`   rd   re   rf   rY   rL   rg   rh   s       r   get_pack_filerw      sq    		$$D
KK&---#--d33*  r    c                    |                                   t          |                                          }t                              d|           t          | t          ||                              |          d          S )Nru   z$application/x-git-packed-objects-tocrv   rh   s       r   get_idx_filery      sq    		$$D
KK&---#--d33.  r    c              #      K   t          | j        d                   }|                    dd g          d         }	 t          ||          }n<# t          $ r/}|                     t          |                    V  Y d }~d S d }~ww xY w|r%| j        s| j                            |	                    d          d           }|| 
                    d          V  d S |                                  |                     t          d|z            }t          t                      j        |          }	 ||t#          |          g|	dd          }
|
j                            d	|	                    d          z   d
z              |
j                            d            |
                                 d S |                                  |                     t          d           t*                              d           t/          |          E d {V  d S )NQUERY_STRINGservicer   rl   Unsupported servicezapplication/x-%s-advertisementT)stateless_rpcadvertise_refss
   # service=   
rb   zEmulating dumb info/refs)r   environgetrL   r   rN   strdumbhandlersrm   	forbiddenrc   rO   rP   r   r   rQ   rH   protowrite_pkt_linehandlere   rf   r   )rU   rK   rG   paramsr|   repoehandler_clswriter   handlers              r   get_info_refsr      s     ck.122FjjTF++A.G%%   mmCFF#####  ,sx ,l&&w~~g'>'>EE-- 566666FG%E%OPP"799>599+__
 
 
 	$$]W^^G5L5L%Lu%TUUU$$T*** 	G\***.///%d+++++++++++s   A 
B$B  Bc                     |                                   |                     t          d           t                              d           t          t          ||                    S )Nrb   zEmulating dumb info/packs)rc   rO   rP   re   rf   r   rL   )rU   rK   rG   s      r   get_info_packsr      sN    KKMMMKK&&&
KK+,,,&x'='=>>>r    c              #      K   	 |                                  }t          |                                d          }|                     |dz             }|dk    rd S |d d         V  c)NT   rk   r   )readlineintrstriprQ   )rV   linelengthchunks       r   _chunk_iterr      sk      zz||T[[]]B''vz""Q;;ECRCjr    c                       e Zd Zd Zd ZdS )ChunkReaderc                 <    t          |          | _        g | _        d S N)r   _iter_buffer)selfrV   s     r   __init__zChunkReader.__init__   s     ^^
r    c                    t          t          t          | j                            |k     ri	 | j                            t          | j                             n# t          $ r Y n/w xY wt          t          t          | j                            |k     id                    | j                  }|d |         }||d          g| _        |S )Nr    )	summaplenr   appendnextr   StopIterationjoin)r   nrV   rets       r   rQ   zChunkReader.read   s    #c4<(())A--##D$4$45555     #c4<(())A--
 HHT\""e!""w
s   ,A 
A'&A'N)__name__
__module____qualname__r   rQ    r    r   r   r      s2          	 	 	 	 	r    r   c                        e Zd ZdZd Z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.
    c                 "    || _         || _        d S r   )_input_bytes_avail)r   input	max_bytess      r   r   z_LengthLimitedFile.__init__  s    %r    c                     | j         dk    rdS |dk    s|| j         k    r| j         }| xj         |z  c_         | j                            |          S )Nr   r    r   )r   r   rQ   )r   sizes     r   rQ   z_LengthLimitedFile.read  s]    !!32:: 111$DT!{%%%r    N)r   )r   r   r   __doc__r   rQ   r   r    r   r   r     sA         & & && & & & & &r    r   c              #   B  K   |                                                     d          }t                              d|           | j                            |                    d          d           }||                     d          V  d S 	 t          ||           n<# t          $ r/}| 
                    t          |                    V  Y d }~d S d }~ww xY w|                                  |                     t          d|z            }| j                            d          dk    r t!          | j        d                   j        }n| j        d         j        }t%          ||          } ||t'          |          g|d	
          }	|	                                 d S )NrC   zHandling service request for %srl   r}   zapplication/x-%s-resultHTTP_TRANSFER_ENCODINGchunked
wsgi.inputT)r~   )rd   lstripre   rf   r   r   rm   r   rL   r   rN   r   rc   rO   rP   r   r   rQ   r   rH   r   )
rU   rK   rG   r|   r   r   r   rQ   r   r   s
             r   handle_service_requestr   "  s     iikk  %%G
KK17;;;,""7>>'#:#:DAAKmm122222#   mmCFF##### KKMMMKK!:W!DEEE
{/00I==3;|455:{<(-tU++E k'JsOO#4e4PPPGNNs   B   
C*$CCc                       e Zd ZdZddefdZd Zeddfdede	e         d	e	e
eeef                           fd
ZdedefdZdedefdZdedefdZddZddZdS )HTTPGitRequestzClass encapsulating the state of a single git HTTP request.

    Attributes:
      environ: the WSGI environment for the request.
    FNr   c                 Z    || _         || _        || _        || _        g | _        g | _        d S r   )r   r   r   _start_response_cache_headers_headers)r   r   start_responser   r   s        r   r   zHTTPGitRequest.__init__B  s2    	 -57/1r    c                 >    | j                             ||f           dS )zAdd a header to the response.N)r   r   )r   namevalues      r   
add_headerzHTTPGitRequest.add_headerJ  s"    dE]+++++r    statusrW   headersc                     |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   rW   r   s       r   rO   zHTTPGitRequest.respondN  sw      	*M  ))) 	AM  .,!?@@@T0111##FDM:::r    messager"   c                     g | _         t                              d|           |                     t          d           |                    d          S )z;Begin a HTTP 404 response and return the text of a message.zNot found: %srb   rl   )r   re   rf   rO   HTTP_NOT_FOUNDrm   r   r   s     r   rN   zHTTPGitRequest.not_found]  D     OW---^\222~~g&&&r    c                     g | _         t                              d|           |                     t          d           |                    d          S )z;Begin a HTTP 403 response and return the text of a message.zForbidden: %srb   rl   )r   re   rf   rO   HTTP_FORBIDDENrm   r   s     r   r   zHTTPGitRequest.forbiddend  r   r    c                     g | _         t                              d|           |                     t          d           |                    d          S )z;Begin a HTTP 500 response and return the text of a message.z	Error: %srb   rl   )r   re   rS   rO   
HTTP_ERRORrm   r   s     r   rS   zHTTPGitRequest.errork  sD     ['***Z...~~g&&&r    c                     t           | _        dS )z2Set the response to never be cached by the client.N)NO_CACHE_HEADERSr   r   s    r   rc   zHTTPGitRequest.nocacher  s    .r    c                 ,    t                      | _        dS )z4Set the response to be cached forever by the client.N)r   r   r   s    r   rq   zHTTPGitRequest.cache_foreverv  s    355r    )FN)r"   N)r   r   r   r   boolr   r   rP   r   r   r   r   rO   bytesrN   r   rS   rc   rq   r   r    r   r   r   ;  s1        2 2d 2 2 2 2, , , &*37	; ;; sm; $uS#X/0	; ; ; ;' ' ' ' ' '' ' ' ' ' ''S 'U ' ' ' '/ / / /6 6 6 6 6 6r    r   c                      e Zd ZdZd ej        d          fed ej        d          fed ej        d          fed ej        d          fed ej        d          fed ej        d          fe	d ej        d	          fe
d ej        d
          fed ej        d          fed ej        d          fei
ZddefdZ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$FNr   c                     || _         || _        t          t                    | _        || _        || j                            |           d S d S r   )rK   r   dictr   r   fallback_appupdate)r   rK   r   r   r   s        r   r   zHTTPGitApplication.__init__  sR    	-..(M  *****  r    c                    |d         }|d         }t          ||| j        | j                  }d }| j                                        D ]4\  }}||k    r|                    |          }	|	r| j        ||f         } n5|3| j        |                     ||          S |                    d          gS  ||| j        |	          S )N	PATH_INFOREQUEST_METHOD)r   r   z#Sorry, that method is not supported)	r   r   r   serviceskeyssearchr   rN   rK   )
r   r   r   r]   methodrU   r   smethodspathrG   s
             r   __call__zHTTPGitApplication.__call__  s    {#)*^$)dm
 
 
 "m0022 	 	NGU&  ,,t$$C -7 ? ,((.AAA&KLLMMwsDL#...r    )FNN)r   r   r   r   recompileri   r   r   rs   rw   ry   r   r   r   r   r   r   r    r   r   r   {  sN         


8$$%}	

=))*M	

6778-	

;<<=}	

1223^BJ?@@	
 BJBCC	
 BJABB	
 	/0013I	01124J'H,+ +d + + + +/ / / / /r    r   c                       e Zd ZdZd Zd ZdS )GunzipFilterzkWSGI middleware that unzips gzip-encoded requests before
    passing on to the underlying application.
    c                     || _         d S r   appr   applications     r   r   zGunzipFilter.__init__      r    c                     dd l }|                    dd          dk    r+|                    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   r   r   r  s       r   r   zGunzipFilter.__call__  s    ;;.33v==$(MMw|'<4 %2 % %GL! /07**,-xx000r    Nr   r   r   r   r   r   r   r    r   r   r     <           
1 
1 
1 
1 
1r    r   c                       e Zd ZdZd Zd ZdS )LimitedInputFilterzgWSGI middleware that limits the input length of a request to that
    specified in Content-Length.
    c                     || _         d S r   r   r   s     r   r   zLimitedInputFilter.__init__  r   r    c                     |                     dd          }|r&t          |d         t          |                    |d<   |                     ||          S )Nr  r   r   )r   r   r   r   )r   r   r   content_lengths       r   r   zLimitedInputFilter.__call__  s\    
 !%5r:: 	$6%s>':':% %GL! xx000r    Nr  r   r    r   r  r    r	  r    r  c                  V    t          | i |}t          t          |                    }|S )zpFactory function to create an instance of HTTPGitApplication,
    correctly wrapped with needed middleware.
    )r   r  r   )argskwargsr   wrapped_apps       r   make_wsgi_chainr    s1     d
-f
-
-C$\#%6%677Kr    c                   $    e Zd ZdZd Zd Zd ZdS )ServerHandlerLoggerz@ServerHandler that uses dulwich's logger for logging exceptions.c                 >    t                               d|           d S Nz/Exception happened during processing of request)exc_infore   	exceptionr   r  s     r   log_exceptionz!ServerHandlerLogger.log_exception  /    = 	 	
 	
 	
 	
 	
r    c                 *    t          j        |g|R   d S r   re   rf   r   formatr  s      r   log_messagezServerHandlerLogger.log_message       F"T""""""r    c                 "    t          j        |  d S r   re   rS   r   r  s     r   	log_errorzServerHandlerLogger.log_error      dr    N)r   r   r   r   r  r"  r'  r   r    r   r  r    sG        JJ
 
 
# # #    r    r  c                   *    e Zd ZdZd Zd Zd Zd ZdS )WSGIRequestHandlerLoggerzEWSGIRequestHandler that uses dulwich's logger for logging exceptions.c                 >    t                               d|           d S r  r  r  s     r   r  z&WSGIRequestHandlerLogger.log_exception  r  r    c                 *    t          j        |g|R   d S r   r  r   s      r   r"  z$WSGIRequestHandlerLogger.log_message  r#  r    c                 "    t          j        |  d S r   r%  r&  s     r   r'  z"WSGIRequestHandlerLogger.log_error  r(  r    c                 T   | j                                         | _        |                                 sdS t	          | j         | j        |                                 |                                           }| |_        |	                    | j
                                                   dS )zHandle a single HTTP requestN)rfiler   raw_requestlineparse_requestr  wfile
get_stderrget_environrequest_handlerrunserverget_app)r   r   s     r   r   zWSGIRequestHandlerLogger.handle  s      $z2244!!## 	F%J
DOO$5$5t7G7G7I7I
 
 #'DK''))*****r    N)r   r   r   r   r  r"  r'  r   r   r    r   r*  r*    sV        OO
 
 
# # #  + + + + +r    r*  c                       e Zd Zd ZdS )WSGIServerLoggerc                 Z    t                               dt          |          z             dS )zHandle an error. z7Exception happened during processing of request from %sN)re   r  r   )r   requestclient_addresss      r   handle_errorzWSGIServerLogger.handle_error  s7    E.!!"	
 	
 	
 	
 	
r    N)r   r   r   r>  r   r    r   r:  r:    s#        
 
 
 
 
r    r:  c                 |   ddl }|                                }|                    ddddd           |                    d	d
dt          dd           |                    |           \  }}t          |          dk    r	|d         }nt          j                    }t          j	                     t          dt          |          i          }t          |          }t          |j        |j        |t           t"                    }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.)rB  typerC  rD  r   rC   )handler_classserver_classz'Listening for HTTP connections on %s:%d)optparseOptionParser
add_optionr   
parse_argsr   r\   getcwdr   default_logging_configr   r   r  r   r@  rE  r*  r:  re   rf   serve_forever)	argvrI  parseroptionsr  gitdirrK   r   r7  s	            r   mainrT  "  sS   OOO""$$F
"     !     %%d++MGT
4yy1}}a$&&&3V-..G
'
"
"C.%  F KK1  
 r    __main__r   )Cr   r\   r   sysr   ior   typingr   r   r   urllib.parser   wsgiref.simple_serverr   r	   r
   r   dulwichr   protocolr   r   r   r   r   r7  r   r   r   r   	getLoggerr   re   rP   r   r   r   r   r   floatr   r   rH   rL   rY   r`   ri   rs   rw   ry   r   r   r   r   r   r   r   r   r   r  r  r  r*  r:  rP  rT  r   r    r   <module>r_     s<  , K J 				 				 



        ( ( ( ( ( ( ( ( ( ( ! ! ! ! ! !< < < < < < < < < < < <       ( ( ( ( ( ( 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 
	X	&	&   (
      " " "3 " " " "J	6s 	6 	6 	6 	64h 4 4 4 4
  2) ) )U U U  "     ,  ,  ,F? ? ?         $& & & & & & & &.  2=6 =6 =6 =6 =6 =6 =6 =6@;/ ;/ ;/ ;/ ;/ ;/ ;/ ;/|1 1 1 1 1 1 1 1*1 1 1 1 1 1 1 1*      -    + + + + +1 + + +:
 
 
 
 
z 
 
 
 h * * * *Z zDFFFFF r    