HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.104.1.lve.el8.x86_64 #1 SMP Tue Feb 10 20:07:30 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/__pycache__/gnupg.cpython-310.pyc
o

�N�g$��@s�dZdZdZdZzddlmZWneyddlmZYnwddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlmZddlmZddlZddlZdZejd	krkzdd
lmZmZmZWneyjdZYnwzddlmZWney�Gdd�de
j�ZYnwz
ed
ZeZeZWney�dZe Ze ZYnwe
�!e"�Z#e#j$s�e#�%e��ej&j"dkr�dd�Z'n	e�(d�Z)dd�Z'e�*�Z+dd�Z,dd�Z-dd�Z.dd�Z/dd�Z0dd�Z1d d!�Z2Gd"d#�d#e3�Z4Gd$d%�d%e3�Z5e�(d&ej6�Z7d'd(d)d*d+d,d-�Z8Gd.d/�d/e3�Z9d0d1�Z:Gd2d3�d3e;�Z<Gd4d5�d5e<�Z=Gd6d7�d7e=�Z>Gd8d9�d9e3�Z?Gd:d;�d;e4e?�Z@Gd<d=�d=e3�ZAGd>d?�d?eA�ZBGd@dA�dAe3�ZCGdBdC�dCeC�ZDGdDdE�dEe?�ZEe�(dF�FdG�ej6�ZGe�(dHej6�ZHe�(dI�ZIGdJdK�dKe3�ZJdS)Lah 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-2021 Vinay Sajip. All rights reserved.

A unittest harness (test_gnupg.py) has also been added.
z0.4.8zVinay Sajipz$24-Nov-2021 09:13:33$�)�StringION)�Popen)�PIPE�nt)�STARTUPINFO�STARTF_USESHOWWINDOW�SW_HIDEc@seZdZdd�ZdS)�NullHandlercC�dS�N�)�self�recordrr�9/opt/saltstack/salt/lib/python3.10/site-packages/gnupg.py�handleB�zNullHandler.handleN)�__name__�
__module__�__qualname__rrrrrr	Asr	FT�ntpathcCsd|S)Nz"%s"r��srrr�shell_quoteVsrz[^\w%+,./:=@-]cCsLt|t�s
tdt|���|sd}|St�|�s|}|Sd|�dd�}|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
        zExpected string type, got %sz''z'%s'�'z'\'')�
isinstance�string_types�	TypeError�type�UNSAFE�search�replace)r�resultrrrr_s


��cCstst|t�r|�t�}|Sr)�_py3kr�	text_type�encode�
fsencodingrrrr�no_quote�s
r&cCs�d}ttjd�r
tjj}nd}	z|�d�}Wnty'tjddd�Yn-w|s+n)|t|�7}z|�	|�WntyI|�	|�
|��Yn
t�d	�Ynqz|��Wnt
yjtjd
dd�Ynwt�d|�dS)Nr�encoding�asciiT�z Exception occurred while reading�)�exc_infozError sending dataz)Exception occurred while closing: ignoredzclosed 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>cCs8tjt||fd�}|�d�t�d|||�|��|S)N��target�argsTzdata copier: %r, %r, %r)�	threading�Threadr>�	setDaemonr1r8�start)r9r:�wrrrr�_threaded_copy_data�s

rGcCs*d|}|�|�}|�|�t�d�dS)Nz%s
zWrote passphrase)r$r4r1r8)�stream�
passphraser'rrr�_write_passphrase�s

rJcCst|ttttf�Sr)r�list�tuple�set�	frozenset)�instancerrr�_is_sequence��rPcCs8z
ddlm}||�}W|Styt|�}Y|Sw)Nr)�BytesIO)�iorR�ImportErrorr)rrR�rvrrr�_make_memory_stream�s
�
�rVcCs>trt|t�r|�|�}t|�St|�tur|�|�}t|�Sr)r"r�strr$rrV)rr'rrr�_make_binary_stream�s

�
rXc@sjeZdZdZdZdZdZdZdZeeeeed�Z	dd	d
dd�Z
d
diZdZdd�Z
dd�ZeZdd�ZdS)�Verifyz#Handle status messages for --verifyrr*���)�TRUST_UNDEFINED�TRUST_NEVER�TRUST_MARGINAL�TRUST_FULLY�TRUST_ULTIMATEzpermission deniedzfile existszfile not foundznot a directory)r*�#�Q�a�zincorrect passphraseNcCsj||_d|_d|_|_|_d|_|_d|_d|_d|_d|_	d|_
d|_d|_d|_
d|_i|_dS�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�sig_info�r
rgrrr�__init__�s
zVerify.__init__cC�|jSr)rh�r
rrr�__nonzero__��zVerify.__nonzero__cs��fdd�}|�jvr|�_�j|�_|�j�jd�dS|dvr+t�d||�dS|dkrKd�_d�_|�dd	�\�_�_	|�j�j	�jd
�dS|dkrd�_|��}|dd�\�_}}}�_
t|�d
krn|d�_d�_|�j�j
�j�jd�dS|dkr�d�_d�_|�dd	�\�_�_	|�j�j	�jd
�dS|dkr�d�_d�_|�dd	�\�_�_	|�j�j	�jd
�dS|dkr�|��dd�\}}	}
}||	|
|f\�_�_
�_�_|��d�_d�_|||	|
|�j�jd�dS|dk�r|��\}}	}
|	|
d��j|<||	|
�_�_
�_
dS|dk�r&d�_|�_d�_dS|dk�r6d�_|�_d �_dS|d!k�rFd�_|�_d"�_dS|d#v�rod�_|��d$�_|d%k�r^d&�_nd'�_�j�_|�j�jd(�dS|d)v�r�d�_|�_|d*k�r�d+�_dSd,|}|�d-d	�\}}|���r�t|�d.@}�jj�r�|�jjv�r�d/|�jj|f}n!t|d0@�}|d1@}|�rÈj}n�j}||v�r�d/|||f}�j�s�|�_dSdS|d2v�r�dSt�d3||�dS)4Ncs&�j}|r�j|}|�|�dSdSr)rlrv�update)�kwargs�sig_id�inforzrr�update_sig_infos

�z-Verify.handle_status.<locals>.update_sig_info)rurt��WARNING�ERROR�potential problem: %s: %sZBADSIGFz
signature badr*)�keyidrnrpZERRSIG���zsignature error)r�rkrirpZEXPSIGzsignature expiredZGOODSIGTzsignature goodZVALIDSIGr\���zsignature valid)rirjrkZexpiryrqrpZSIG_ID)rjrk�DECRYPTION_FAILED�decryption failedZ	NO_PUBKEYz
no public keyZ	NO_SECKEY�
no secret key)�	EXPKEYSIGZ	REVKEYSIGrr�zsigning key has expiredzsigning key was revoked)rpr�)�
UNEXPECTED�FAILUREr�zunexpected dataz
error - %s� i����%s: %si�i�)ZDECRYPTION_INFOZ	PLAINTEXTZPLAINTEXT_LENGTH�
BEGIN_SIGNING�message ignored: %s, %s)�TRUST_LEVELSrtrur1r2rhrp�splitrmrnrkr3rirjrsrrrqrvrlro�rsplit�isdigit�intrg�	error_map�bool�GPG_SYSTEM_ERROR_CODES�GPG_ERROR_CODESr8)r
�key�valuer��parts�algo�	hash_algo�clsrirjZsig_tsZ	expire_tsrrk�messageZ	operation�codeZsystem_error�mappingrrzr�
handle_statuss�

�

�
�


�

�

���
�
���













�
zVerify.handle_status)rrr�__doc__r]r^r_r`rar�r�r��
returncoderxr{�__bool__r�rrrrrY�s2���rYc@sbeZdZdZd��ZdZdd�Zdd�ZeZ	dd	d
ddd
d�Z
dddddd�Zdd�Zdd�Z
dS)�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_importedNcCs.||_g|_g|_|jD]}t||d�qdS)Nr)rg�results�fingerprints�counts�setattr)r
rgr!rrrrx�s
�zImportResult.__init__cCs|jrdS|js
dSdS)NFT)�not_importedr�rzrrrr{�s

zImportResult.__nonzero__zNot actually changedzEntirely new keyzNew user IDszNew signatureszNew subkeyszContains private key)�0�1�2�4�8Z16zNo specific reason givenzInvalid CertificatezIssuer Certificate missingzCertificate Chain too longzError storing certificate)r�r�r��3r�cCs�|dvr
t�d||�dS|dvrdS|dkr#|j�dddd��dS|dkre|��\}}g}t|j���D]\}}t|�t|�Bt|�krK|�|�q6d	�	|�d	}|j�|||d
��|j
�|�dS|dkr�z|��\}}Wn|}d}Y|j�|||j|d��dS|d
kr�|��}	t|j
�D]\}
}t||t|	|
��q�dS|dkr�|j�dddd��dS|dkr�|j�dddd��dS|dkr�|j�dddd��dSt�d||�dS)Nr�r�)ZIMPORTED�KEY_CONSIDERED�NODATAr�zNo valid data found)riZproblem�textZ	IMPORT_OK�
)ri�okr�ZIMPORT_PROBLEMz	<unknown>Z
IMPORT_RES�
KEYEXPIREDzKey expired�
SIGEXPIREDzSignature expiredr�z
Other failurer�)r1r2r��appendr�rK�	ok_reason�itemsr��joinr��problem_reason�	enumerater�r�r8)r
r�r��reasonriZreasonsr�r�Z
reasontextZ
import_res�i�countrrrr��s^�
��
�����zImportResult.handle_statuscCs4g}|�d|j�|jr|�d|j�d�|�S)Nz%d importedz%d not imported�, )r�Zimportedr�r�)r
r!rrr�summary�s

zImportResult.summary)rrrr�r�r�r�rxr{r�r�r�r�r�rrrrr�|s0��
�+r�z\\x([0-9a-f][0-9a-f])r��
����)z\nz\rz\fz\vz\bz\0c@s eZdZdZdd�Zdd�ZdS)�
SendResultNcCs
||_dSr)rgrwrrrrx��
zSendResult.__init__cCst�d||�dS)NzSendResult: %s: %s)r1r8�r
r�r�rrrr��rQzSendResult.handle_status)rrrr�rxr�rrrrr��sr�cCs8t|�D]\}}|t|�kr||||<qd||<qdS)NZunavailable)r�r3)r@Z
fieldnamesrAr��varrrr�_set_fields�s

�r�c@sHeZdZdZdZd��ZdZdd�Zdd�Z	d	d
�Z
dd�Zd
d�ZdS)�
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 expiresNcCs||_d|_g|_g|_dSr)rg�curkeyr��uidsrwrrrrx�s
zSearchKeys.__init__cCs&i}t||j|�g|d<g|d<|S)Nr��sigs)r��FIELDS)r
rAr!rrr�
get_fieldss
zSearchKeys.get_fieldscCs|�|�|_}|�|�dSr)r�r�r��r
rAr�rrr�pub
szSearchKeys.pubcCsX||j}t�dd�|�}t��D]
\}}|�||�}q|jd�|�|j�|�dS)NcSstt|�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rr�s
zSearchKeys.uidcCr
rrr�rrrr�rzSearchKeys.handle_status)
rrrr�r�r�r�r�rxr�r�r�r�rrrrr��sr�csdeZdZdZdZd��Z�fdd�Zdd�ZeZ	Z
dd	�Zd
d�Zdd
�Z
dd�Zdd�Z�ZS)�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 origincs tt|��|�d|_i|_dSrf)�superr�rx�	in_subkey�key_maprw��	__class__rrrx-s
zListKeys.__init__cCsL|�|�|_}|dr|d�|d�|d=g|d<|�|�d|_dS)Nr�r��subkeysF)r�r�r�r�r�rrrr�2s

zListKeys.keycCsv|d}||jvr|jjrtd|��|js)||jd<|j�|�|j|j|<dS|jdd�|�|j|j|<dS)Nr�z$Unexpected fingerprint collision: %srir�r�)r�rg�check_fingerprint_collisions�
ValueErrorr�r�r�r�)r
rA�fprrr�fpr=s
zListKeys.fprcCs.|�di�}i}t||j|�|||d<dS)NZsubkey_infor\)�
setdefaultr�r�)r
r�rAZinfo_mapr�rrr�_collect_subkey_infoIszListKeys._collect_subkey_infocC�8|d|dg}|jd�|�|�|j|�d|_dS)Nr\rer�T�r�r�r�r��r
rAZsubkeyrrrr�Os
zListKeys.subcCs4|ddg}|jd�|�|�|j|�d|_dS)Nr\r�Tr�r�rrr�ssbXs
zListKeys.ssbcCs&|jd�|d|d|df�dS)Nr�r\r��
)r�r�)r
rArrr�sig^s&zListKeys.sig)rrrr�r�r�r�rxr�r�Zsecr�r�r�r�r��
__classcell__rrr�rr�s		r�c@seZdZdZdd�ZdS)�ScanKeysz/ Handle status messages for --with-fingerprint.cCr�)Nr\r�r�Tr�r�rrrr�es
zScanKeys.subN)rrrr�r�rrrrr�bsr�c@s,eZdZdd�ZereZdSeZdd�ZdS)�TextHandlercCs|j�|jj|jj�Sr)r=�decodergr'�
decode_errorsrzrrr�_as_textnszTextHandler._as_textcCryr)r=rzrrr�__str__vr|zTextHandler.__str__N)rrrrr"rZ__unicode__rrrrr�msr�c@s,eZdZdZdd�Zdd�ZeZdd�ZdS)	�Cryptz2Handle status messages for --encrypt and --decryptcCs(t�||�d|_d|_d|_d|_dS)N�F)rYrxr=r�rprmrwrrrrx|s

zCrypt.__init__cC�|jrdSdS�NTF)r�rzrrrr{��
zCrypt.__nonzero__cCsp|dvr
t�d||�dS|dkr|jdvrd|_dSdS|dvr,|�dd���|_dS|d	kr<|jd
kr:d|_dSdS|dkrEd
|_dS|dkrU|jd
krSd|_dSdS|dkr^d|_dS|dkrjd|_d|_dS|dkrvd|_d|_dS|dkrd|_dS|dkr�d|_dS|dkr�d|_dS|dkr�d|_dS|dkr�|�dd �d!|_dS|d"vr�dSt�	|||�dS)#Nr�r�r�)r�zno data was provided)�NEED_PASSPHRASE�BAD_PASSPHRASE�GOOD_PASSPHRASEZMISSING_PASSPHRASE�KEY_NOT_CREATEDZNEED_PASSPHRASE_PIN�_r�r�r�r�ZNEED_PASSPHRASE_SYMzneed symmetric passphraseZBEGIN_DECRYPTIONzdecryption incompleteZBEGIN_ENCRYPTIONzencryption incompleteZDECRYPTION_OKAYz
decryption okTZEND_ENCRYPTIONz
encryption okZINV_RECPzinvalid recipientr��key expired�SIG_CREATEDzsig createdr�zsig expiredZENC_TOr*r)	�USERID_HINTZGOODMDCZEND_DECRYPTIONZCARDCTRLZBADMDCZ
SC_OP_FAILUREZ
SC_OP_SUCCESSZPINENTRY_LAUNCHEDr�)
r1r2rpr �lowerr�r�rmrYr�r�rrrr��sN

�

�


�






zCrypt.handle_statusN)rrrr�rxr{r�r�rrrrrzsrc@s8eZdZdZdZdd�Zdd�ZeZdd�Zd	d
�Z	dS)�GenKeyz$Handle status messages for --gen-keyNcCs||_d|_d|_dSr)rgrrirwrrrrx�s
zGenKey.__init__cCrr�rirzrrrr{�rzGenKey.__nonzero__cCs
|jpdS)Nrrrzrrrr�r�zGenKey.__str__cCsT|dvr
t�d||�dS|dkr|��\|_|_dS|dvr!dSt�d||�dS)Nr�r�ZKEY_CREATED)ZPROGRESSr
rr�)r1r2r�rrir8r�rrrr��szGenKey.handle_status)
rrrr�r�rxr{r�rr�rrrrr�srcs eZdZdZ�fdd�Z�ZS)�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.
    cs"|dvrdStt|��||�dS)N)ZEXPORTEDZ
EXPORT_RES)r�rr�r�r�rrr��szExportResult.handle_status)rrrr�r�r�rrr�rr�src@sDeZdZdZdZdd�Zdd�Zddd	d
�Zdd�Zd
d�Z	e	Z
dS)�DeleteResultz?Handle status messages for --delete-key and --delete-secret-keyNcCs||_d|_dS�Nr�)rgrprwrrrrx�s
zDeleteResult.__init__cCryr�rprzrrrr�r|zDeleteResult.__str__zNo such keyzMust delete secret key firstzAmbiguous specification)r�r�r�cCs2|dkr|j�|d|�|_dSt�d||�dS)NZDELETE_PROBLEMzUnknown error: %rr�)r��getrpr1r8r�rrrr��s

�zDeleteResult.handle_statuscCs
|jdkSrrrzrrrr{�r�zDeleteResult.__nonzero__)rrrr�r�rxrr�r�r{r�rrrrr�s�rc@seZdZdS)�TrustResultN)rrrrrrrr�src@s0eZdZdZdZdd�Zdd�ZeZdd�ZdS)	�Signz!Handle status messages for --signNcCs.||_d|_d|_d|_d|_d|_d|_dSr)rgrr�rirprmrnrwrrrrxs
z
Sign.__init__cCs
|jduSrrrzrrrr{r�zSign.__nonzero__cCs�|dvr
t�d||�dS|dvrd|_dS|dkrd|_dS|dkr6|��\|_}|_}|_|_d|_dS|d	krF|�d
d�\|_|_	dS|dkrOd
|_dS|dvrUdSt�
d||�dS)N)r�r�r�r�)r�r�r
Z
KEYREVOKEDzkey revokedrzsignature createdrr�r*r	zbad passphrase)rr
r�r�)r1r2rpr�rr�rkrirmrnr8)r
r�r�r�r�rrrr�s$

�

zSign.handle_status)	rrrr�r�rxr{r�r�rrrrrs	rz(gpg \(GnuPG(?:/MacGPG2)?\) (\d+(\.\d+)*)r(z
[0-9a-f]+$zgpg: public key is (\w+)c
@sxeZdZdZdZeeeee	e
eee
eeed�Z				dJdd�Zdd	�ZdKd
d�Zdd
�ZdLdd�ZdMdd�Zdd�ZdNdd�Zdd�Zdd�Zdd�Z		dOdd�Zdd �ZdPd!d"�ZdLd#d$�Z dMd%d&�Z!d'd(�Z"d)d*�Z#		dQd+d,�Z$		dRd-d.�Z%d/d0�Z&dSd1d2�Z'd3d4�Z(dTd6d7�Z)d8d9�Z*d:d;�Z+			dUd<d=�Z,d>d?�Z-d@dA�Z.		dVdBdC�Z/dDdE�Z0dLdFdG�Z1dHdI�Z2dS)W�GPGN�strict)�crypt�delete�generate�import�sendrK�scanr�sign�trust�verify�exportrgFc
Csr||_||_|rtj�|�std|��|rt|t�r|g}||_|r+t|t�r+|g}||_	||_
||_t|t�r<|g}||_
d|_d|_|rUtj�|j�sUt�|jd�z|�dg�}Wntyrd|j}	t�|	�t|	��w|jd|�}
|j||
|jd�|jd	kr�td
|j|
jf��t�|
j�}|s�d|_nd�d�}td
d�|� �d	�!|�D��|_d|_"dS)a9Initialize 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.
        z.gnupghome should be a directory (it isn't): %sNzlatin-1i�z	--versionz1Unable to run gpg (%s) - it may not be available.r$�r.rzError invoking gpg: %s: %s�.r(cS�g|]}t|��qSr)r���.0rrrr�
<listcomp>�r�z GPG.__init__.<locals>.<listcomp>F)#�	gpgbinary�	gnupghome�os�path�isdirr�rr�keyring�secret_keyring�verbose�	use_agentrW�options�on_datar'�makedirs�_open_subprocess�OSErrorr1r5�
result_map�_collect_outputr.r��stderr�
VERSION_RE�matchr=�versionr$rL�groupsr�r�)
r
r,r-r3r4r1r5r2�p�msgr!r��dotrrrrxCsP




�
�
"
zGPG.__init__cCs|jddddg}dtjvr|�ddg�|r(t|d�r(|jd	kr(d
dg|dd�<|�gd
��|jr<|�dt|j�g�|jrS|�	d�|jD]}|�dt|�g�qG|j
re|j
D]}|�dt|�g�qY|rn|�ddg�|jrv|�	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-verboseZ	DEBUG_IPCz--debugZipcr?�rZr*z--pinentry-modeZloopbackr*)�--fixed-list-modez--batch�
--with-colonsz	--homedirz--no-default-keyringz	--keyringz--secret-keyringz--passphrase-fdr�z--use-agent)
r,r.�environ�extendr,r?r-r&r1r�r2r4r5)r
rArI�cmd�fnrrr�	make_args�s0






z
GPG.make_argscCsrddlm}|�||�}|jrt||��tsd}n	t�}t|_t|_	t
|dttt|d�}t�
d|j||��|S)Nr)�list2cmdlineF)�shellr.�stdoutr<�startupinfor�)�
subprocessrLrKr3�printrrZdwFlagsrZwShowWindowrrr1r8�pid)r
rArIZdebug_printrI�sir!rrrr8�s�zGPG._open_subprocesscCs�g}	|��}t|�dkrnB|�|�|��}|jrt|�t�d|�|dd�dkrO|dd�}|�dd�}|d}t|�dkrG|d}nd}|�	||�qd�
|�|_dS)NTrz%sr�z	[GNUPG:] r*r)�readliner3r��rstripr3rQr1r8r�r�r�r<)r
rHr!�lines�line�L�keywordr�rrr�_read_response�s(

�zGPG._read_responsecCs�g}	|�d�}t|�dkr|r||�nt�d|dd��d}|r*||�dk}|r1|�|�qtr?t|���|�|_dSd�|�|_dS)NTr)rz	chunk: %r�Fr)	r/r3r1r8r�r"rr�r=)r
rHr!r6�chunksr=r�rrr�
_read_data�s"

�zGPG._read_datac
Cst�|j�|j�}tj|j||fd�}|�d�t�	d|�|�
�|j}tj|j|||j
fd�}|�d�t�	d|�|�
�|��|��|durP|��|��|j|_}	|	dkrdt�d|	�|durxz|��Wn	tywYnw|��|��|	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?Tzstderr reader: %rzstdout reader: %rNrz&gpg returned a non-zero error code: %d)�codecs�	getreaderr'r<rBrCrZrDr1r8rErNr]r6r��waitr�r2r6r7)
r
�processr!�writerr.r<ZrrrNZdr�rcrrrr;�s:
�
�zGPG._collect_outputcCs
t|d�S)z4
        Simplistic check for a file object
        r/)r,)r
�fileobjrrr�
is_valid_files
zGPG.is_valid_filec	Cst|�|�std|��|�||du�}|st�|j�|j�}n|j}|r+t|||j�t||�}|�	||||�|S)z;Handle a call to GPG - pass input data, collect output datazNot a valid file: %sN)
rerr8r^�	getwriterr'r.rJrGr;)	r
rArdr!rI�binaryrAr.rbrrr�
_handle_io"s

zGPG._handle_iocK�*t||j�}|j|fi|��}|��|S)zsign message)rXr'�	sign_filer6)r
r�r~�fr!rrrr"6szGPG.signcCs.tj�|�r|�dg�|�dt|�g�dS)z@If writing to a file which exists, avoid a confirmation message.�--yesz--outputN)r.r/�existsrHr&)r
rA�outputrrr�set_output_without_confirmation=sz#GPG.set_output_without_confirmationcCsd|vod|vod|vS)z�
        Confirm that the passphrase doesn't contain newline-type characters -
        it is passed in a pipe to gpg, and so not checking could lead to
        spoofing attacks by passing arbitrary text after passphrase and newline.
        r�r�r�r)r
rIrrr�is_valid_passphraseDs�zGPG.is_valid_passphraseTc	Cs|r|�|�std��t�d|�|rdg}	ndg}	|r"|	�d�n|r)|	�d�|r4|	�dt|�g�|r<|�|	|�|rC|	�|�|jd|�}
|�	|	|d	u�}z|j
}|r_t|||j�t
||�}
Wntyut�d
�d	}
Ynw|�||
|
|�|
S)z	sign file�Invalid passphrasez
sign_file: %sz-sz-saz
--detach-signz--clearsign�
--default-keyr"Nzerror writing message)rpr�r1r8r�rHr&ror:r8r.rJr'rGr7�loggingr5r;)r
�filer�rIZ	clearsign�detachrgrn�
extra_argsrAr!rAr.rbrrrrjMs:


�z
GPG.sign_filecKri)awVerify the signature on the contents of the string 'data'

        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> if not os.path.isdir('keys'): os.mkdir('keys')
        >>> 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

        )rXr'�verify_filer6)r
r=r~rkr!rrrr$ssz
GPG.verifyc	Cs�t�d||�|jd|�}dg}|r|�|�|dur'|j|||dd�|St�d�ddl}|jd	d
�\}}	|��}
|rB|��t�d|
�t	�
||
�t	�|�|�t|	��|�t|��z|�
|�}|j|||jd�Wt	�|	�|St	�|	�w)
zCVerify the signature on the contents of the file-like object 'file'zverify_file: %r, %rr$�--verifyNT�rgzHandling detached verificationrZpygpg)�prefixzWrote to temp file: %rr&)r1r8r:rHrh�tempfile�mkstempr/r6r.r4r�r&r8r;r.�unlink)r
rtZ
data_filenameZ
close_filervr!rAr{�fdrJrrArrrrw�s2

�


�zGPG.verify_filecCsht�d||dd��|jd|�}dg}|r|�|�|�t|�dg�t|�}|j|||dd�|S)	z;Verify the signature in sig_filename against data in memoryzverify_data: %r, %r ...Nr�r$rx�-Try)r1r8r:rHr&rVrh)r
Zsig_filenamer=rvr!rArHrrr�verify_data�s
zGPG.verify_datacCsp|jd|�}t�d|dd��t||j�}dg}|r!|�|�|j||||dd�t�d|j�|��|S)	z7
        Import the key_data into our keyring.
        rzimport_keys: %rNr[�--importT�rIrgzimport_keys result: %r)	r:r1r8rXr'rHrh�__dict__r6)r
Zkey_datarvrIr!r=rArrr�import_keys�s
zGPG.import_keyscG�t|jd|�}t�d|�td|j�}dt|�dg}|�dd�|D��|j|||dd	�t�d
|j�|�	�|S)a�Import a key from a keyserver

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

        rz
recv_keys: %rr�--keyserverz--recv-keyscSr(r�r&�r*r�rrrr+�r�z!GPG.recv_keys.<locals>.<listcomp>Tryzrecv_keys result: %r�
r:r1r8rXr'r&rHrhr�r6�r
�	keyserver�keyidsr!r=rArrr�	recv_keys�s
z
GPG.recv_keyscGr�)z�Send a key to a keyserver.

        Note: it's not practical to test this function without sending
        arbitrary data to live keyservers.
        r z
send_keys: %rrr�z--send-keyscSr(rr�r�rrrr+�r�z!GPG.send_keys.<locals>.<listcomp>Tryzsend_keys result: %rr�r�rrr�	send_keys�sz
GPG.send_keysc
Cs|r|�|�std��d}|r |jdkr|dur|rtd��d}t|�r,dd�|D�}nt|�g}d	|g}|rC|jdkrC|�d
d�|�|�|jd|�}|rV|jdkrf|�|�}|j	|||j
d
�|Std|j�}	z|j
||	||dd�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).
        rqr�rDNzHFor GnuPG >= 2.1, deleting secret keys needs a passphrase to be providedz
secret-keycSr(rr�r)rrrr+r�z#GPG.delete_keys.<locals>.<listcomp>z--delete-%srrlrr&rTr�)rpr�r?rPr&�insertrHr:r8r;r.rXr'rhr6)
r
r��secretrI�expect_passphrase�whichrAr!rArkrrr�delete_keys�s:
�



	��
�zGPG.delete_keyscCs<|r|�|�std��d}|r d}|jdkr |dur |r td��t|�r,dd�|D�}nt|�g}d	|g}|r=|�d
�|rF|�ddg�|�|�|jd
|�}	|rY|jdkrh|�|�}
|j	|
|	|
j
d�ntd|j�}z|j
|||	|dd�W|��n|��wt�d|	jdd��|	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).
        rqrz-secret-keyrDNzIFor GnuPG >= 2.1, exporting secret keys needs a passphrase to be providedcSr(rr�r�rrrr+*r�z#GPG.export_keys.<locals>.<listcomp>z
--export%s�--armorz--export-optionszexport-minimalr%r&Tr�zexport_keys result[:100]: %r�d)rpr�r?rPr&r�rHr:r8r;r.rXr'rhr6r1r8r=r�r)r
r�r��armorZminimalrIr�r�rAr!rArkrrr�export_keyssB
�




�zGPG.export_keysc	Cs�|j||�}|j|||jd�|j�|j|j���}d��}|D]/}|j	r*t
|�t�d|�
��|s7|S|���d�}|sAq!|d}||vrPt||�|�q!|S)Nr&zpub uid sec fpr sub ssb sig�line: %r�:r)r:r;r.r=r�r'r�
splitlinesr�r3rQr1r8rU�strip�getattr)	r
rA�kindr!rV�valid_keywordsrWrXrYrrr�_get_list_outputIs.
����zGPG._get_list_outputcCsX|rd}nd}|rd}d|ddg}|r!t|t�r|g}|�|�|�|�}|�|d�S)a� list the keys currently in the keyring

        >>> import shutil
        >>> shutil.rmtree("keys", ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> if not os.path.isdir('keys'): os.mkdir('keys')
        >>> 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��keyszsecret-keysz	--list-%s�
--fingerprintrK)rrrHr8r�)r
r�r�r�r�rArArrr�	list_keys^s�


z
GPG.list_keyscCsJ|jdkr
gd�}n	t�d�gd�}|�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
        rD)z	--dry-runz--import-optionszimport-showr�zTTrying to list packets, but if the file is not a keyring, might accidentally decrypt)z--with-fingerprintrFrEr!)r?r1r2r�r&r8r�)r
�filenamerArArrr�	scan_keys�s



z
GPG.scan_keys�pgp.mit.educCs�|��}t�|�r
d|}ddt|�dt|�g}|�|�}|jd|�}|j|||jd�|j�	|j
|j���}ddg}|D]-}|j
rGt|�t�d	|���|sRq>|���d
�}	|	s\q>|	d}
|
|vrkt||
�|	�q>|S)a� search keyserver by query (using --search-keys option)

        >>> import shutil
        >>> shutil.rmtree('keys', ignore_errors=True)
        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> if not os.path.isdir('keys'): os.mkdir('keys')
        >>> gpg = GPG(gpgbinary=GPGBINARY, gnupghome='keys')
        >>> os.chmod('keys', 0x1C0)
        >>> result = gpg.search_keys('<vinay_sajip@hotmail.com>')
        >>> if 'NO_EXTERNAL_TESTS' not in os.environ: 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-keysrr&r�r�r�r�r)r��
HEX_DIGITS_REr>r&r8r:r;r.r=r�r'rr�r3rQr1r8rUr�r�)r
�queryr�rArAr!rVr�rWrXrYrrr�search_keys�s<

�

���zGPG.search_keyscCs>dg}|jd|�}t||j�}|j|||dd�|��|S)a�Generate a key; you might use gen_key_input() to create the
        control input.

        >>> GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
        >>> if not os.path.isdir('keys'): os.mkdir('keys')
        >>> 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-keyrTry)r:rXr'rhr6)r
�inputrAr!rkrrr�gen_key�szGPG.gen_keyc	Ksi}|�dd�}t|���D]\}}|�dd���}t|���r$|||<q|�dd�d|vr5|�dd	�|�d
d�tj	�
d�pHtj	�
d
�pHd}t��}|�dd|�dd�|f�d|�d�}t|���D]\}}|d||f7}qh|r{|d7}|d7}|S)z>
        Generate --gen-key input per gpg doc/DETAILS
        �
no_protectionFrrzKey-TypeZRSAZ	key_curvez
Key-Lengthiz	Name-RealzAutogenerated KeyZLOGNAME�USERNAME�unspecifiedz
Name-Emailz%s@%sr�z
Key-Type: %s
z%s: %s
z%no-protection
z%commit
)
�poprKr�r �titlerWr�r�r.rGr�socket�gethostname)	r
r~Zparmsr�r��valZlogname�hostname�outrrr�
gen_key_input�s2���zGPG.gen_key_inputc

Cs|r|�|�std��dg}
|r!dg}
|dur |
�dt|�g�n|s'td��t|�s.|f}|D]}|
�dt|�g�q0|rC|
�d�|rK|�|
|�|durU|
�d	�n|ra|
�d	d
t|�g�|rh|
�d�|	ro|
�|	�|jd|�}|j|
|||dd
�t	�
d|jdd��|S)z9Encrypt the message read from the file-like object 'file'rqz	--encryptz--symmetricTz
--cipher-algoz2No recipients specified with asymmetric encryptionz--recipientr�z--signrr�--always-trustrr�zencrypt result[:100]: %rNr�)rpr�rHr&rPr�ror:rhr1r8r=)
r
rt�
recipientsr"�always_trustrIr�rnZ	symmetricrvrAZ	recipientr!rrr�encrypt_files<�


zGPG.encrypt_filecKs,t||j�}|j||fi|��}|��|S)a�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')
        >>> if not os.path.isdir('keys'): os.mkdir('keys')
        >>> 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

        )rXr'r�r6)r
r=r�r~r!rrr�encrypt3s+zGPG.encryptcKrir)rXr'�decrypt_filer6�r
r�r~r=r!rrr�decryptc�zGPG.decryptcCs�|r|�|�std��dg}|r|�||�|r|�d�|r$|�|�|jd|�}|j||||dd�t�d|j	dd��|S)	Nrq�	--decryptr�rTryzdecrypt result[:100]: %rr�)
rpr�ror�rHr:rhr1r8r=)r
rtr�rIrnrvrAr!rrrr�is

zGPG.decrypt_filecKrir)rXr'�get_recipients_filer6r�rrr�get_recipientsyr�zGPG.get_recipientscCs`gd�}|r|�|�|jd|�}|j|||dd�g}t�|j�D]
}|�|�d��q#|S)N)r�z--list-onlyz-vrTryr*)rHr:rh�
PUBLIC_KEY_RE�finditerr<r�r�)r
rtrvrAr!Zidsr�rrrr�s
zGPG.get_recipients_filec
	Cstj}||vrd�t|��}td||f��||d}ddl}zg|��\}}g}t|t�r1|g}|D]}	|�	d|	|f�q3t
j�|�t
j}
t�
d|
�t
�||
�|j��t
�|�|jd|�}|�d|g�}|j|||jd	�|jdkr�td
|j��Wt
�|�|St
�|�w)Nr�z-Invalid trust level: "%s" (must be one of %s)rZrz%s:%s:zwriting ownertrust info: %sr#z--import-ownertrustr&z&gpg returned an error - return code %d)rYr�r��sortedr�r{r|rrr�r.�linesepr1r8r4r$r'r6r:r8r;r.r��remove)
r
r�Z
trustlevelZlevelsZpossr{r~rJrVrkrr!rArrr�
trust_keys�s<�


��
�zGPG.trust_keys)rgNFFNNN)Fr)NNrf)NNTFFNN)NTN)FNT)FTFNT)FNF)r�)NFNTNFN)FNNN)3rrrr�rrrrr�r�r�r�r�rrrYrr:rxrKr8rZr]r;rerhr"rorprjr$rwr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrr-s��
�C
!

%
	
�&



�)
�3
"
,4
�'0
�
r)Kr��__version__�
__author__�__date__rSrrTZ	cStringIOr^�localersr.�rer�rPrrr-rBr�namerrZlogging.NullHandlerr	�HandlerZunicoder"Z
basestringrr#�	NameErrorrW�	getLoggerrr1�handlers�
addHandlerr/r�compiler�getfilesystemencodingr%r&r>rGrJrPrVrX�objectrYr��Ir�r�r�r�rKr�r�r�r�rrrrrrr$r=r�r�rrrrr�<module>s�"�
���


""	2Z�	
(I
;(