U
    [eZy                     @   s  d dl mZ eZdddddddgZzd d	lmZ W n  ek
rR   d d	lmZ Y nX d d
l	Z	d d
l
Z
d d
lZd dlmZ d d
lZd dlmZ d d
lZzd dlmZ W n  ek
r   d dlmZ Y nX zd dlmZ W n  ek
r   d dlmZ Y nX d d
lZd dlmZmZ d dlmZ eekr,eZneZd dl m!Z! d dl"m#Z$m%Z%m&Z&m'Z' d dl(m)Z) dZ*dZ+dZ,dZ-dZ.e/e0e1fZ2dd Z3dd Z4G dd de&Z5G dd de$Z#G dd de$Z6G d d de7Z8G d!d" d"e8Z9G d#d$ d$e8Z:G d%d& d&e8Z;G d'd de7Z<G d(d) d)e<Z=G d*d de=Z>G d+d, d,e?Z@G d-d. d.e@ZAG d/d0 d0e@ZBG d1d2 d2eBZCG d3d4 d4eBZDG d5d6 d6eDZEG d7d8 d8e@ZFG d9d: d:e@ZGG d;d< d<e@ZHG d=d> d>e@ZId
S )?    )print_functionAccessTokenAnonymousAccessToken AuthorizeRequestTokenWithBrowserCredentialStoreRequestTokenAuthorizationEngineConsumerCredentials)StringION)select)stdin)	urlencode)urljoin)	b64decode	b64encode)parse_qs)	HTTPError)r   r   OAuthAuthorizerSystemWideConsumer)urisz+request-tokenz+access-tokenz+authorize-token   i  c                   C   s   t tjddS )zWhether the user has disabled SSL certificate connection.

    Some testing servers have broken certificates.  Rather than raising an
    error, we allow an environment variable,
    ``LP_DISABLE_SSL_CERTIFICATE_VALIDATION`` to disable the check.
    Z%LP_DISABLE_SSL_CERTIFICATE_VALIDATIONF)boolosenvironget r   r   Z/var/www/html/services/stratfitenv/lib/python3.8/site-packages/launchpadlib/credentials.py$_ssl_certificate_validation_disabledV   s    
r   c                 C   sD   t  }tj|dj| d|t|d\}}|jdkr<t||||fS )zPOST to ``url`` with ``headers`` and a body of urlencoded ``params``.

    Wraps it up to make sure we avoid the SSL certificate validation if our
    environment tells us to.  Also, raises an error on non-200 statuses.
    )Z"disable_ssl_certificate_validationPOST)methodheadersbody   )r   httplib2ZHttprequestr   statusr   )urlr    paramsZcert_disabledresponsecontentr   r   r   
_http_postc   s       


r*   c                   @   sX   e Zd ZdZdZdZdZdZdZdd Z	e
d	d
 ZdejefddZejfddZdS )r	   zStandard credentials storage and usage class.

    :ivar consumer: The consumer (application)
    :type consumer: `Consumer`
    :ivar access_token: Access information on behalf of the user
    :type access_token: `AccessToken`
    Nuridictz<BR>
c                 C   s0   t  }| | | }t|tr,|d}|S )zeTurn this object into a string.

        This should probably be moved into OAuthAuthorizer.
        utf-8)r
   savegetvalue
isinstanceunicode_typeencode)selfsio
serializedr   r   r   	serialize   s    


zCredentials.serializec                 C   s,   |  }t |ts|d}|t| |S )z}Create a `Credentials` object from a serialized string.

        This should probably be moved into OAuthAuthorizer.
        r.   )r1   r2   decodeloadr
   )clsvaluecredentialsr   r   r   from_string   s
    

zCredentials.from_stringc           	      C   s   | j dk	std| jdks$tdt|}t| j jddd}|t }d|i}|| jkrbd|d	< t	|||\}}t
|tr|d
}|| jkrt|}|dk	r||d< t|| _|S t|| _d|t| jjf }|dk	r|| j_|d| 7 }|S dS )a  Request an OAuth token to Launchpad.

        Also store the token in self._request_token.

        This method must not be called on an object with no consumer
        specified or if an access token has already been obtained.

        :param context: The context of this token, that is, its scope of
            validity within Launchpad.
        :param web_root: The URL of the website on which the token
            should be requested.
        :token_format: How the token should be
            presented. URI_TOKEN_FORMAT means just return the URL to
            the page that authorizes the token.  DICT_TOKEN_FORMAT
            means return a dictionary describing the token
            and the site's authentication policy.

        :return: If token_format is URI_TOKEN_FORMAT, the URL for the
            user to authorize the `AccessToken` provided by
            Launchpad. If token_format is DICT_TOKEN_FORMAT, a dict of
            information about the new access token.
        NzConsumer not specified.zAccess token already obtained.	PLAINTEXT&)oauth_consumer_keyoauth_signature_methodoauth_signatureRefererzapplication/jsonAcceptr.   
lp.contextz%s%s?oauth_token=%sz&lp.context=%s)consumerAssertionErroraccess_tokenr   lookup_web_rootr,   keyrequest_token_pageDICT_TOKEN_FORMATr*   r1   bytesr8   jsonloadsr   from_params_request_tokenr=   authorize_token_pagecontext)	r4   rS   web_roottoken_formatr'   r&   r    r(   r)   r   r   r   get_request_token   s>    





zCredentials.get_request_tokenc                 C   sl   | j dk	stdt|}t| jjd| j jd| j j d}|t }d|i}t	|||\}}t
|| _dS )ad  Exchange the previously obtained request token for an access token.

        This method must not be called unless get_request_token() has been
        called and completed successfully.

        The access token will be stored as self.access_token.

        :param web_root: The base URL of the website that granted the
            request token.
        Nz5get_request_token() doesn't seem to have been called.r>   z&%s)r@   rA   oauth_tokenrB   rC   )rQ   rG   r   rI   r,   rF   rJ   secretaccess_token_pager*   r   r=   rH   )r4   rT   r'   r&   r    r(   r)   r   r   r   'exchange_request_token_for_access_token   s    

z3Credentials.exchange_request_token_for_access_token)__name__
__module____qualname____doc__rQ   ZURI_TOKEN_FORMATrL   ZITEM_SEPARATORNEWLINEr7   classmethodr=   r   ZSTAGING_WEB_ROOTrV   rZ   r   r   r   r   r	   r   s   

>c                   @   s(   e Zd ZdZedd Zedd ZdS )r   zAn OAuth access token.c                 C   s&   |d }|d }| d}| |||S )z:Create and return a new `AccessToken` from the given dict.rW   oauth_token_secretrE   )r   )r:   r'   rJ   rX   rS   r   r   r   rP      s    
zAccessToken.from_paramsc                 C   s   t |ts|d}t|dd}|d }t|dks<td|d }|d }t|dks`td	|d }|d
}|dk	rt|dkstd|d }| |||S )z<Create and return a new `AccessToken` from the given string.r.   F)keep_blank_valuesrW   r   z/Query string must have exactly one oauth_token.r   ra   z*Query string must have exactly one secret.rE   Nz*Query string must have exactly one context)r1   r2   r8   r   lenrG   r   )r:   Zquery_stringr'   rJ   rX   rS   r   r   r   r=      s"    



zAccessToken.from_stringN)r[   r\   r]   r^   r`   rP   r=   r   r   r   r   r      s
   
c                       s    e Zd ZdZ fddZ  ZS )r   zoAn OAuth access token that doesn't authenticate anybody.

    This token can be used for anonymous access.
    c                    s   t t| dd d S )N )superr   __init__r4   	__class__r   r   rf     s    zAnonymousAccessToken.__init__)r[   r\   r]   r^   rf   __classcell__r   r   rh   r   r     s   c                   @   s:   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdS )r   zStore OAuth credentials locally.

    This is a generic superclass. To implement a specific way of
    storing credentials locally you'll need to subclass this class,
    and implement `do_save` and `do_load`.
    Nc                 C   s
   || _ dS )a  Constructor.

        :param credential_save_failed: A callback to be invoked if the
            save to local storage fails. You should never invoke this
            callback yourself! Instead, you should raise an exception
            from do_save().
        N)credential_save_failedr4   rk   r   r   r   rf   &  s    zCredentialStore.__init__c              
   C   sb   z|  || W nL tk
r&    Y n8 tk
r\ } z| jdkrD||   W 5 d}~X Y nX |S )zSave the credentials and invoke the callback on failure.

        Do not override this method when subclassing. Override
        do_save() instead.
        N)do_saveEXPLOSIVE_ERRORS	Exceptionrk   )r4   r<   unique_consumer_ider   r   r   r/   0  s    
zCredentialStore.savec                 C   s
   t  dS )zStore newly-authorized credentials locally for later use.

        :param credentials: A Credentials object to save.
        :param unique_consumer_id: A string uniquely identifying an
            OAuth consumer on a Launchpad instance.
        NNotImplementedError)r4   r<   rp   r   r   r   rm   @  s    zCredentialStore.do_savec                 C   s
   |  |S )a0  Retrieve credentials from a local store.

        This method is the inverse of `save`.

        There's no special behavior in this method--it just calls
        `do_load`. There _is_ special behavior in `save`, and this
        way, developers can remember to implement `do_save` and
        `do_load`, not `do_save` and `load`.

        :param unique_key: A string uniquely identifying an OAuth consumer
            on a Launchpad instance.

        :return: A `Credentials` object if one is found in the local
            store, and None otherise.
        )do_loadr4   
unique_keyr   r   r   r9   I  s    zCredentialStore.loadc                 C   s
   t  dS )a@  Retrieve credentials from a local store.

        This method is the inverse of `do_save`.

        :param unique_key: A string uniquely identifying an OAuth consumer
            on a Launchpad instance.

        :return: A `Credentials` object if one is found in the local
            store, and None otherise.
        Nrr   ru   r   r   r   rt   [  s    zCredentialStore.do_load)N)	r[   r\   r]   r^   rf   r/   rm   r9   rt   r   r   r   r   r     s   

	c                       sB   e Zd ZdZdZd fdd	Zedd Zd	d
 Zdd Z	  Z
S )KeyringCredentialStorezStore credentials in the GNOME keyring or KDE wallet.

    This is a good solution for desktop applications and interactive
    scripts. It doesn't work for non-interactive scripts, or for
    integrating third-party websites into Launchpad.
    s   <B64>NFc                    s(   t t| | d | _|r$t|| _d S N)re   rw   rf   	_fallbackMemoryCredentialStore)r4   rk   fallbackrh   r   r   rf   s  s    zKeyringCredentialStore.__init__c                   C   sJ   dt  krddladt  krFzddlma W n tk
rD   taY nX dS )aG  Ensure the keyring module is imported (postponing side effects).

        The keyring module initializes the environment-dependent backend at
        import time (nasty).  We want to avoid that initialization because it
        may do things like prompt the user to unlock their password store
        (e.g., KWallet).
        keyringr   NNoKeyringError)r}   )globalsr|   Zkeyring.errorsr}   ImportErrorRuntimeErrorr   r   r   r   _ensure_keyring_importedy  s    	

z/KeyringCredentialStore._ensure_keyring_importedc              
   C   s   |    | }| jt| }ztd||d W nP tk
r } z2ttkr^dt	|kr^ | j
rt| j
|| n W 5 d}~X Y nX dS )z2Store newly-authorized credentials in the keyring.launchpadlibr.   $No recommended backend was availableN)r   r7   	B64MARKERr   r|   set_passwordr8   r}   r   strry   r/   )r4   r<   rv   r6   rq   r   r   r   rm     s$      
zKeyringCredentialStore.do_savec              
   C   s   |    ztd|}W nT tk
rl } z6ttkr@dt|kr@ | jrZ| j| W Y S  W 5 d}~X Y nX |dk	rt|t	r|
d}|| jrzt|t| jd }W n tk
r   Y dS X zt|}|W S  tk
r   Y dS X dS )z&Retrieve credentials from the keyring.r   r   Nutf8)r   r|   get_passwordr}   r   r   ry   r9   r1   r2   r3   
startswithr   r   rc   	TypeErrorr	   r=   ro   )r4   rv   Zcredential_stringrq   r<   r   r   r   rt     s>     



zKeyringCredentialStore.do_load)NF)r[   r\   r]   r^   r   rf   staticmethodr   rm   rt   rj   r   r   rh   r   rw   i  s   
rw   c                       s2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )
UnencryptedFileCredentialStorezStore credentials unencrypted in a file on disk.

    This is a good solution for scripts that need to run without any
    user interaction.
    Nc                    s   t t| | || _d S rx   )re   r   rf   filename)r4   r   rk   rh   r   r   rf     s    
z'UnencryptedFileCredentialStore.__init__c                 C   s   | | j dS )zSave the credentials to disk.N)Zsave_to_pathr   r4   r<   rv   r   r   r   rm     s    z&UnencryptedFileCredentialStore.do_savec                 C   s4   t j| jr0t | jtj dks0t| jS dS )zLoad the credentials from disk.r   N)r   pathexistsr   statST_SIZEr	   Zload_from_pathru   r   r   r   rt     s    z&UnencryptedFileCredentialStore.do_load)Nr[   r\   r]   r^   rf   rm   rt   rj   r   r   rh   r   r     s   r   c                       s2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )
rz   zCredentialStore that stores keys only in memory.

    This can be used to provide a CredentialStore instance without
    actually saving any key to persistent storage.
    Nc                    s   t t| | i | _d S rx   )re   rz   rf   _credentialsrl   rh   r   r   rf     s    zMemoryCredentialStore.__init__c                 C   s   || j |< dS )z!Store the credentials in our dictN)r   r   r   r   r   rm     s    zMemoryCredentialStore.do_savec                 C   s   | j |S )z&Retrieve the credentials from our dict)r   r   ru   r   r   r   rt     s    zMemoryCredentialStore.do_load)Nr   r   r   rh   r   rz     s   rz   c                   @   sJ   e Zd ZdZdZdddZedd Zdd	 Zd
d Z	dd Z
dd ZdS )r   a/  The superclass of all request token authorizers.

    This base class does not implement request token authorization,
    since that varies depending on how you want the end-user to
    authorize a request token. You'll need to subclass this class and
    implement `make_end_user_authorize_token`.
    UNAUTHORIZEDNc                 C   s   t || _t || _|dkr0|dkr0td|dk	rP|dk	rPtd||f |dkrhdg}t|}nt|}|}|| _|| _	|pg | _
dS )aD  Base class initialization.

        :param service_root: The root of the Launchpad instance being
            used.

        :param application_name: The name of the application that
            wants to use launchpadlib. This is used in conjunction
            with a desktop-wide integration.

            If you specify this argument, your values for
            consumer_name and allow_access_levels are ignored.

        :param consumer_name: The OAuth consumer name, for an
            application that wants its own point of integration into
            Launchpad. In almost all cases, you want to specify
            application_name instead and do a desktop-wide
            integration. The exception is when you're integrating a
            third-party website into Launchpad.

        :param allow_access_levels: A list of the Launchpad access
            levels to present to the user. ('READ_PUBLIC' and so on.)
            Your value for this argument will be ignored during a
            desktop-wide integration.
        :type allow_access_levels: A list of strings.
        Nz:You must provide either application_name or consumer_name.zZYou must provide only one of application_name and consumer_name. (You provided %r and %r.)ZDESKTOP_INTEGRATION)r   Zlookup_service_rootservice_rootZweb_root_for_service_rootrT   
ValueErrorr   r   rF   application_nameallow_access_levels)r4   r   r   consumer_namer   rF   r   r   r   rf   	  s(     
z(RequestTokenAuthorizationEngine.__init__c                 C   s   | j jd | j S )z7Return a string identifying this consumer on this host.@)rF   rJ   r   rg   r   r   r   rp   I  s    z2RequestTokenAuthorizationEngine.unique_consumer_idc                 C   s>   dt |f }d}t| jdkr2|||| j 7 }t| j|S )zReturn the authorization URL for a request token.

        This is the URL the end-user must visit to authorize the
        token. How exactly does this happen? That depends on the
        subclass implementation.
        z%s?oauth_token=%sz&allow_permission=r   )rR   rc   r   joinr   rT   )r4   request_tokenpageZallow_permissionr   r   r   authorization_urlN  s    z1RequestTokenAuthorizationEngine.authorization_urlc                 C   s6   |  |}| || |jdkr$dS ||| j |S )ad  Authorize a token and associate it with the given credentials.

        If the credential store runs into a problem storing the
        credential locally, the `credential_save_failed` callback will
        be invoked. The callback will not be invoked if there's a
        problem authorizing the credentials.

        :param credentials: A `Credentials` object. If the end-user
            authorizes these credentials, this object will have its
            .access_token property set.

        :param credential_store: A `CredentialStore` object. If the
            end-user authorizes the credentials, they will be
            persisted locally using this object.

        :return: If the credentials are successfully authorized, the
            return value is the `Credentials` object originally passed
            in. Otherwise the return value is None.
        N)rV   make_end_user_authorize_tokenrH   r/   rp   )r4   r<   Zcredential_storeZrequest_token_stringr   r   r   __call__]  s    

z(RequestTokenAuthorizationEngine.__call__c                 C   s   |j | jtjd}|d S )z\Get a new request token from the server.

        :param return: The request token.
        )rT   rU   rW   )rV   rT   r	   rL   )r4   r<   Zauthorization_jsonr   r   r   rV   {  s
     z1RequestTokenAuthorizationEngine.get_request_tokenc                 C   s
   t  dS )a5  Authorize the given request token using the given credentials.

        Your subclass must implement this method: it has no default
        implementation.

        Because an access token may expire or be revoked in the middle
        of a session, this method may be called at arbitrary points in
        a launchpadlib session, or even multiple times during a single
        session (with a different request token each time).

        In most cases, however, this method will be called at the
        beginning of a launchpadlib session, or not at all.
        Nrr   )r4   r<   r   r   r   r   r     s    z=RequestTokenAuthorizationEngine.make_end_user_authorize_token)NNN)r[   r\   r]   r^   ZUNAUTHORIZED_ACCESS_LEVELrf   propertyrp   r   r   rV   r   r   r   r   r   r     s      
@

c                   @   s@   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dS )AuthorizeRequestTokenWithURLzAuthorize using a URL.

    This authorizer simply shows the URL for the user to open for
    authorization, and waits until the server responds.
    zPlease open this authorization page:
 (%s)
in your browser. Use your browser to authorize
this program to access Launchpad on your behalf.z.Press Enter after authorizing in your browser.c                 C   s   t | dS )zDisplay a message.

        By default, prints the message to standard output. The message
        does not require any user interaction--it's solely
        informative.
        N)print)r4   messager   r   r   output  s    z#AuthorizeRequestTokenWithURL.outputc                 C   s   |  | j|  dS )Notify the end-user of the URL.N)r   WAITING_FOR_USER)r4   r   r   r   r   !notify_end_user_authorization_url  s    z>AuthorizeRequestTokenWithURL.notify_end_user_authorization_urlc              
   C   s|   z| | j W n` tk
rp } zB|jjdkr:t|jn&|jjdkrVtd t| t|jW 5 d}~X Y nX |j	dk	S )z Check if the end-user authorizedi  i  z#Unexpected response from Launchpad:N)
rZ   rT   r   r(   r%   EndUserDeclinedAuthorizationr)   r   EndUserNoAuthorizationrH   )r4   r<   rq   r   r   r   check_end_user_authorization  s    z9AuthorizeRequestTokenWithURL.check_end_user_authorizationc                 C   s"   |  | j t  | | dS )"Wait for the end-user to authorizeN)r   WAITING_FOR_LAUNCHPADr   readliner   )r4   r<   r   r   r   wait_for_end_user_authorization  s    z<AuthorizeRequestTokenWithURL.wait_for_end_user_authorizationc                 C   s"   |  |}| | | | dS )z2Have the end-user authorize the token using a URL.N)r   r   r   )r4   r<   r   r   r   r   r   r     s    

z:AuthorizeRequestTokenWithURL.make_end_user_authorize_tokenN)r[   r\   r]   r^   r   r   r   r   r   r   r   r   r   r   r   r     s   	r   c                       sJ   e Zd ZdZdZdZdZdZdZd fdd		Z	 fd
dZ
dd Z  ZS )r   aS  Authorize using a URL that pops-up automatically in a browser.

    This authorizer simply opens up the end-user's web browser to a
    Launchpad URL and lets the end-user authorize the request token
    themselves.

    This is the same as its superclass, except this class also
    performs the browser automatic opening of the URL.
    zThe authorization page:
 (%s)
should be opening in your browser. Use your browser to authorize
this program to access Launchpad on your behalf.z/Press Enter to continue or wait (%d) seconds...   )zwww-browserlinksZlinks2ZlynxZelinkszelinks-liteZnetrikZw3mz5Waiting to hear from Launchpad about your decision...Nc                    s   t t| ||d| dS )ao  Constructor.

        :param service_root: See `RequestTokenAuthorizationEngine`.
        :param application_name: See `RequestTokenAuthorizationEngine`.
        :param consumer_name: The value of this argument is
            ignored. If we have the capability to open the end-user's
            web browser, we must be running on the end-user's computer,
            so we should do a full desktop integration.
        :param credential_save_failed: See `RequestTokenAuthorizationEngine`.
        :param allow_access_levels: The value of this argument is
            ignored, for the same reason as consumer_name.
        N)re   r   rf   )r4   r   r   r   rk   r   rh   r   r   rf     s    
   z)AuthorizeRequestTokenWithBrowser.__init__c                    s   t t| | z"t }t|dd}|| jk}W n tjk
rP   d}d}Y nX |r| | j	| j
  ttgg g | j
\}}}|rt  |dk	rt| dS )r   basenameNF)re   r   r   
webbrowserr   getattrTERMINAL_BROWSERSErrorr   TIMEOUT_MESSAGETIMEOUTr   r   r   open)r4   r   Zbrowser_objZbrowserZconsole_browserZrlist_rh   r   r   r     s(     
zBAuthorizeRequestTokenWithBrowser.notify_end_user_authorization_urlc                 C   sr   |  | j t }|jdkrntt z| |r8W qnW n tk
rN   Y nX t |t krt	dt qdS )r   NzTimed out after %d seconds.)
r   r   timerH   sleepaccess_token_poll_timer   r   access_token_poll_timeoutTokenAuthorizationTimedOut)r4   r<   
start_timer   r   r   r   &  s    


z@AuthorizeRequestTokenWithBrowser.wait_for_end_user_authorization)NNN)r[   r\   r]   r^   r   r   r   r   r   rf   r   r   rj   r   r   rh   r   r     s      c                   @   s   e Zd ZdS )TokenAuthorizationExceptionNr[   r\   r]   r   r   r   r   r   7  s   r   c                   @   s   e Zd ZdS )RequestTokenAlreadyAuthorizedNr   r   r   r   r   r   ;  s   r   c                   @   s   e Zd ZdZdS )EndUserAuthorizationFailedz?Superclass exception for all failures of end-user authorizationNr[   r\   r]   r^   r   r   r   r   r   ?  s   r   c                   @   s   e Zd ZdZdS )r   zEnd-user declined authorizationNr   r   r   r   r   r   E  s   r   c                   @   s   e Zd ZdZdS )r   z*End-user did not perform any authorizationNr   r   r   r   r   r   K  s   r   c                   @   s   e Zd ZdZdS )r   z<End-user did not perform any authorization in timeout periodNr   r   r   r   r   r   Q  s   r   c                   @   s   e Zd ZdS )ClientErrorNr   r   r   r   r   r   W  s   r   c                   @   s   e Zd ZdS )ServerErrorNr   r   r   r   r   r   [  s   r   c                   @   s   e Zd ZdS )NoLaunchpadAccountNr   r   r   r   r   r   _  s   r   c                   @   s   e Zd ZdS )TooManyAuthenticationFailuresNr   r   r   r   r   r   c  s   r   )J
__future__r   typeZ__metaclass____all__	cStringIOr
   r   ior#   rN   r   r   r   sysr   r   urllib.parser   urllibr   urlparser   base64r   r   Zsix.moves.urllib.parser   rM   r   unicoder2   Zlazr.restfulclient.errorsr   Z"lazr.restfulclient.authorize.oauthr   Z_AccessTokenr   r   r   r   r   rK   rY   rR   r   r   MemoryErrorKeyboardInterrupt
SystemExitrn   r   r*   r	   r   objectr   rw   r   rz   r   r   r   ro   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s   


  
Kf ;f