3
i(]e:                 @   s  d dl mZ d dlZd dlZd dl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 y4d dlZd dlmZmZ d dlZd dlmZ dZW n& ek
r   d	Zd dlZejZY nX d
ZdZdZdZdZdZ dZ!G dd dZ"G dd de#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$d% Z-d&d' Z.G d(d) d)e/Z0G d*d+ d+ee0Z1d,d- Z2d.d/ Z3G d0d1 d1e/Z4d2d3 Z5e6d4krd dl7Z7e7j8d5 j9d6d5 Z:e;e3e: dS )7    )print_functionN)gettext)Thread)ShortcutException)	HTTPErrorURLError)HTTPExceptionFTzNhttps://keyserver.ubuntu.com/pks/lookup?op=get&options=mr&exact=on&search=0x%sz,https://launchpad.net/api/1.0/%s/+archive/%sz https://launchpad.net/api/1.0/%sz%https://launchpad.net/api/1.0/%s/ppasz#https://launchpad.net/api/1.0/%s/%sz"/etc/ssl/certs/ca-certificates.crtc               @   s   e Zd Zdd Zdd ZdS )CurlCallbackc             C   s
   d| _ d S )N )contents)self r   8/usr/lib/python3/dist-packages/softwareproperties/ppa.py__init__>   s    zCurlCallback.__init__c             C   s   | j | | _ d S )N)r   )r   Zbufr   r   r   body_callbackA   s    zCurlCallback.body_callbackN)__name__
__module____qualname__r   r   r   r   r   r   r	   =   s   r	   c               @   s   e Zd ZdddZdd ZdS )PPAExceptionNc             C   s   || _ || _d S )N)valueoriginal_error)r   r   r   r   r   r   r   G   s    zPPAException.__init__c             C   s
   t | jS )N)reprr   )r   r   r   r   __str__K   s    zPPAException.__str__)N)r   r   r   r   r   r   r   r   r   r   E   s   
r   c             C   s   t jdd| S )Nz[^a-zA-Z0-9_-]_)resub)sr   r   r   encodeO   s    r   c             C   s0   t rt| |}n
t| |}|r(tj|S |S d S )N)NEED_PYCURL_get_https_content_pycurl_get_https_content_py3jsonloads)Zurlaccept_jsondatar   r   r   get_info_from_httpsR   s    

r%   c             C   s
   t | dS )NT)r%   )lp_urlr   r   r   get_info_from_lp^   s    r'   c             C   s(   | d dkrd|  } t | |f }t|S )Nr   ~)LAUNCHPAD_PPA_APIr'   )Z
owner_nameppar&   r   r   r   get_ppa_info_from_lpa   s    r+   c             C   s2   t | |f }yt| dS  tk
r,   dS X d S )NTF)!LAUNCHPAD_DISTRIBUTION_SERIES_APIr'   r   )distributionZseriesr&   r   r   r   series_valid_for_distrog   s    r.   c             C   s   t |  }tjjt|d S )NZcurrent_series_link)LAUNCHPAD_DISTRIBUTION_APIospathbasenamer'   )r-   r&   r   r   r   get_current_series_from_lpo   s    r3   c             C   s   yH|rddini }t jjt| |d}t jj|td}|j jdd}W nL tt	fk
r } z,t
|drn|jpp|}td| |f |W Y d d }~X nX |S )	NZAcceptz application/json)headers)Zcafilezutf-8strictreasonzError reading %s: %s)urllibrequestZRequeststrZurlopenLAUNCHPAD_PPA_CERTreaddecoder   r   hasattrr6   r   )r&   r#   r4   r8   Zlp_pager$   er6   r   r   r   r    t   s    $r    c             C   s   yt  }tj }|jtjd |jtjd |jtj|j trN|jtj	t |jtj
t|  |rt|jtjdg |j  |j|j}|j  |j}W n6 tjk
r } ztd| |f |W Y d d }~X nX |dkrtd| |f |S )N      zAccept: application/jsonzError reading %s: %s   z"Error reading %s: response code %i)r	   pycurlZCurlZsetoptZSSL_VERIFYPEERZSSL_VERIFYHOSTZWRITEFUNCTIONr   r:   ZCAINFOZURLr9   Z
HTTPHEADERZperformZgetinfoZRESPONSE_CODEcloser   errorr   )r&   r#   callbackZcurlZresponser$   r>   r   r   r   r      s(    
$r   c             C   s   | j dd }|jdr"|jd}|j dd }|d dkrH|dd  }|j ddd  }g }t|dk rtddg}n(t|dkr|jdd |j| n|}d|dj|f }|S )	N:r?   /r   r(   Zubuntur*   z~%s/%s)split
startswithlstripleninsertextendjoin)shortcutZppa_shortcutuserZppa_path_objsppa_pathr*   r   r   r   mangle_ppa_shortcut   s     


rR   c             C   s   t | dkS )z>Verify that the keyid is a v4 fingerprint with at least 160bit      g      4@)rK   )signing_key_fingerprintr   r   r   verify_keyid_is_v4   s    rV   c               @   sT   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dddZdS )AddPPASigningKeyz; thread class for adding the signing key in the background Nc             C   s   || _ tj | _d S )N)rQ   tempfileZmkdtemp_homedir)r   rQ   	keyserverr   r   r   r      s    zAddPPASigningKey.__init__c             C   s   t j| j d S )N)shutilZrmtreerY   )r   r   r   r   __del__   s    zAddPPASigningKey.__del__c             C   s&   d| j |f }tj|j tjtjdS )NzRgpg -q --homedir %s --no-default-keyring --no-options --import --import-options %s)stdinstdout)rY   
subprocessPopenrH   PIPE)r   argscmdr   r   r   gpg_cmd   s    zAddPPASigningKey.gpg_cmdc             C   sJ   yt |std|  dS W n tk
r8   td dS X tt| ddS )Nz-Error: signing key fingerprint '%s' too shortFz-Error: signing key fingerprint does not exist)r#   )rV   print	TypeErrorr%   SKS_KEYSERVER)r   rU   r   r   r   	_recv_key   s    zAddPPASigningKey._recv_keyc             C   s.   | j d}|j|j \}}|jdkr*dS |S )Nzimport-minimal,import-exportr   F)rd   communicater   
returncode)r   keypminimal_keyr   r   r   r   _minimize_key   s
    

zAddPPASigningKey._minimize_keyc             C   s`   g }| j d}|j|\}}|jdkr\x4|jdj D ]"}|jdr6|j|jdd  q6W |S )Nz-show-only --fingerprint --batch --with-colonsr   zutf-8zfpr:rF   	   )rd   ri   rj   r<   
splitlinesrI   appendrH   )r   rk   Zfingerprintsrl   outputr   liner   r   r   _get_fingerprints   s    


z"AddPPASigningKey._get_fingerprintsc             C   sR   | j |}t|dkr*tdt|  dS |d }||krNtd||f  dS dS )Nr?   z(Got '%s' fingerprints, expected only oneFr   z6Fingerprints do not match, not importing: '%s' != '%s'T)rt   rK   re   )r   rk   Zexpected_fingerprintZgot_fingerprintsZgot_fingerprintr   r   r   _verify_fingerprint   s    
z$AddPPASigningKey._verify_fingerprintc       
   %   C   s  |dkr| j }yt|}W n* tk
rD } zt|j dS d}~X nX y|d }W n, tk
r~ } ztd|  dS d}~X nX | j|}|sdS tjj	d}t
jj|t|d dd }| j|}|sdS | j||sdS td| d	}	|	j| W dQ R X d
S )zQuery and add the corresponding PPA signing key.

        The signing key fingerprint is obtained from the Launchpad PPA page,
        via a secure channel, so it can be trusted.
        NFrU   z/Error: can't find signing_key_fingerprint at %szDir::Etc::trustedparts	referencer?   z%s.gpgwbT)rQ   get_ppa_infor   re   r   
IndexErrorrh   apt_pkgconfigfind_dirr0   r1   rN   r   rn   ru   openwrite)
r   rQ   Zppa_infor>   rU   Zarmored_keyZtrustedgpgdZapt_keyringrm   fr   r   r   add_ppa_signing_key   s2    


z$AddPPASigningKey.add_ppa_signing_key)N)N)r   r   r   __doc__r   r\   rd   rh   rn   rt   ru   r   r   r   r   r   rW      s   

rW   c               @   s   e Zd ZdddZdd ZdS )AddPPASigningKeyThreadNc             C   s   t j|  tj| ||d d S )N)rQ   rZ   )r   r   rW   )r   rQ   rZ   r   r   r   r     s    
zAddPPASigningKeyThread.__init__c             C   s   | j | j d S )N)r   rQ   )r   r   r   r   run  s    zAddPPASigningKeyThread.run)N)r   r   r   r   r   r   r   r   r   r     s   
r   c             C   s"  y g }yyt t|  }W n  tk
r:   tdj| dS X t t|  }|d rXtdntd}|d dkr|jtd|| |d	  |jtd
 xJ|d D ]$}|jtd|d |d d  qW n|jtd|| d  dj|S  tk
 r   dS X W n t	k
r   tdS X d S )Nz,ERROR: '{user}' user or team does not exist.)rP   Zis_teamZteamrP   Z
total_sizer   z:The %(entity)s named '%(user)s' has no PPA named '%(ppa)s')entityrP   r*   z0Please choose from the following available PPAs:Zentriesz * '%(name)s':  %(displayname)snamedisplayname)r   r   z5The %(entity)s named '%(user)s' does not have any PPA)r   rP   
r
   z4Please check that the PPA name or format is correct.)
r'   LAUNCHPAD_USER_APIr   r   formatLAUNCHPAD_USER_PPAS_APIrq   rN   KeyErrorImportError)rP   Zppa_namemsgZlp_userZlp_ppasZentity_namer*   r   r   r   _get_suggested_ppa_message"  s4    




r   c             C   s   | j dd }dj| j ddd  }y:t||}|d j dd |d< |d j dd |d< |S  ttfk
r   g }|jtd||f  td	j|d	 t|| Y n0 t	t
fk
r   ttd
t||f  Y nX d S )NrG   r   r?   Zdistribution_linkr-   Z
owner_linkownerzCannot add PPA: 'ppa:%s/%s'.r   zUCannot access PPA (%s) to get PPA information, please check your internet connection.r   )rH   rN   r+   r   	Exceptionrq   r   r   r   
ValueErrorr   r)   )rO   rP   r*   Zretr   r   r   r   rx   B  s"    

rx   c                   s@   e Zd Z fddZdd ZdddZdd	 Zdd
dZ  ZS )PPAShortcutHandlerc          
      sn   t t| j  yt|| _W n    ttdj|dY nX t| j}d|krd|d rdttd|| _	d S )Nz-ERROR: '{shortcut}' is not a valid ppa format)rO   Zprivatez.Adding private PPAs is not supported currently)
superr   r   rR   rO   r   r   r   rx   _info)r   rO   info)	__class__r   r   r   \  s    


zPPAShortcutHandler.__init__c             C   s   | j S )N)r   )r   r   r   r   r   k  s    zPPAShortcutHandler.infoNc             C   s   |d k	r6|| j d kr6t| j d | r6t| j d }d| j d dd  | j d | j d |f }tjjd}tjj|dt	| j d dd  t	| j d t	| j d |f }||fS )Nr-   z-deb http://ppa.launchpad.net/%s/%s/%s %s mainr   r?   r   zDir::Etc::sourcepartsz%s-%s-%s-%s.list)
r   r.   r3   rz   r{   r|   r0   r1   rN   r   )r   ZcodenameZdistroZdeblineZsourceslistdfilenamer   r   r   expandn  s    
 zPPAShortcutHandler.expandc             C   s   dS )NTr   )r   r   r   r   should_confirm  s    z!PPAShortcutHandler.should_confirmc             C   s   t | jd |d}|j S )Nrv   )rZ   )rW   r   r   )r   rZ   Zapskr   r   r   add_key  s    zPPAShortcutHandler.add_key)N)N)	r   r   r   r   r   r   r   r   __classcell__r   r   )r   r   r   [  s
   
r   c             C   s   | j dsd S t| S )Nzppa:)rI   r   )rO   r   r   r   shortcut_handler  s    
r   __main__r?   rF   )<Z
__future__r   rz   r!   r0   r   r[   r_   rX   r   r   Z	threadingr   Zsoftwareproperties.shortcutsr   Zurllib.requestr7   Zurllib.errorr   r   Zurllib.parseZhttp.clientr   r   r   rB   rD   rg   r)   r   r   r/   r,   r:   r	   r   r   r   r%   r'   r+   r.   r3   r    r   rR   rV   objectrW   r   r   rx   r   r   r   sysargvrH   r*   re   r   r   r   r   <module>   sb   
c 0
