o
    X¨Êh.ß  ã                   @   sä  d Z dZdZdZzddlmZ W n ey   ddlmZ Y nw 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ZddlZdZejd	krkzdd
lmZmZmZ W n eyj   dZY nw zddlmZ W n ey…   G dd„ de
jƒZY nw z
e dZeZeZW n eyŸ   dZe Ze ZY nw e
 !e"¡Z#e#j$s®e# %eƒ ¡ ej&j"dkr¹dd„ Z'n	e (d¡Z)dd„ Z'e *¡ Z+dd„ Z,dd„ Z-dd„ Z.dd„ Z/dd„ Z0dd„ Z1d d!„ Z2G d"d#„ d#e3ƒZ4G d$d%„ d%e3ƒZ5e (d&ej6¡Z7d'd(d)d*d+d,d-œZ8G d.d/„ d/e3ƒZ9d0d1„ Z:G d2d3„ d3e;ƒZ<G d4d5„ d5e<ƒZ=G d6d7„ d7e=ƒZ>G d8d9„ d9e3ƒZ?G d:d;„ d;e4e?ƒZ@G d<d=„ d=e3ƒZAG d>d?„ d?eAƒZBG d@dA„ dAe3ƒZCG dBdC„ dCe?ƒZDe (dD EdE¡ej6¡ZFe (dFej6¡ZGG dGdH„ dHe3ƒZHdS )Iah   A wrapper for the 'gpg' command::

Portions of this module are derived from A.M. Kuchling's well-designed
GPG.py, using Richard Jones' updated version 1.3, which can be found
in the pycrypto CVS repository on Sourceforge:

http://pycrypto.cvs.sourceforge.net/viewvc/pycrypto/gpg/GPG.py

This module is *not* forward-compatible with amk's; some of the
old interface has changed.  For instance, since I've added decrypt
functionality, I elected to initialize with a 'gnupghome' argument
instead of 'keyring', so that gpg can find both the public and secret
keyrings.  I've also altered some of the returned objects in order for
the caller to not have to know as much about the internals of the
result classes.

While the rest of ISconf is released under the GPL, I am releasing
this single file under the same terms that A.M. Kuchling used for
pycrypto.

Steve Traugott, stevegt@terraluna.org
Thu Jun 23 21:27:20 PDT 2005

This version of the module has been modified from Steve Traugott's version
(see http://trac.t7a.org/isconf/browser/trunk/lib/python/isconf/GPG.py) by
Vinay Sajip to make use of the subprocess module (Steve's version uses os.fork()
and so does not work on Windows). Renamed to gnupg.py to avoid confusion with
the previous versions.

Modifications Copyright (C) 2008-2018 Vinay Sajip. All rights reserved.

A unittest harness (test_gnupg.py) has also been added.
z0.4.3zVinay Sajipz$13-Jun-2018 12:11:43$é    )ÚStringION)ÚPopen)ÚPIPEÚnt)ÚSTARTUPINFOÚSTARTF_USESHOWWINDOWÚSW_HIDEc                   @   s   e Zd Zdd„ ZdS )ÚNullHandlerc                 C   ó   d S ©N© )ÚselfÚrecordr   r   ú7/var/www/html/env/lib/python3.10/site-packages/gnupg.pyÚhandleB   ó   zNullHandler.handleN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r	   A   s    r	   FTÚntpathc                 C   s   d|  S )Nz"%s"r   ©Úsr   r   r   Úshell_quoteV   s   r   z[^\w%+,./:=@-]c                 C   sL   t | tƒstdt| ƒ ƒ‚| sd}|S t | ¡s| }|S d|  dd¡ }|S )a¦  
        Quote text so that it is safe for Posix command shells.

        For example, "*.py" would be converted to "'*.py'". If the text is
        considered safe it is returned unquoted.

        :param s: The value to quote
        :type s: str (or unicode on 2.x)
        :return: A safe version of the input, from the point of view of Posix
                 command shells
        :rtype: The passed-in type
        zExpected string type, got %sz''z'%s'ú'z'\'')Ú
isinstanceÚstring_typesÚ	TypeErrorÚtypeÚUNSAFEÚsearchÚreplace)r   Úresultr   r   r   r   _   s   

üÿc                 C   s   t st| tƒr|  t¡} | S r   )Ú_py3kr   Ú	text_typeÚencodeÚ
fsencodingr   r   r   r   Úno_quoteƒ   s   
r&   c                 C   sæ   d}t tjdƒrtjj}nd}	 z|  d¡}W n ty'   tjddd� Y n-w |s+n)|t|ƒ7 }z| 	|¡ W n tyI   | 	| 
|¡¡ Y n
   t d	¡ Y nqz| ¡  W n tyj   tjd
dd� Y nw t d|¡ d S )Nr   ÚencodingÚasciiTé   z Exception occurred while readingé   )Úexc_infozError sending dataz)Exception occurred while closing: ignoredzclosed output, %d bytes sent)ÚhasattrÚsysÚstdinr'   ÚreadÚUnicodeErrorÚloggerÚwarningÚlenÚwriter$   Ú	exceptionÚcloseÚIOErrorÚdebug)ÚinstreamÚ	outstreamÚsentÚencÚdatar   r   r   Ú
_copy_dataˆ   s8   
þ
ìÿr>   c                 C   s8   t jt| |fd�}| d¡ t d|| |¡ | ¡  |S )N©ÚtargetÚargsTzdata copier: %r, %r, %r)Ú	threadingÚThreadr>   Ú	setDaemonr1   r8   Ústart)r9   r:   Úwrr   r   r   Ú_threaded_copy_dataª   s
   
rG   c                 C   s*   d| }|  |¡}|  |¡ t d¡ d S )Nz%s
zWrote passphrase)r$   r4   r1   r8   )ÚstreamÚ
passphraser'   r   r   r   Ú_write_passphrase±   s   

rJ   c                 C   s   t | ttttfƒS r   )r   ÚlistÚtupleÚsetÚ	frozenset)Úinstancer   r   r   Ú_is_sequence·   ó   rP   c                 C   s8   zddl m} || ƒ}W |S  ty   t| ƒ}Y |S w )Nr   )ÚBytesIO)ÚiorR   ÚImportErrorr   )r   rR   Úrvr   r   r   Ú_make_memory_streamº   s   
þ
þrV   c                 C   s>   t rt| tƒr|  |¡} t| ƒS t| ƒtur|  |¡} t| ƒS r   )r"   r   Ústrr$   r   rV   )r   r'   r   r   r   Ú_make_binary_streamÂ   s   

þ
rX   c                   @   sf   e Zd ZdZdZdZdZdZdZeeeeedœZ	dd	d
ddœZ
ddiZdd„ Zdd„ ZeZdd„ ZdS )ÚVerifyz#Handle status messages for --verifyr   r*   é   é   é   )ÚTRUST_UNDEFINEDÚTRUST_NEVERÚTRUST_MARGINALÚTRUST_FULLYÚTRUST_ULTIMATEzpermission deniedzfile existszfile not foundznot a directory)r*   é#   éQ   éa   é   zincorrect passphrasec                 C   sd   || _ d| _d  | _ | _| _d  | _| _d | _d | _d | _d | _	d | _
d | _d | _d | _d | _d S ©NF)ÚgpgÚvalidÚfingerprintÚcreation_dateÚ	timestampÚsignature_idÚkey_idÚusernameÚ
key_statusÚstatusÚpubkey_fingerprintÚexpire_timestampÚsig_timestampÚ
trust_textÚtrust_level©r   rg   r   r   r   Ú__init__é   s   
zVerify.__init__c                 C   ó   | j S r   )rh   ©r   r   r   r   Ú__nonzero__ø   ó   zVerify.__nonzero__c                 C   s�  || j v r|| _| j | | _d S |dv rt d||¡ d S |dkr3d| _d| _| d d¡\| _| _	d S |dkrNd| _| ¡ d d… \| _}}}| _
d	| _d S |d
krdd| _d| _| d d¡\| _| _	d S |dkrzd| _d| _| d d¡\| _| _	d S |dkrš| ¡ d d… \| _| _| _| _| ¡ d | _d| _d S |dkrª| ¡ \| _| _| _
d S |dkr¹d| _|| _d| _d S |dkrÈd| _|| _d| _d S |dv rçd| _| ¡ d | _|dkrÞd| _nd| _| j| _d S |dv �r8d| _|| _|dkrûd| _d S d | }| ¡ }|d  ¡ �r-t|d ƒ}t|d!@ ƒ}	|d"@ }|	�r!| j}
n| j}
||
v �r-|
| }| j�s6|| _d S d S |d#v �r?d S t d$||¡ d S )%N©ÚWARNINGÚERRORúpotential problem: %s: %sÚBADSIGFzsignature badr*   ÚERRSIGé   zsignature errorÚEXPSIGzsignature expiredÚGOODSIGTzsignature goodÚVALIDSIGr\   éÿÿÿÿzsignature validÚSIG_IDÚDECRYPTION_FAILEDzdecryption failedÚ	NO_PUBKEYzno public key)Ú	EXPKEYSIGÚ	REVKEYSIGr   rŠ   zsigning key has expiredzsigning key was revoked)Ú
UNEXPECTEDÚFAILURErŒ   zunexpected dataz
error - %si €  iÿ  )ÚDECRYPTION_INFOÚ	PLAINTEXTÚPLAINTEXT_LENGTHÚ	NO_SECKEYÚBEGIN_SIGNINGúmessage ignored: %s, %s)ÚTRUST_LEVELSrt   ru   r1   r2   rh   rp   Úsplitrm   rn   rk   ri   rj   rs   rr   rq   rl   ro   ÚisdigitÚintÚboolÚGPG_SYSTEM_ERROR_CODESÚGPG_ERROR_CODESr8   )r   ÚkeyÚvalueÚalgoÚ	hash_algoÚclsÚmessageÚpartsÚcodeÚsystem_errorÚmappingr   r   r   Úhandle_statusý   s”   
ý
ý
ÿ





ÿ
zVerify.handle_statusN)r   r   r   Ú__doc__r]   r^   r_   r`   ra   r”   r™   rš   rw   rz   Ú__bool__r¥   r   r   r   r   rY   Ë   s0    ûüÿrY   c                   @   s^   e Zd ZdZd ¡ Zdd„ Zdd„ ZeZddd	d
dddœZ	ddddddœZ
dd„ Zdd„ ZdS )ÚImportResultz#Handle status messages for --importz‘count no_user_id imported imported_rsa unchanged
            n_uids n_subk n_sigs n_revoc sec_read sec_imported
            sec_dups not_importedc                 C   s4   || _ g | _g | _g | _| jD ]}t| |d ƒ qd S r   )rg   ÚimportedÚresultsÚfingerprintsÚcountsÚsetattr)r   rg   r!   r   r   r   rw   X  s   
ÿzImportResult.__init__c                 C   s   | j rdS | js
dS dS )NFT)Únot_importedr«   ry   r   r   r   rz   `  s   

zImportResult.__nonzero__zNot actually changedzEntirely new keyzNew user IDszNew signatureszNew subkeyszContains private key)Ú0Ú1Ú2Ú4Ú8Ú16zNo specific reason givenzInvalid CertificatezIssuer Certificate missingzCertificate Chain too longzError storing certificate)r¯   r°   r±   Ú3r²   c                 C   sÀ  |dv rt  d||¡ d S |dv rd S |dkr#| j d dddœ¡ d S |dkre| ¡ \}}g }t| j ¡ ƒD ]\}}t|ƒt|ƒB t|ƒkrK| |¡ q6d	 	|¡d	 }| j |||d
œ¡ | j
 |¡ d S |dkr‰z| ¡ \}}W n   |}d}Y | j ||| j| dœ¡ d S |dkr§| ¡ }	t| jƒD ]\}
}t| |t|	|
 ƒƒ q–d S |dkr·| j d dddœ¡ d S |dkrÇ| j d dddœ¡ d S |dkr×| j d dddœ¡ d S t  d||¡ d S )Nr|   r   )ÚIMPORTEDÚKEY_CONSIDEREDÚNODATAr¯   zNo valid data found)ri   ÚproblemÚtextÚ	IMPORT_OKÚ
)ri   Úokrº   ÚIMPORT_PROBLEMz	<unknown>Ú
IMPORT_RESÚ
KEYEXPIREDzKey expiredÚ
SIGEXPIREDzSignature expiredr�   zOther failurer“   )r1   r2   rª   Úappendr•   rK   Ú	ok_reasonÚitemsr—   Újoinr«   Úproblem_reasonÚ	enumerater¬   r­   r8   )r   r›   rœ   Úreasonri   Úreasonsr¢   rº   Ú
reasontextÚ
import_resÚiÚcountr   r   r   r¥   x  s^   ÿ
€ÿ
ÿÿÿÿÿzImportResult.handle_statusc                 C   s4   g }|  d| j ¡ | jr|  d| j ¡ d |¡S )Nz%d importedz%d not importedú, )rÂ   r©   r®   rÅ   )r   Úlr   r   r   Úsummary£  s
   
zImportResult.summaryN)r   r   r   r¦   r•   r¬   rw   rz   r§   rÃ   rÆ   r¥   rÐ   r   r   r   r   r¨   R  s.    þú
û+r¨   z\\x([0-9a-f][0-9a-f])r¼   úúúúú )z\nz\rz\fz\vz\bz\0c                   @   s   e Zd Zdd„ Zdd„ ZdS )Ú
SendResultc                 C   s
   || _ d S r   )rg   rv   r   r   r   rw   µ  ó   
zSendResult.__init__c                 C   s   t  d||¡ d S )NzSendResult: %s: %s)r1   r8   ©r   r›   rœ   r   r   r   r¥   ¸  rQ   zSendResult.handle_statusN)r   r   r   rw   r¥   r   r   r   r   rÖ   ´  s    rÖ   c                 C   s8   t |ƒD ]\}}|t|ƒk r|| | |< qd| |< qd S )NÚunavailable)rÇ   r3   )r@   Ú
fieldnamesrA   rÌ   Úvarr   r   r   Ú_set_fields»  s
   
ürÜ   c                   @   sD   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 )Ú
SearchKeysz“ Handle status messages for --search-keys.

        Handle pub and uid (relating the latter to the former).

        Don't care about the rest
    r*   z#type keyid algo length date expiresc                 C   s   || _ d | _g | _g | _d S r   )rg   Úcurkeyr«   Úuidsrv   r   r   r   rw   Í  s   
zSearchKeys.__init__c                 C   s&   i }t || j|ƒ g |d< g |d< |S )Nrß   Úsigs)rÜ   ÚFIELDS)r   rA   r!   r   r   r   Ú
get_fieldsÓ  s
   zSearchKeys.get_fieldsc                 C   s   |   |¡ | _}|  |¡ d S r   )râ   rÞ   rÂ   ©r   rA   rÞ   r   r   r   ÚpubÚ  s   zSearchKeys.pubc                 C   sX   || j  }t dd„ |¡}t ¡ D ]
\}}| ||¡}q| jd  |¡ | j |¡ d S )Nc                 S   s   t t|  d¡dƒƒS )Nr*   é   )Úchrr—   Úgroup)Úmr   r   r   Ú<lambda>à  ó    z SearchKeys.uid.<locals>.<lambda>rß   )	Ú	UID_INDEXÚESCAPE_PATTERNÚsubÚBASIC_ESCAPESrÄ   r    rÞ   rÂ   rß   )r   rA   ÚuidÚkÚvr   r   r   rï   Þ  s   
zSearchKeys.uidc                 C   r
   r   r   rØ   r   r   r   r¥   æ  r   zSearchKeys.handle_statusN)r   r   r   r¦   rë   r•   rá   rw   râ   rä   rï   r¥   r   r   r   r   rÝ   Â  s    rÝ   c                       sd   e Zd ZdZdZd ¡ Z‡ fdd„Zdd„ Ze Z	Z
dd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Z‡  ZS )ÚListKeysa   Handle status messages for --list-keys, --list-sigs.

        Handle pub and uid (relating the latter to the former).

        Don't care about (info from src/DETAILS):

        crt = X.509 certificate
        crs = X.509 certificate and private key available
        uat = user attribute (same as user id except for field 10).
        sig = signature
        rev = revocation signature
        pkd = public key data (special field format, see below)
        grp = reserved for gpgsm
        rvk = revocation key
    é	   z}type trust length algo keyid date expires dummy ownertrust uid sig cap issuer flag token hash curve compliance updated originc                    s    t t| ƒ |¡ d| _i | _d S rf   )Úsuperrò   rw   Ú	in_subkeyÚkey_maprv   ©Ú	__class__r   r   rw   ý  s   
zListKeys.__init__c                 C   sL   |   |¡ | _}|d r|d  |d ¡ |d= g |d< |  |¡ d| _d S )Nrï   rß   ÚsubkeysF)râ   rÞ   rÂ   rõ   rã   r   r   r   r›     s   

zListKeys.keyc                 C   sn   |d }|| j v rtd| ƒ‚| js%|| jd< | j |¡ | j| j |< d S | jd d  |¡ | j| j |< d S )Nró   z$Unexpected fingerprint collision: %sri   rù   r†   )rö   Ú
ValueErrorrõ   rÞ   r«   rÂ   )r   rA   Úfpr   r   r   Úfpr  s   

zListKeys.fprc                 C   s.   |  di ¡}i }t|| j|ƒ |||d < d S )NÚsubkey_infor\   )Ú
setdefaultrÜ   rá   )r   rÞ   rA   Úinfo_mapÚinfor   r   r   Ú_collect_subkey_info  s   zListKeys._collect_subkey_infoc                 C   ó8   |d |d g}| j d  |¡ |  | j |¡ d| _d S )Nr\   re   rù   T©rÞ   rÂ   r  rõ   ©r   rA   Úsubkeyr   r   r   rí     s   
zListKeys.subc                 C   s4   |d d g}| j d  |¡ |  | j |¡ d| _d S )Nr\   rù   Tr  r  r   r   r   Ússb(  s   
zListKeys.ssbc                 C   s&   | j d  |d |d |d f¡ d S )Nrà   r\   ró   é
   )rÞ   rÂ   )r   rA   r   r   r   Úsig.  s   &zListKeys.sig)r   r   r   r¦   rë   r•   rá   rw   r›   rä   Úsecrü   r  rí   r  r  Ú__classcell__r   r   r÷   r   rò   é  s    		rò   c                   @   s   e Zd ZdZdd„ ZdS )ÚScanKeysz/ Handle status messages for --with-fingerprint.c                 C   r  )Nr\   r†   rù   Tr  r  r   r   r   rí   5  s   
zScanKeys.subN)r   r   r   r¦   rí   r   r   r   r   r  2  s    r  c                   @   s,   e Zd Zdd„ ZereZdS eZdd„ ZdS )ÚTextHandlerc                 C   s   | j  | jj| jj¡S r   )r=   Údecoderg   r'   Údecode_errorsry   r   r   r   Ú_as_text>  s   zTextHandler._as_textc                 C   rx   r   )r=   ry   r   r   r   Ú__str__F  r{   zTextHandler.__str__N)r   r   r   r  r"   r  Ú__unicode__r   r   r   r   r  =  s    r  c                   @   ó,   e Zd ZdZdd„ Zdd„ ZeZdd„ ZdS )	ÚCryptz2Handle status messages for --encrypt and --decryptc                 C   s(   t  | |¡ d| _d| _d| _d | _d S )NÚ F)rY   rw   r=   r½   rp   rm   rv   r   r   r   rw   L  s
   
zCrypt.__init__c                 C   ó   | j rdS dS ©NTF)r½   ry   r   r   r   rz   S  ó   
zCrypt.__nonzero__c                 C   s4  |dv rt  d||¡ d S |dkrd| _d S |dv r%| dd¡ ¡ | _d S |dkr.d	| _d S |d
kr7d| _d S |dkr@d| _d S |dkrLd| _d| _d S |dkrXd| _d| _d S |dkrad| _d S |dkrjd| _d S |dkrsd| _d S |dkr|d| _d S |dkr‹| dd¡d | _d S |dv r‘d S t 	| ||¡ d S )Nr|   r   r¸   zno data was provided)ÚNEED_PASSPHRASEÚBAD_PASSPHRASEÚGOOD_PASSPHRASEÚMISSING_PASSPHRASErˆ   ÚKEY_NOT_CREATEDÚNEED_PASSPHRASE_PINÚ_ú ÚNEED_PASSPHRASE_SYMzneed symmetric passphraseÚBEGIN_DECRYPTIONzdecryption incompleteÚBEGIN_ENCRYPTIONzencryption incompleteÚDECRYPTION_OKAYzdecryption okTÚEND_ENCRYPTIONzencryption okÚINV_RECPzinvalid recipientrÀ   úkey expiredÚSIG_CREATEDzsig createdrÁ   zsig expiredÚENC_TOr*   r   )	ÚUSERID_HINTÚGOODMDCÚEND_DECRYPTIONÚCARDCTRLÚBADMDCÚSC_OP_FAILUREÚSC_OP_SUCCESSÚPINENTRY_LAUNCHEDr·   )
r1   r2   rp   r    Úlowerr½   r•   rm   rY   r¥   rØ   r   r   r   r¥   Y  s>   









zCrypt.handle_statusN©r   r   r   r¦   rw   rz   r§   r¥   r   r   r   r   r  J  s    r  c                   @   s4   e Zd ZdZdd„ Zdd„ ZeZdd„ Zdd	„ Zd
S )ÚGenKeyz$Handle status messages for --gen-keyc                 C   s   || _ d | _d | _d S r   )rg   r   ri   rv   r   r   r   rw   ƒ  s   
zGenKey.__init__c                 C   r  r  ©ri   ry   r   r   r   rz   ˆ  r  zGenKey.__nonzero__c                 C   s
   | j pdS )Nr  r4  ry   r   r   r   r  Ž  r×   zGenKey.__str__c                 C   sT   |dv rt  d||¡ d S |dkr| ¡ \| _| _d S |dv r!d S t  d||¡ d S )Nr|   r   ÚKEY_CREATED)ÚPROGRESSr  r  r“   )r1   r2   r•   r   ri   r8   rØ   r   r   r   r¥   ‘  s   zGenKey.handle_statusN)	r   r   r   r¦   rw   rz   r§   r  r¥   r   r   r   r   r3  �  s    r3  c                       s    e Zd ZdZ‡ fdd„Z‡  ZS )ÚExportResultzÀHandle status messages for --export[-secret-key].

    For now, just use an existing class to base it on - if needed, we
    can override handle_status for more specific message handling.
    c                    s"   |dv rd S t t| ƒ ||¡ d S )N)ÚEXPORTEDÚ
EXPORT_RES)rô   r7  r¥   rØ   r÷   r   r   r¥   ¡  s   zExportResult.handle_status)r   r   r   r¦   r¥   r
  r   r   r÷   r   r7  ›  s    r7  c                   @   s@   e Zd ZdZdd„ Zdd„ Zdddd	œZd
d„ Zdd„ ZeZ	dS )ÚDeleteResultz?Handle status messages for --delete-key and --delete-secret-keyc                 C   s   || _ d| _d S ©Nr½   )rg   rp   rv   r   r   r   rw   ©  s   
zDeleteResult.__init__c                 C   rx   r   ©rp   ry   r   r   r   r  ­  r{   zDeleteResult.__str__zNo such keyzMust delete secret key firstzAmbiguous specification)r°   r±   rµ   c                 C   s2   |dkr| j  |d| ¡| _d S t d||¡ d S )NÚDELETE_PROBLEMzUnknown error: %rr“   )rÆ   Úgetrp   r1   r8   rØ   r   r   r   r¥   ¶  s
   
ÿzDeleteResult.handle_statusc                 C   s
   | j dkS r;  r<  ry   r   r   r   rz   ½  r×   zDeleteResult.__nonzero__N)
r   r   r   r¦   rw   r  rÆ   r¥   rz   r§   r   r   r   r   r:  §  s    ýr:  c                   @   r  )	ÚSignz!Handle status messages for --signc                 C   s.   || _ d | _d | _d | _d | _d | _d | _d S r   )rg   r   rž   ri   rp   rm   rn   rv   r   r   r   rw   Å  s   
zSign.__init__c                 C   s
   | j d uS r   r4  ry   r   r   r   rz   Î  r×   zSign.__nonzero__c                 C   s¼   |dv rt  d||¡ d S |dv rd| _d S |dkrd| _d S |dkr6| ¡ \| _}| _}| _| _d| _d S |d	krF| d
d¡\| _| _	d S |dkrOd| _d S |dv rUd S t  
d||¡ d S )N)r}   r~   r�   r   )rÀ   rÁ   r&  Ú
KEYREVOKEDzkey revokedr'  zsignature createdr)  r  r*   r  zbad passphrase)r  r  r’   r“   )r1   r2   rp   r•   r   rž   rk   ri   rm   rn   r8   )r   r›   rœ   r�   rŸ   r   r   r   r¥   Ó  s$   

þ

zSign.handle_statusNr2  r   r   r   r   r?  Ã  s    	r?  z(gpg \(GnuPG(?:/MacGPG2)?\) (\d+(\.\d+)*)r(   z
[0-9a-f]+$c                   @   sN  e Zd ZdZeeeeee	e
eeeedœZ	 			dBdd„Zdd	„ ZdCd
d„Zdd„ ZdDdd„ZdEdd„ZdFdd„Zdd„ Zdd„ Z		dGdd„Zdd„ ZdHdd„ZdDdd „Zd!d"„ Zd#d$„ Zd%d&„ Z		dId'd(„Z 		dJd)d*„Z!d+d,„ Z"dKd-d.„Z#d/d0„ Z$dLd2d3„Z%d4d5„ Z&d6d7„ Z'			dMd8d9„Z(d:d;„ Z)d<d=„ Z*		dNd>d?„Z+d@dA„ Z,dS )OÚGPGÚstrict)ÚcryptÚdeleteÚgenerateÚimportÚsendrK   Úscanr   ÚsignÚverifyÚexportrg   NFc                 C   sR  || _ || _|rt|tƒr|g}|| _|rt|tƒr|g}|| _|| _|| _t|tƒr.|g}|| _	d| _
d| _|rGtj | j¡sGt | jd¡ z|  dg¡}W n tyd   d| j  }	t |	¡ t|	ƒ‚w | jd | ƒ}
| j||
|jd� |jdkr„td	|j|
jf ƒ‚t |
j¡}|s‘d| _dS d
 d¡}tdd„ |  ¡ d  !|¡D ƒƒ| _dS )a9  Initialize a GPG process wrapper.  Options are:

        gpgbinary -- full pathname for GPG binary.

        gnupghome -- full pathname to where we can find the public and
        private keyrings.  Default is whatever gpg defaults to.
        keyring -- name of alternative keyring file to use, or list of such
        keyrings. If specified, the default keyring is not used.
        options =-- a list of additional options to pass to the GPG binary.
        secret_keyring -- name of alternative secret keyring file to use, or
        list of such keyrings.
        Nzlatin-1iÀ  z	--versionz1Unable to run gpg (%s) - it may not be available.rJ  ©r.   r   zError invoking gpg: %s: %sÚ.r(   c                 S   ó   g | ]}t |ƒ‘qS r   )r—   ©Ú.0r   r   r   r   Ú
<listcomp>8  rê   z GPG.__init__.<locals>.<listcomp>)"Ú	gpgbinaryÚ	gnupghomer   r   ÚkeyringÚsecret_keyringÚverboseÚ	use_agentrW   ÚoptionsÚon_datar'   ÚosÚpathÚisdirÚmakedirsÚ_open_subprocessÚOSErrorr1   r5   Ú
result_mapÚ_collect_outputr.   Ú
returncoderú   ÚstderrÚ
VERSION_REÚmatchr=   Úversionr$   rL   Úgroupsr•   )r   rR  rS  rV  rW  rT  rX  rU  ÚpÚmsgr!   rè   Údotr   r   r   rw   þ  sJ   




ý
ÿ

&zGPG.__init__c                 C   s  | j ddddg}dtjv r| ddg¡ |r(t| dƒr(| jd	kr(d
dg|dd…< | g d¢¡ | jr<| dt| jƒg¡ | jrS| 	d¡ | jD ]}| dt|ƒg¡ qG| j
re| j
D ]}| dt|ƒg¡ qY|rn| ddg¡ | jrv| 	d¡ | jr| | j¡ | |¡ |S )zÕ
        Make a list of command line elements for GPG. The value of ``args``
        will be appended. The ``passphrase`` argument needs to be True if
        a passphrase will be sent to GPG, else False.
        z--status-fdr±   z--no-ttyz--no-verboseÚ	DEBUG_IPCz--debugÚipcrf  ©rZ   r*   z--pinentry-modeÚloopbackr*   )ú--fixed-list-modez--batchú--with-colonsz	--homedirz--no-default-keyringz	--keyringz--secret-keyringz--passphrase-fdr¯   z--use-agent)rR  rZ  ÚenvironÚextendr,   rf  rS  r&   rT  rÂ   rU  rW  rX  )r   rA   rI   ÚcmdÚfnr   r   r   Ú	make_args:  s0   






zGPG.make_argsc                 C   sr   ddl m} |  ||¡}| jrt||ƒƒ tsd }n	tƒ }t|_t|_	t
|dttt|d�}t d|j||ƒ¡ |S )Nr   )Úlist2cmdlineF)Úshellr.   Ústdoutrc  Ústartupinfoz%s: %s)Ú
subprocessrv  ru  rV  Úprintr   r   ÚdwFlagsr   ÚwShowWindowr   r   r1   r8   Úpid)r   rA   rI   Údebug_printrs  Úsir!   r   r   r   r^  Y  s   ÿzGPG._open_subprocessc                 C   s°   g }	 |  ¡ }t|ƒdkrnB| |¡ | ¡ }| jrt|ƒ t d|¡ |dd… dkrO|dd … }| d d¡}|d }t|ƒdkrG|d }nd}| 	||¡ qd 
|¡|_d S )NTr   z%sró   z	[GNUPG:] r*   r  )Úreadliner3   rÂ   ÚrstriprV  r{  r1   r8   r•   r¥   rÅ   rc  )r   rH   r!   ÚlinesÚlineÚLÚkeywordrœ   r   r   r   Ú_read_responsez  s(   

îzGPG._read_responsec                 C   sv   g }	 |  d¡}t|ƒdkrnt d|d d…  ¡ | |¡ |r%||ƒ qtr3t|ƒƒ  |¡|_d S d |¡|_d S )NTr)   r   z	chunk: %ré   r  )	r/   r3   r1   r8   rÂ   r"   r   rÅ   r=   )r   rH   r!   rY  Úchunksr=   r   r   r   Ú
_read_data–  s   

ùzGPG._read_datac           	      C   sä   t  | j¡|jƒ}tj| j||fd�}| d¡ t 	d|¡ | 
¡  |j}tj| j||| jfd�}| d¡ t 	d|¡ | 
¡  | ¡  | ¡  |durP| ¡  | ¡  |durhz| ¡  W n	 tyg   Y nw | ¡  | ¡  dS )a  
        Drain the subprocesses output streams, writing the collected output
        to the result. If a writer thread (writing to the subprocess) is given,
        make sure it's joined before returning. If a stdin stream is given,
        close it before returning.
        r?   Tzstderr reader: %rzstdout reader: %rN)ÚcodecsÚ	getreaderr'   rc  rB   rC   r‡  rD   r1   r8   rE   rx  rŠ  rY  rÅ   Úwaitr6   r7   )	r   Úprocessr!   Úwriterr.   rc  Úrrrx  Údrr   r   r   ra  §  s.   

ÿzGPG._collect_outputc           	      C   s^   |   ||du¡}|st | j¡|jƒ}n|j}|r t||| jƒ t||ƒ}|  ||||¡ |S )z;Handle a call to GPG - pass input data, collect output dataN)r^  r‹  Ú	getwriterr'   r.   rJ   rG   ra  )	r   rA   Úfileobjr!   rI   Úbinaryrh  r.   r�  r   r   r   Ú
_handle_ioÇ  s   
zGPG._handle_ioc                 K   ó*   t || jƒ}| j|fi |¤Ž}| ¡  |S )zsign message)rX   r'   Ú	sign_filer6   )r   r    ÚkwargsÚfr!   r   r   r   rI  Ù  s   zGPG.signc                 C   s.   t j |¡r| dg¡ | dt|ƒg¡ dS )z@If writing to a file which exists, avoid a confirmation message.z--yesz--outputN)rZ  r[  Úexistsrr  r&   )r   rA   Úoutputr   r   r   Úset_output_without_confirmationà  s   z#GPG.set_output_without_confirmationTc	                 C   sê   t  d|¡ |rdg}	ndg}	|r|	 d¡ n|r|	 d¡ |r)|	 dt|ƒg¡ |r1|  |	|¡ |r8|	 |¡ | jd | ƒ}
|  |	|du¡}z|j}|rTt	||| j
ƒ t||ƒ}W n tyj   t d	¡ d}Y nw |  ||
||¡ |
S )
z	sign filezsign_file: %sz-sz-saz--detach-signz--clearsignú--default-keyrI  Nzerror writing message)r1   r8   rÂ   rr  r&   rœ  r`  r^  r.   rJ   r'   rG   r7   Úloggingr5   ra  )r   ÚfileÚkeyidrI   Ú	clearsignÚdetachr”  r›  Ú
extra_argsrA   r!   rh  r.   r�  r   r   r   r—  ç  s6   


þzGPG.sign_filec                 K   r–  )a<  Verify the signature on the contents of the string 'data'

        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome="keys")
        >>> input = gpg.gen_key_input(passphrase='foo')
        >>> key = gpg.gen_key(input)
        >>> assert key
        >>> sig = gpg.sign('hello',keyid=key.fingerprint,passphrase='bar')
        >>> assert not sig
        >>> sig = gpg.sign('hello',keyid=key.fingerprint,passphrase='foo')
        >>> assert sig
        >>> verify = gpg.verify(sig.data)
        >>> assert verify

        )rX   r'   Úverify_filer6   )r   r=   r˜  r™  r!   r   r   r   rJ    s   z
GPG.verifyc              	   C   sü   t  d||¡ | jd | ƒ}dg}|r| |¡ |du r'| j|||dd� |S t  d¡ ddl}|jd	d
�\}}	| ¡ }
|rB| ¡  t  d|
¡ t	 
||
¡ t	 |¡ | t|	ƒ¡ | t|ƒ¡ z|  |¡}| j|||jd� W t	 |	¡ |S t	 |	¡ w )zCVerify the signature on the contents of the file-like object 'file'zverify_file: %r, %rrJ  ú--verifyNT©r”  zHandling detached verificationr   Úpygpg)ÚprefixzWrote to temp file: %rrL  )r1   r8   r`  rr  r•  ÚtempfileÚmkstempr/   r6   rZ  r4   rÂ   r&   r^  ra  r.   Úunlink)r   rŸ  Údata_filenameÚ
close_filer£  r!   rA   r©  Úfdrt  r   rh  r   r   r   r¤     s2   

ð


ÿzGPG.verify_filec                 C   sh   t  d||dd… ¡ | jd | ƒ}dg}|r| |¡ | t|ƒdg¡ t|ƒ}| j|||dd� |S )	z;Verify the signature in sig_filename against data in memoryzverify_data: %r, %r ...Nrå   rJ  r¥  ú-Tr¦  )r1   r8   r`  rr  r&   rV   r•  )r   Úsig_filenamer=   r£  r!   rA   rH   r   r   r   Úverify_data<  s   
zGPG.verify_datac                 C   s\   | j d | ƒ}t d|dd… ¡ t|| jƒ}| jdg||dd� t d|j¡ | ¡  |S )	z7
        Import the key_data into our keyring.
        rF  zimport_keys: %rNrˆ  ú--importTr¦  zimport_keys result: %r)r`  r1   r8   rX   r'   r•  Ú__dict__r6   )r   Úkey_datar!   r=   r   r   r   Úimport_keysL  s   zGPG.import_keysc                 G   ót   | j d | ƒ}t d|¡ td| jƒ}dt|ƒdg}| dd„ |D ƒ¡ | j|||dd	� t d
|j¡ | 	¡  |S )al  Import a key from a keyserver

        >>> import shutil
        >>> shutil.rmtree("keys", ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome="keys")
        >>> os.chmod('keys', 0x1C0)
        >>> result = gpg.recv_keys('pgp.mit.edu', '92905378')
        >>> assert result

        rF  zrecv_keys: %rr  ú--keyserverz--recv-keysc                 S   rN  r   ©r&   ©rP  rð   r   r   r   rQ  i  rê   z!GPG.recv_keys.<locals>.<listcomp>Tr¦  zrecv_keys result: %r©
r`  r1   r8   rX   r'   r&   rr  r•  r³  r6   ©r   Ú	keyserverÚkeyidsr!   r=   rA   r   r   r   Ú	recv_keysX  s   zGPG.recv_keysc                 G   r¶  )z–Send a key to a keyserver.

        Note: it's not practical to test this function without sending
        arbitrary data to live keyservers.
        rG  zsend_keys: %rr  r·  z--send-keysc                 S   rN  r   r¸  r¹  r   r   r   rQ  z  rê   z!GPG.send_keys.<locals>.<listcomp>Tr¦  zsend_keys result: %rrº  r»  r   r   r   Ú	send_keyso  s   zGPG.send_keysc           
      C   sÖ   d}|r| j dkr|du r|rtdƒ‚d}t|ƒr!dd„ |D ƒ}nt|ƒg}d| g}| |¡ | jd	 | ƒ}|r>| j dk rN|  |¡}| j|||jd
� |S t	d| j
ƒ}	z| j||	||dd� W |	 ¡  |S |	 ¡  w )a4  
        Delete the indicated keys.

        Since GnuPG 2.1, you can't delete secret keys without providing a
        passphrase. However, if you're expecting the passphrase to go to gpg
        via pinentry, you should specify expect_passphrase=False. (It's only
        checked for GnuPG >= 2.1).
        r›   rm  NzHFor GnuPG >= 2.1, deleting secret keys needs a passphrase to be providedz
secret-keyc                 S   rN  r   r¸  rO  r   r   r   rQ  ’  rê   z#GPG.delete_keys.<locals>.<listcomp>z--delete-%srD  rL  r  T©rI   r”  )rf  rú   rP   r&   rr  r`  r^  ra  r.   rX   r'   r•  r6   )
r   r«   ÚsecretrI   Úexpect_passphraseÚwhichrA   r!   rh  r™  r   r   r   Údelete_keys€  s2   
ÿ



	úÿ
ÿzGPG.delete_keysc                 C   s  d}|rd}| j dkr|du r|rtdƒ‚t|ƒr!dd„ |D ƒ}nt|ƒg}d| g}|r2| d	¡ |r;| d
dg¡ | |¡ | jd | ƒ}	|rN| j dk r]|  |¡}
| j|
|	|
j	d� nt
d| jƒ}z| j|||	|dd� W | ¡  n| ¡  w t d|	j¡ |	j}	|r�|	 | j| j¡}	|	S )aW  
        Export the indicated keys. A 'keyid' is anything gpg accepts.

        Since GnuPG 2.1, you can't export secret keys without providing a
        passphrase. However, if you're expecting the passphrase to go to gpg
        via pinentry, you should specify expect_passphrase=False. (It's only
        checked for GnuPG >= 2.1).
        r  z-secret-keyrm  NzIFor GnuPG >= 2.1, exporting secret keys needs a passphrase to be providedc                 S   rN  r   r¸  r¹  r   r   r   rQ  ¸  rê   z#GPG.export_keys.<locals>.<listcomp>z
--export%sú--armorz--export-optionszexport-minimalrK  rL  TrÀ  zexport_keys result: %r)rf  rú   rP   r&   rÂ   rr  r`  r^  ra  r.   rX   r'   r•  r6   r1   r8   r=   r  r  )r   r½  rÁ  ÚarmorÚminimalrI   rÂ  rÃ  rA   r!   rh  r™  r   r   r   Úexport_keys¥  s>   ÿ




ÿzGPG.export_keysc           	      C   s¦   | j | | ƒ}| j|||jd� |j | j| j¡ ¡ }d ¡ }|D ]/}| j	r*t
|ƒ t d| ¡ ¡ |s7 |S | ¡  d¡}|sAq!|d }||v rPt||ƒ|ƒ q!|S )NrL  zpub uid sec fpr sub ssb sigúline: %rú:r   )r`  ra  r.   r=   r  r'   r  Ú
splitlinesr•   rV  r{  r1   r8   r‚  ÚstripÚgetattr)	r   rh  Úkindr!   rƒ  Úvalid_keywordsr„  r…  r†  r   r   r   Ú_get_list_output×  s.   
ÿÿú€zGPG._get_list_outputc                 C   sX   |rd}nd}|rd}d| ddg}|r!t |tƒr|g}| |¡ |  |¡}|  |d¡S )aP   list the keys currently in the keyring

        >>> import shutil
        >>> shutil.rmtree("keys", ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome="keys")
        >>> input = gpg.gen_key_input(passphrase='foo')
        >>> result = gpg.gen_key(input)
        >>> fp1 = result.fingerprint
        >>> result = gpg.gen_key(input)
        >>> fp2 = result.fingerprint
        >>> pubkeys = gpg.list_keys()
        >>> assert fp1 in pubkeys.fingerprints
        >>> assert fp2 in pubkeys.fingerprints

        rà   Úkeyszsecret-keysz	--list-%sú--fingerprintrK   )r   r   rr  r^  rÐ  )r   rÁ  rÑ  rà   rÃ  rA   rh  r   r   r   Ú	list_keysì  s   ÿ


zGPG.list_keysc                 C   sJ   | j dkr
g d¢}n	t d¡ g d¢}| t|ƒ¡ |  |¡}|  |d¡S )an  
        List details of an ascii armored or binary key file
        without first importing it to the local keyring.

        The function achieves this on modern GnuPG by running:

        $ gpg --dry-run --import-options import-show --import

        On older versions, it does the *much* riskier:

        $ gpg --with-fingerprint --with-colons filename
        rm  )z	--dry-runz--import-optionszimport-showr²  zTTrying to list packets, but if the file is not a keyring, might accidentally decrypt)z--with-fingerprintrp  ro  rH  )rf  r1   r2   rÂ   r&   r^  rÐ  )r   ÚfilenamerA   rh  r   r   r   Ú	scan_keys  s   



zGPG.scan_keysúpgp.mit.educ                 C   sÜ   |  ¡ }t |¡rd| }ddt|ƒdt|ƒg}|  |¡}| jd | ƒ}| j|||jd� |j 	| j
| j¡ ¡ }ddg}|D ]-}| jrGt|ƒ t d	| ¡ ¡ |sRq>|  ¡  d
¡}	|	s\q>|	d }
|
|v rkt||
ƒ|	ƒ q>|S )aj   search keyserver by query (using --search-keys option)

        >>> import shutil
        >>> shutil.rmtree('keys', ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome='keys')
        >>> os.chmod('keys', 0x1C0)
        >>> result = gpg.search_keys('<vinay_sajip@hotmail.com>')
        >>> assert result, 'Failed using default keyserver'
        >>> #keyserver = 'keyserver.ubuntu.com'
        >>> #result = gpg.search_keys('<vinay_sajip@hotmail.com>', keyserver)
        >>> #assert result, 'Failed using keyserver.ubuntu.com'

        Ú0xrÒ  r·  z--search-keysr   rL  rä   rï   rÉ  rÊ  r   )rÌ  ÚHEX_DIGITS_REre  r&   r^  r`  ra  r.   r=   r  r'   r  rË  rV  r{  r1   r8   r‚  r•   rÍ  )r   Úqueryr¼  rA   rh  r!   rƒ  rÏ  r„  r…  r†  r   r   r   Úsearch_keys#  s<   

þ

ÿÿ€zGPG.search_keysc                 C   s>   dg}| j d | ƒ}t|| jƒ}| j|||dd� | ¡  |S )a•  Generate a key; you might use gen_key_input() to create the
        control input.

        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome="keys")
        >>> input = gpg.gen_key_input(passphrase='foo')
        >>> result = gpg.gen_key(input)
        >>> assert result
        >>> result = gpg.gen_key('foo')
        >>> assert not result

        z	--gen-keyrE  Tr¦  )r`  rX   r'   r•  r6   )r   ÚinputrA   r!   r™  r   r   r   Úgen_keyN  s   zGPG.gen_keyc                 K   sâ   i }t | ¡ ƒD ]\}}| dd¡ ¡ }t|ƒ ¡ r|||< q| dd¡ | dd¡ | dd¡ tj 	d	¡p>tj 	d
¡p>d}t
 ¡ }| dd| dd¡|f ¡ d| d¡ }t | ¡ ƒD ]\}}|d||f 7 }q^|d7 }|S )z>
        Generate --gen-key input per gpg doc/DETAILS
        r  r¯  zKey-TypeÚRSAz
Key-Lengthi   z	Name-RealzAutogenerated KeyÚLOGNAMEÚUSERNAMEÚunspecifiedz
Name-Emailz%s@%sr  zKey-Type: %s
z%s: %s
z%commit
)rK   rÄ   r    ÚtitlerW   rÌ  rþ   rZ  rq  r>  ÚsocketÚgethostnameÚpop)r   r˜  Úparmsr›   ÚvalÚlognameÚhostnameÚoutr   r   r   Úgen_key_inputb  s*   €ÿÿzGPG.gen_key_inputc
                 C   sü   dg}
|rdg}
|dur|
  dt|ƒg¡ n|stdƒ‚t|ƒs#|f}|D ]}|
  dt|ƒg¡ q%|r8|
 d¡ |r@|  |
|¡ |du rJ|
 d¡ n|rV|
  dd	t|ƒg¡ |r]|
 d
¡ |	rd|
  |	¡ | jd | ƒ}| j|
|||dd� t 	d|j
¡ |S )z9Encrypt the message read from the file-like object 'file'z	--encryptz--symmetricTz--cipher-algoz2No recipients specified with asymmetric encryptionz--recipientrÅ  z--signr�  ú--always-trustrC  rÀ  zencrypt result: %r)rr  r&   rú   rP   rÂ   rœ  r`  r•  r1   r8   r=   )r   rŸ  Ú
recipientsrI  Úalways_trustrI   rÆ  r›  Ú	symmetricr£  rA   Ú	recipientr!   r   r   r   Úencrypt_file’  s8   €


zGPG.encrypt_filec                 K   s,   t || jƒ}| j||fi |¤Ž}| ¡  |S )aX  Encrypt the message contained in the string 'data'

        >>> import shutil
        >>> if os.path.exists("keys"):
        ...     shutil.rmtree("keys", ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome="keys")
        >>> input = gpg.gen_key_input(name_email='user1@test', passphrase='pp1')
        >>> result = gpg.gen_key(input)
        >>> fp1 = result.fingerprint
        >>> input = gpg.gen_key_input(name_email='user2@test', passphrase='pp2')
        >>> result = gpg.gen_key(input)
        >>> fp2 = result.fingerprint
        >>> result = gpg.encrypt("hello",fp2)
        >>> message = str(result)
        >>> assert message != 'hello'
        >>> result = gpg.decrypt(message, passphrase='pp2')
        >>> assert result
        >>> str(result)
        'hello'
        >>> result = gpg.encrypt("hello again", fp1)
        >>> message = str(result)
        >>> result = gpg.decrypt(message, passphrase='bar')
        >>> result.status in ('decryption failed', 'bad passphrase')
        True
        >>> assert not result
        >>> result = gpg.decrypt(message, passphrase='pp1')
        >>> result.status == 'decryption ok'
        True
        >>> str(result)
        'hello again'
        >>> result = gpg.encrypt("signed hello", fp2, sign=fp1, passphrase='pp1')
        >>> result.status == 'encryption ok'
        True
        >>> message = str(result)
        >>> result = gpg.decrypt(message, passphrase='pp2')
        >>> result.status == 'decryption ok'
        True
        >>> assert result.fingerprint == fp1

        )rX   r'   rð  r6   )r   r=   rì  r˜  r!   r   r   r   Úencrypt·  s   *zGPG.encryptc                 K   r–  r   )rX   r'   Údecrypt_filer6   )r   r    r˜  r=   r!   r   r   r   Údecryptæ  s   zGPG.decryptc                 C   sf   dg}|r|   ||¡ |r| d¡ |r| |¡ | jd | ƒ}| j||||dd� t d|j¡ |S )Nz	--decryptrë  rC  Tr¦  zdecrypt result: %r)rœ  rÂ   rr  r`  r•  r1   r8   r=   )r   rŸ  rí  rI   r›  r£  rA   r!   r   r   r   rò  ì  s   

zGPG.decrypt_filec              	   C   s  t j}||vrd t|ƒ¡}td||f ƒ‚|| d }dd l}z[| ¡ \}}g }t|tƒr1|g}|D ]}	| 	d|	|f ¡ q3t
j |¡t
j }
t d|
¡ t
 ||
 | j¡¡ t
 |¡ | jd | ƒ}|  d|g¡}| j|||jd	� W t
 |¡ |S t
 |¡ w )
NrÎ   z-Invalid trust level: "%s" (must be one of %s)rZ   r   z%s:%s:zwriting ownertrust info: %srD  z--import-ownertrustrL  )rY   r”   rÅ   Úsortedrú   r©  rª  r   r   rÂ   rZ  Úlinesepr1   r8   r4   r$   r'   r6   r`  r^  ra  r.   Úremove)r   r«   Ú
trustlevelÚlevelsÚpossr©  r®  rt  rƒ  r™  r   r!   rh  r   r   r   Ú
trust_keysú  s2   ÿ


ÿzGPG.trust_keys)rg   NFFNNN)Fr   )NNrf   )NNTFFNN)NTN)FNT)FTFNT)FNF)rÖ  )NFNTNFN)FNNN)-r   r   r   r  r  r:  r3  r¨   rÖ   rò   r  rÝ   r?  rY   r7  r`  rw   ru  r^  r‡  rŠ  ra  r•  rI  rœ  r—  rJ  r¤  r±  rµ  r¾  r¿  rÄ  rÈ  rÐ  rÓ  rÕ  rÚ  rÜ  rê  rð  rñ  ró  rò  rú  r   r   r   r   rA  ë  st    õ
þ<
!


 
ÿ$


ÿ%
ÿ2
 
+0
þ%/
ÿrA  )Ir¦   Ú__version__Ú
__author__Ú__date__rS   r   rT   Ú	cStringIOr‹  Úlocalerž  rZ  Úrerâ  rz  r   r   r-   rB   r   Únamer   r   Úlogging.NullHandlerr	   ÚHandlerÚunicoder"   Ú
basestringr   r#   Ú	NameErrorrW   Ú	getLoggerr   r1   ÚhandlersÚ
addHandlerr[  r   Úcompiler   Úgetfilesystemencodingr%   r&   r>   rG   rJ   rP   rV   rX   ÚobjectrY   r¨   ÚIrì   rî   rÖ   rÜ   rK   rÝ   rò   r  r  r  r3  r7  r:  r?  r$   rd  rØ  rA  r   r   r   r   Ú<module>   s¢    "ÿ
ÿÿý


""	 Xú	'I7%