
    0jX                     J   d Z ddlm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	Z	ddl
Z
	 ddlmZmZ ddlmZmZmZ ddlmZ n'# e$ r ddlmZmZ ddlmZmZ dd	lmZ ddlmZ Y nw xY w ej        e          Zd@d
Zd Zd Zd@dZd Zd Z d Z!d Z" G d de          Z# G d dee$          Z% G d de%          Z& G d de$          Z'edk    rddl(Z(ddl)Z)ddl*m+Z+  ej,        ej-                    e(j.        e(j/        e dz             xZ0Z1e02                    d d!d"#           e02                    d$d%&           e02                    d'e3dd()           e02                    d*e3d+d,)           e02                    d-d.d/0           e02                    d1dd20           e14                                Z5 e+d3e5j6        ie5j7                  Z8 e'e5j9        4          5 Z:e8;                    e5j<        re5j<        =                                ndd5>                    e5j?        e:@                                6          7          ZA eB e)jC        e:D                    eAd8         d9d:d;e5jE        eAd<         =          d>?                     ddd           dS # 1 swxY w Y   dS dS )Aa$  A one-stop helper for desktop app to acquire an authorization code.

It starts a web server to listen redirect_uri, waiting for auth code.
It optionally opens a browser window to guide a human user to manually login.
After obtaining an auth code, the web server will automatically shut down.
    )defaultdictN)Template)
HTTPServerBaseHTTPRequestHandler)urlparseparse_qs	urlencodeescape)r   r   )r	   c                     t          |           5 }|                    |d                              d          cd d d            S # 1 swxY w Y   d S )Nportz<html><body>
                Open this link to <a href='$auth_uri'>Sign In</a>
                (You may want to use incognito window)
                <hr><a href='$abort_uri'>Abort</a>
                </body></html>)auth_uriwelcome_templatecode)AuthCodeReceiverget_auth_responseget)listen_portr   receivers      _/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/msal/oauth2cli/authcode.pyobtain_auth_coder      s    	{	+	+	+ x))" *   c&kk                 s   *AAAc                     	 t          d          5 } |                                 D ]V}|                    dd          d                                         }|                                dk    r d d d            dS W	 d d d            n# 1 swxY w Y   n# t          $ r Y nw xY wt
          j                            d          S )Nz/proc/1/cgroup:   /Tz/.dockerenv)open	readlinessplitstripIOErrorospathexists)flinecgroup_paths      r   _is_inside_dockerr(   +   s(   	"## 	 q     "jja00399;;$$&&#--	  	  	  	  	  	  	  	 
 . 	  	  	  	  	  	  	  	  	  	  	  	  	  	  	     7>>-(((sA   B AB
/B <B
>B 
BB BB 
B#"B#c                      dd l } |                                 }t          |d|d                                                   }t          |d|d                                                   }|dk    od|v S )Nr   systemreleaser   linux	microsoft)platformunamegetattrlower)r.   r/   platform_namer+   s       r   is_wslr3   9   ss    
 OOONNEE8U1X66<<>>MeYa117799GG#>w(>>    c                     	 t                     }|j        dvr"t                              d|j                   dS n,# t          $ r t                              d            Y dS w xY wt           fddD                       rt                              d           dS dd	l}|r)|                    |                                         }n|                               }|spt                      rbdd	l
}	 |                    d
 g          }|dk    }n# t          $ r Y nw xY w|s-	 |                    d g          }|dv }n# t          $ r Y nw xY w|S )zJBrowse uri with named browser. Default browser is customizable by $BROWSER)httphttpsz"Invalid URI scheme for browser: %sFzInvalid URI: %sc              3       K   | ]}|v V  	d S N ).0cr   s     r   	<genexpr>z_browse.<locals>.<genexpr>O   s'      
+
+Q1=
+
+
+
+
+
+r4   z
	zInvalid characters in URIr   Nwslviewzexplorer.exe)r      )r   schemeloggerwarning
ValueErrorany
webbrowserr   r   r3   
subprocesscallFileNotFoundError)r   browser_name
parsed_urirE   browser_openedrF   	exit_codes   `      r   _browserM   E   s   h''
$555NN?ARSSS5 6    ((333uu 
+
+
+
+(
+
+
+++ 2333u 3#55::8DD $22  fhh 	"H(=>>I&!^NN  	 	 	D	 	 'OO^X,FGG	!*f!4$   s3   8> %A'&A':D 
D%$D%+E 
EEc                 >    d |                                  D             S )z;Flatten parse_qs()'s single-item lists into the item itselfc                 z    i | ]8\  }}|t          |t                    rt          |          d k    r|d         n|9S )r?   r   )
isinstancelistlenr;   kvs      r   
<dictcomp>z_qs2kv.<locals>.<dictcomp>p   sS          Aq z!T**As1vv{{qtt      r4   items)qss    r   _qs2kvrZ   n   s+       HHJJ       r4   c                 ,    |                      d          S )N<)
startswithtexts    r   _is_htmlr`   t   s    ??3r4   c                 >    d |                                  D             S )Nc                 4    i | ]\  }}|t          |          S r:   r
   rS   s      r   rV   z_escape.<locals>.<dictcomp>y   s$    ===TQAvayy===r4   rW   )key_value_pairss    r   _escaperd   x   s"    ==_%:%:%<%<====r4   c                 v    t          | t                    r#|                                 st          |           n| S r9   )rP   strisprintablereprr^   s    r   	_printifyri   {   s2    #D#..St7G7G7I7IS4:::tSr4   c                   .    e Zd Zd Zd Zd ZddZd ZdS )	_AuthCodeHandlerc                    t          t          | j                  j                  }|                    dd g          d         }|                    dd g          d         }|dk    r!|                     | j        j                   d S |dk    r|                     dd           d S |r|                     d	d           d S |                     d
d           d S )Nwelcomer   errortrueabortzAuthentication abortedFis_okzresponse_mode=query is not supported for authentication responses. This application operates in response_mode=form_post mode only.z_Authentication could not be completed. You can close this window and return to the application.)r   r   r#   queryr   _send_full_responseserverwelcome_page)selfrY   welcome_paramerror_params       r   do_GETz_AuthCodeHandler.do_GET   s   hty))/00y4&11!4ffWtf--a0F""$$T[%=>>>>>G##$$%=U$KKKKK 
	$$R %      $$q %     r4   c                    t          | j                            dd                    }| j                            |                              d          }t          |          }|                    d          s|                    d          r$|                     t          |                     d S | 	                    dd           d S )	NzContent-Lengthr   utf-8r   rn   zInvalid POST requestFrq   )
intheadersr   rfilereaddecoder   _process_auth_responserZ   rt   )rw   content_length	post_datarY   s       r   do_POSTz_AuthCodeHandler.do_POST   s     T\--.>BBCCJOON33::7CC	i  66&>> 	JRVVG__ 	J''r

33333$$%;5$IIIIIr4   c                    t                               d|           | j        j        r<| j        j        |                    d          k    r|                     dd           dS d|v r| j        j        n| j        j        }t          |j	                  rt          |          }n|}t          t          |          }|                      |j        di |           || j        _        dS )	z:Process the auth response from either GET or POST request.zGot auth response: %sstatez>State mismatch. Waiting for next response... or you may abort.Frq   r   Nr:   )rA   debugru   
auth_stater   rt   success_templateerror_templater`   templaterd   r   rf   safe_substituteauth_response)rw   r   r   	safe_datafilled_datas        r   r   z'_AuthCodeHandler._process_auth_response   s   ,m<<<;! 	6dk&<@Q@QRY@Z@Z&Z&Z $$PX] % _ _ _ _ _ ]** 44040J )** *#M22		)	%c955K$$%=X%=%L%L%L%LMMM(5DK%%%r4   Tc                    |                      |rdnd           t          |          rdnd}|                     d|           |                                  | j                            |                    d                     d S )N   i  z	text/htmlz
text/plainzContent-typer|   )send_responser`   send_headerend_headerswfilewriteencode)rw   bodyrr   content_types       r   rt   z$_AuthCodeHandler._send_full_response   s    %033S111&.tnnF{{,666
W--.....r4   c                 P    t          j        |gt          t          |          R   d S r9   )rA   r   mapri   )rw   formatargss      r   log_messagez_AuthCodeHandler.log_message   s*    V3c)T22333333r4   N)T)__name__
__module____qualname__rz   r   r   rt   r   r:   r4   r   rk   rk      sg          *	J 	J 	J6 6 6&/ / / /4 4 4 4 4r4   rk   c                   $     e Zd Z fdZd Z xZS )_AuthCodeHttpServerc                     |\  }}|r%t           j        dk    st                      rd| _         t	          t
          |           j        |g|R i | d S )Nwin32F)sysr.   r3   allow_reuse_addresssuperr   __init__)rw   server_addressr   kwargs_r   	__class__s         r   r   z_AuthCodeHttpServer.__init__   sg     4 	-S\W,,,
 (-D$1!4((1.R4RRR6RRRRRr4   c                      t          d          )Nz"Timeout. No auth response arrived.)RuntimeErrorrw   s    r   handle_timeoutz"_AuthCodeHttpServer.handle_timeout   s     ?@@@r4   )r   r   r   r   r   __classcell__)r   s   @r   r   r      sS        S S S S SA A A A A A Ar4   r   c                       e Zd Zej        ZdS )_AuthCodeHttpServer6N)r   r   r   socketAF_INET6address_familyr:   r4   r   r   r      s        _NNNr4   r   c                   F    e Zd Zd	dZd Zd
dZ	 	 	 	 ddZd Zd Zd Z	dS )r   Nc                     t                      rdnd}t          |pg           | _        d|v rt          nt          } |||pdft
                    | _        d| _        dS )a  Create a Receiver waiting for incoming auth response.

        :param port:
            The local web server will listen at http://...:<port>
            You need to use the same port when you register with your app.
            If your Identity Provider supports dynamic port, you can use port=0 here.
            Port 0 means to use an arbitrary unused port, per this official example:
            https://docs.python.org/2.7/library/socketserver.html#asynchronous-mixins

        :param scheduled_actions:
            For example, if the input is
            ``[(10, lambda: print("Got stuck during sign in? Call 800-000-0000"))]``
            then the receiver would call that lambda function after
            waiting the response for 10 seconds.
        z0.0.0.0	127.0.0.1r   r   FN)r(   sorted_scheduled_actionsr   r   rk   _server_closing)rw   r   scheduled_actionsaddressServers        r   r   zAuthCodeReceiver.__init__   sn       122C)) #)):)@b"A"A),%%=P vw	24DEEr4   c                 &    | j         j        d         S )z*The port this server actually listening tor?   )r   r   r   s    r   get_portzAuthCodeReceiver.get_port   s     |*1--r4   c                    i }t          j        | j        |f|          }d|_        |                                 t          j                    }|rt          j                    |z
  |k     rn	 t          j        d           |                                sn| j        rt          j                    |z
  | j        d         d         k    rY| j        	                    d          \  }} |             | j        r+t          j                    |z
  | j        d         d         k    Y|rt          j                    |z
  |k     n|pdS )a	  Wait and return the auth response. Raise RuntimeError when timeout.

        :param str auth_uri:
            If provided, this function will try to open a local browser.
            Starting from 2026, the built-in http server will require response_mode=form_post.
        :param int timeout: In seconds. None means wait indefinitely.
        :param str state:
            You may provide the state you used in auth_uri,
            then we will use it to validate incoming response.
        :param str welcome_template:
            If provided, your end user will see it instead of the auth_uri.
            When present, it shall be a plaintext or html template following
            `Python Template string syntax <https://docs.python.org/3/library/string.html#template-strings>`_,
            and include some of these placeholders: $auth_uri and $abort_uri.
        :param str success_template:
            The page will be displayed when authentication was largely successful.
            Placeholders can be any of these:
            https://tools.ietf.org/html/rfc6749#section-5.1
        :param str error_template:
            The page will be displayed when authentication encountered error.
            Placeholders can be any of these:
            https://tools.ietf.org/html/rfc6749#section-5.2
        :param callable auth_uri_callback:
            A function with the shape of lambda auth_uri: ...
            When a browser was unable to be launch, this function will be called,
            so that the app could tell user to manually visit the auth_uri.
        :param str browser_name:
            If you did
            ``webbrowser.register("xyz", None, BackgroundBrowser("/path/to/browser"))``
            beforehand, you can pass in the name "xyz" to use that browser.
            The default value ``None`` means using default browser,
            which is customizable by env var $BROWSER.
        :return:
            The auth response of the first leg of Auth Code flow,
            typically {"code": "...", "state": "..."} or {"error": "...", ...}
            See https://tools.ietf.org/html/rfc6749#section-4.1.2
            and https://openid.net/specs/openid-connect-core-1_0.html#AuthResponse
            Returns None when the state was mismatched, or when timeout occurred.
        )targetr   r   Tr?   r   N)
	threadingThread_get_auth_responsedaemonstarttimesleepis_aliver   pop)rw   timeoutr   resulttbeginr   callbacks           r   r   z"AuthCodeReceiver.get_auth_response  sF   l *&6K K K					18 	ty{{U"W,,,,JqMMM::<< * 	e+d.Ea.H.KKK"599!<<8


 * 	e+d.Ea.H.KKK 29 	ty{{U"W,,,, ~r4   c
                 ~   d                     |                                           }
d                     |
          }t                              d|           |rLt	          t          |          j                  }|                    dd g          d         dk    s
J d	            t          |pd
          	                    ||          | j
        _        |r|r|
dz   n|}t                              d|z             d}	 t          ||	          }n!#  t                              d           Y nxY w|sP|sCt                              d                     |||                                                      n ||           d}t          |pd|z             | j
        _        t          |pd|z             | j
        _        || j
        _        i | j
        _        || j
        _        | j        s-| j
                                         | j
        j        rn| j        -|                    | j
        j                   d S )Nzhttp://localhost:{p})pz{loc}?error=abort)loczAbort by visit %sresponse_moder   	form_postziThe built-in http server supports HTTP POST only. The auth_uri must be built with response_mode=form_post )r   	abort_uriz?welcome=truez*Open a browser on this device to visit: %sF)rI   z_browse(...) unsuccessfula  Found no browser in current environment. If this program is being run inside a container which either (1) has access to host network (i.e. started by `docker run --net=host -it ...`), or (2) published port {port} to host network (i.e. started by `docker run -p 127.0.0.1:{port}:{port} -it ...`), you can use browser on host to visit the following link. Otherwise, this auth attempt would either timeout (current timeout setting is {timeout}) or be aborted by CTRL+C. Auth URI: {auth_uri})r   r   r   z`For your security: Do not share the contents of this page, the address bar, or take screenshots.z\Authentication complete. You can return to the application. Please close this browser tab.

zBAuthentication failed. $error: $error_description. ($error_uri).

)r   r   rA   r   r   r   rs   r   r   r   r   rv   inforM   	exceptionrB   r   r   r   r   r   r   handle_requestupdate)rw   r   r   r   r   r   r   r   auth_uri_callbackrI   netlocr   params_urirK   recommendations                   r   r   z#AuthCodeReceiver._get_auth_responseH  s   
 (...AA'..6.::	()444 	K hx00677F::ov66q9[HHHJ IHH %--=-C$D$D$T$T %U %4 %4! 	,1AOF_,,xDKKDtKLLL"N>!(L!I!I!I>   !<=====! ,( ,NN	H IO%)7 IO IR IRS S S S &%d+++{(01A 2~lo}}) )%&.~ 0d SUcc	'e 'e#  '%'""'- 	 L'')))|)  - 	 	dl011111s   D D3c                 F    d| _         | j                                         dS )zGEither call this eventually; or use the entire class as context managerTN)r   r   server_closer   s    r   closezAuthCodeReceiver.close  s#    !!#####r4   c                     | S r9   r:   r   s    r   	__enter__zAuthCodeReceiver.__enter__  s    r4   c                 .    |                                   d S r9   )r   )rw   exc_typeexc_valexc_tbs       r   __exit__zAuthCodeReceiver.__exit__  s    

r4   )NNr9   )NNNNNNNN)
r   r   r   r   r   r   r   r   r   r   r:   r4   r   r   r      s        ! ! ! !F. . .
D D D DL MQIM"B2 B2 B2 B2H$ $ $
      r4   r   __main__r?   )Client)levelz/The auth code received will be shown at stdout.)formatter_classdescriptionz
--endpointzThe auth endpoint for your app.z>https://login.microsoftonline.com/common/oauth2/v2.0/authorize)helpdefault	client_idz!The client_id of your application)r   z--portzThe port in redirect_uri)typer   r   z	--timeout<   zTimeout value, in secondz--hostr   zThe host of redirect_uri)r   r   z--scopezThe scope listauthorization_endpointr   zhttp://{h}:{p})hr   )scoperedirect_urir   zB<a href='$auth_uri'>Sign In</a>, or <a href='$abort_uri'>Abort</a>z<html>Oh no. $error</html>zOh yeah. Got $coder   )r   r   r   r   r   r      )indentr9   )F__doc__collectionsr   loggingr"   r   r   stringr   r   r   http.serverr   r   urllib.parser   r   r	   htmlr   ImportErrorBaseHTTPServerurllibcgi	getLoggerr   rA   r   r(   r3   rM   rZ   r`   rd   ri   rk   objectr   r   r   argparsejsonoauth2r   basicConfigINFOArgumentParserArgumentDefaultsHelpFormatterr   parseradd_argumentr}   
parse_argsr   endpointr   clientr   r   initiate_auth_code_flowr   r   r   hostr   flowprintdumpsr   r   r:   r4   r   <module>r     s!    $ # # # # #  				  



           >>>>>>>>::::::::::   AAAAAAAA++++++++      	 
	8	$	$	 	 	 	) ) )	? 	? 	?& & & &R          > > >T T T>4 >4 >4 >4 >4- >4 >4 >4BA A A A A*f A A A(% % % % %. % % %} } } } }v } } }B zGgl++++(( >OOQ Q Q QA NN<P  R R R NN;%HNIIINN8#q7QNRRRNN;S";UNVVVNN8[7QNRRRNN9d1ANBBBDV-t}=t~NNF		ty	)	)	) X--(,
<$*""$$$)0049@Q@Q@S@S0TT .   	jdj33*%T71Lw- 4      	 	 	                 # s$   A !A%$A% B)JJJ