changeset 53:daefe8ad6705

now symlinked
author Charlie Root
date Wed, 08 Oct 2025 09:04:47 -0400
parents cee7317dd26a
children abd18922cc1d
files vendor/pear/crypt_gpg/Crypt/GPG.php vendor/pear/crypt_gpg/Crypt/GPG/Engine.php vendor/pear/crypt_gpg/Crypt/GPG/Exceptions.php vendor/pear/crypt_gpg/Crypt/GPG/Key.php vendor/pear/crypt_gpg/Crypt/GPG/KeyGenerator.php vendor/pear/crypt_gpg/Crypt/GPG/PinEntry.php vendor/pear/crypt_gpg/Crypt/GPG/ProcessControl.php vendor/pear/crypt_gpg/Crypt/GPG/ProcessHandler.php vendor/pear/crypt_gpg/Crypt/GPG/Signature.php vendor/pear/crypt_gpg/Crypt/GPG/SignatureCreationInfo.php vendor/pear/crypt_gpg/Crypt/GPG/SubKey.php vendor/pear/crypt_gpg/Crypt/GPG/UserId.php vendor/pear/crypt_gpg/Crypt/GPGAbstract.php
diffstat 13 files changed, 0 insertions(+), 9819 deletions(-) [+]
line wrap: on
line diff
--- a/vendor/pear/crypt_gpg/Crypt/GPG.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2065 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This package provides an object oriented interface to GNU Privacy
- * Guard (GPG). It requires the GPG executable to be on the system.
- *
- * Though GPG can support symmetric-key cryptography, this package is intended
- * only to facilitate public-key cryptography.
- *
- * This file contains the main GPG class. The class in this file lets you
- * encrypt, decrypt, sign and verify data; import and delete keys; and perform
- * other useful GPG tasks.
- *
- * Example usage:
- * <code>
- * <?php
- * // encrypt some data
- * $gpg = new Crypt_GPG();
- * $gpg->addEncryptKey($mySecretKeyId);
- * $encryptedData = $gpg->encrypt($data);
- * ?>
- * </code>
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Base class for GPG methods
- */
-require_once 'Crypt/GPGAbstract.php';
-
-/**
- * GPG exception classes.
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-// {{{ class Crypt_GPG
-
-/**
- * A class to use GPG from PHP
- *
- * This class provides an object oriented interface to GNU Privacy Guard (GPG).
- *
- * Though GPG can support symmetric-key cryptography, this class is intended
- * only to facilitate public-key cryptography.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG extends Crypt_GPGAbstract
-{
-    // {{{ class constants for data signing modes
-
-    /**
-     * Signing mode for normal signing of data. The signed message will not
-     * be readable without special software.
-     *
-     * This is the default signing mode.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_NORMAL = 1;
-
-    /**
-     * Signing mode for clearsigning data. Clearsigned signatures are ASCII
-     * armored data and are readable without special software. If the signed
-     * message is unencrypted, the message will still be readable. The message
-     * text will be in the original encoding.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_CLEAR = 2;
-
-    /**
-     * Signing mode for creating a detached signature. When using detached
-     * signatures, only the signature data is returned. The original message
-     * text may be distributed separately from the signature data. This is
-     * useful for miltipart/signed email messages as per
-     * {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_DETACHED = 3;
-
-    // }}}
-    // {{{ class constants for fingerprint formats
-
-    /**
-     * No formatting is performed.
-     *
-     * Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_NONE = 1;
-
-    /**
-     * Fingerprint is formatted in the format used by the GnuPG gpg command's
-     * default output.
-     *
-     * Example: C3BC 615A D9C7 66E5 A85C  1F27 16D2 7458 B1BB A1C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_CANONICAL = 2;
-
-    /**
-     * Fingerprint is formatted in the format used when displaying X.509
-     * certificates
-     *
-     * Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_X509 = 3;
-
-    // }}}
-    // {{{ class constants for boolean options
-
-    /**
-     * Use to specify ASCII armored mode for returned data
-     */
-    const ARMOR_ASCII = true;
-
-    /**
-     * Use to specify binary mode for returned data
-     */
-    const ARMOR_BINARY = false;
-
-    /**
-     * Use to specify that line breaks in signed text should be normalized
-     */
-    const TEXT_NORMALIZED = true;
-
-    /**
-     * Use to specify that line breaks in signed text should not be normalized
-     */
-    const TEXT_RAW = false;
-
-    // }}}
-    // {{{ protected class properties
-
-    /**
-     * Keys used to encrypt
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => null
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addEncryptKey()
-     * @see Crypt_GPG::clearEncryptKeys()
-     */
-    protected $encryptKeys = array();
-
-    /**
-     * Keys used to decrypt
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => $passphrase
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addSignKey()
-     * @see Crypt_GPG::clearSignKeys()
-     */
-    protected $signKeys = array();
-
-    /**
-     * Keys used to sign
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => $passphrase
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addDecryptKey()
-     * @see Crypt_GPG::clearDecryptKeys()
-     */
-    protected $decryptKeys = array();
-
-    /**
-     * Passphrases used on import/export of private keys in GnuPG 2.1
-     *
-     * The array is of the form:
-     * <code>
-     * array($key_id => $passphrase);
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addPassphrase()
-     * @see Crypt_GPG::clearPassphrases()
-     */
-    protected $passphrases = array();
-
-    // }}}
-    // {{{ importKey()
-
-    /**
-     * Imports a public or private key into the keyring
-     *
-     * Keys may be removed from the keyring using
-     * {@link Crypt_GPG::deletePublicKey()} or
-     * {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $data the key data to be imported.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addPassphrase()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG::addPassphrase()
-     * @see Crypt_GPG::clearPassphrases()
-     */
-    public function importKey($data)
-    {
-        return $this->_importKey($data, false);
-    }
-
-    // }}}
-    // {{{ importKeyFile()
-
-    /**
-     * Imports a public or private key file into the keyring
-     *
-     * Keys may be removed from the keyring using
-     * {@link Crypt_GPG::deletePublicKey()} or
-     * {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $filename the key file to be imported.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *                                                  private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_FileException if the key file is not readable.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addPassphrase()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function importKeyFile($filename)
-    {
-        return $this->_importKey($filename, true);
-    }
-
-    // }}}
-    // {{{ exportPrivateKey()
-
-    /**
-     * Exports a private key from the keyring
-     *
-     * The exported key remains on the keyring. To delete the key, use
-     * {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first private key is exported.
-     *
-     * @param string  $keyId either the full uid of the private key, the email
-     *                       part of the uid of the private key or the key id of
-     *                       the private key. For example,
-     *                       "Test User (example) <test@example.com>",
-     *                       "test@example.com" or a hexadecimal string.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the private key data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addPassphrase()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function exportPrivateKey($keyId, $armor = true)
-    {
-        return $this->_exportKey($keyId, $armor, true);
-    }
-
-    // }}}
-    // {{{ exportPublicKey()
-
-    /**
-     * Exports a public key from the keyring
-     *
-     * The exported key remains on the keyring. To delete the public key, use
-     * {@link Crypt_GPG::deletePublicKey()}.
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first public key is exported.
-     *
-     * @param string  $keyId either the full uid of the public key, the email
-     *                       part of the uid of the public key or the key id of
-     *                       the public key. For example,
-     *                       "Test User (example) <test@example.com>",
-     *                       "test@example.com" or a hexadecimal string.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the public key data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function exportPublicKey($keyId, $armor = true)
-    {
-        return $this->_exportKey($keyId, $armor, false);
-    }
-
-    // }}}
-    // {{{ deletePublicKey()
-
-    /**
-     * Deletes a public key from the keyring
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first public key is deleted.
-     *
-     * The private key must be deleted first or an exception will be thrown.
-     * In GnuPG >= 2.1 this limitation does not exist.
-     * See {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $keyId either the full uid of the public key, the email
-     *                      part of the uid of the public key or the key id of
-     *                      the public key. For example,
-     *                      "Test User (example) <test@example.com>",
-     *                      "test@example.com" or a hexadecimal string.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_DeletePrivateKeyException if the specified public key
-     *         has an associated private key on the keyring. The private key
-     *         must be deleted first (when using GnuPG < 2.1).
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function deletePublicKey($keyId)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Public key not found: ' . $keyId,
-                self::ERROR_KEY_NOT_FOUND,
-                $keyId
-            );
-        }
-
-        $operation = '--delete-key ' . escapeshellarg($fingerprint);
-        $arguments = array(
-            '--batch',
-            '--yes'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-    }
-
-    // }}}
-    // {{{ deletePrivateKey()
-
-    /**
-     * Deletes a private key from the keyring
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first private key is deleted.
-     *
-     * Calls GPG with the <kbd>--delete-secret-key</kbd> command.
-     *
-     * @param string $keyId either the full uid of the private key, the email
-     *                      part of the uid of the private key or the key id of
-     *                      the private key. For example,
-     *                      "Test User (example) <test@example.com>",
-     *                      "test@example.com" or a hexadecimal string.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function deletePrivateKey($keyId)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Private key not found: ' . $keyId,
-                self::ERROR_KEY_NOT_FOUND,
-                $keyId
-            );
-        }
-
-        $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
-        $arguments = array(
-            '--batch',
-            '--yes'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-    }
-
-    // }}}
-    // {{{ getKeys()
-
-    /**
-     * Gets the available keys in the keyring
-     *
-     * Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
-     * the first section of <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
-     * description of how the GPG command output is parsed.
-     *
-     * @param string $keyId optional. Only keys with that match the specified
-     *                      pattern are returned. The pattern may be part of
-     *                      a user id, a key id or a key fingerprint. If not
-     *                      specified, all keys are returned.
-     *
-     * @return array an array of {@link Crypt_GPG_Key} objects. If no keys
-     *               match the specified <kbd>$keyId</kbd> an empty array is
-     *               returned.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Key
-     */
-    public function getKeys($keyId = '')
-    {
-        return parent::_getKeys($keyId);
-    }
-
-    // }}}
-    // {{{ getFingerprint()
-
-    /**
-     * Gets a key fingerprint from the keyring
-     *
-     * If more than one key fingerprint is available (for example, if you use
-     * a non-unique user id) only the first key fingerprint is returned.
-     *
-     * Calls the GPG <kbd>--list-keys</kbd> command with the
-     * <kbd>--with-fingerprint</kbd> option to retrieve a public key
-     * fingerprint.
-     *
-     * @param string  $keyId  either the full user id of the key, the email
-     *                        part of the user id of the key, or the key id of
-     *                        the key. For example,
-     *                        "Test User (example) <test@example.com>",
-     *                        "test@example.com" or a hexadecimal string.
-     * @param integer $format optional. How the fingerprint should be formatted.
-     *                        Use {@link Crypt_GPG::FORMAT_X509} for X.509
-     *                        certificate format,
-     *                        {@link Crypt_GPG::FORMAT_CANONICAL} for the format
-     *                        used by GnuPG output and
-     *                        {@link Crypt_GPG::FORMAT_NONE} for no formatting.
-     *                        Defaults to <code>Crypt_GPG::FORMAT_NONE</code>.
-     *
-     * @return string the fingerprint of the key, or null if no fingerprint
-     *                is found for the given <kbd>$keyId</kbd>.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function getFingerprint($keyId, $format = self::FORMAT_NONE)
-    {
-        $output    = '';
-        $operation = '--list-keys ' . escapeshellarg($keyId);
-        $arguments = array(
-            '--with-colons',
-            '--with-fingerprint'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $fingerprint = null;
-
-        foreach (explode(PHP_EOL, $output) as $line) {
-            if (mb_substr($line, 0, 3, '8bit') == 'fpr') {
-                $lineExp     = explode(':', $line);
-                $fingerprint = $lineExp[9];
-
-                switch ($format) {
-                case self::FORMAT_CANONICAL:
-                    $fingerprintExp = str_split($fingerprint, 4);
-                    $format         = '%s %s %s %s %s  %s %s %s %s %s';
-                    $fingerprint    = vsprintf($format, $fingerprintExp);
-                    break;
-
-                case self::FORMAT_X509:
-                    $fingerprintExp = str_split($fingerprint, 2);
-                    $fingerprint    = implode(':', $fingerprintExp);
-                    break;
-                }
-
-                break;
-            }
-        }
-
-        return $fingerprint;
-    }
-
-    // }}}
-    // {{{ getLastSignatureInfo()
-
-    /**
-     * Get information about the last signature that was created.
-     *
-     * @return Crypt_GPG_SignatureCreationInfo
-     */
-    public function getLastSignatureInfo()
-    {
-        return $this->engine->getProcessData('SignatureInfo');
-    }
-
-    // }}}
-    // {{{ encrypt()
-
-    /**
-     * Encrypts string data
-     *
-     * Data is ASCII armored by default but may optionally be returned as
-     * binary.
-     *
-     * @param string  $data  the data to be encrypted.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the encrypted data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @sensitive $data
-     */
-    public function encrypt($data, $armor = self::ARMOR_ASCII)
-    {
-        return $this->_encrypt($data, false, null, $armor);
-    }
-
-    // }}}
-    // {{{ encryptFile()
-
-    /**
-     * Encrypts a file
-     *
-     * Encrypted data is ASCII armored by default but may optionally be saved
-     * as binary.
-     *
-     * @param string  $filename      the filename of the file to encrypt.
-     * @param string  $encryptedFile optional. The filename of the file in
-     *                               which to store the encrypted data. If null
-     *                               or unspecified, the encrypted data is
-     *                               returned as a string.
-     * @param boolean $armor         optional. If true, ASCII armored data is
-     *                               returned; otherwise, binary data is
-     *                               returned. Defaults to true.
-     *
-     * @return void|string if the <kbd>$encryptedFile</kbd> parameter is null,
-     *                     a string containing the encrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function encryptFile(
-        $filename,
-        $encryptedFile = null,
-        $armor = self::ARMOR_ASCII
-    ) {
-        return $this->_encrypt($filename, true, $encryptedFile, $armor);
-    }
-
-    // }}}
-    // {{{ encryptAndSign()
-
-    /**
-     * Encrypts and signs data
-     *
-     * Data is encrypted and signed in a single pass.
-     *
-     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
-     * encrypted-signed data without decrypting it at the same time. If you try
-     * to use {@link Crypt_GPG::verify()} method on encrypted-signed data with
-     * earlier GnuPG versions, you will get an error. Please use
-     * {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data.
-     *
-     * @param string  $data  the data to be encrypted and signed.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the encrypted signed data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG::decryptAndVerify()
-     */
-    public function encryptAndSign($data, $armor = self::ARMOR_ASCII)
-    {
-        return $this->_encryptAndSign($data, false, null, $armor);
-    }
-
-    // }}}
-    // {{{ encryptAndSignFile()
-
-    /**
-     * Encrypts and signs a file
-     *
-     * The file is encrypted and signed in a single pass.
-     *
-     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
-     * encrypted-signed files without decrypting them at the same time. If you
-     * try to use {@link Crypt_GPG::verify()} method on encrypted-signed files
-     * with earlier GnuPG versions, you will get an error. Please use
-     * {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed
-     * files.
-     *
-     * @param string  $filename   the name of the file containing the data to
-     *                            be encrypted and signed.
-     * @param string  $signedFile optional. The name of the file in which the
-     *                            encrypted, signed data should be stored. If
-     *                            null or unspecified, the encrypted, signed
-     *                            data is returned as a string.
-     * @param boolean $armor      optional. If true, ASCII armored data is
-     *                            returned; otherwise, binary data is returned.
-     *                            Defaults to true.
-     *
-     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
-     *                     string containing the encrypted, signed data is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG::decryptAndVerifyFile()
-     */
-    public function encryptAndSignFile(
-        $filename,
-        $signedFile = null,
-        $armor = self::ARMOR_ASCII
-    ) {
-        return $this->_encryptAndSign($filename, true, $signedFile, $armor);
-    }
-
-    // }}}
-    // {{{ decrypt()
-
-    /**
-     * Decrypts string data
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedData the data to be decrypted.
-     *
-     * @return string the decrypted data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decrypt($encryptedData)
-    {
-        return $this->_decrypt($encryptedData, false, null);
-    }
-
-    // }}}
-    // {{{ decryptFile()
-
-    /**
-     * Decrypts a file
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedFile the name of the encrypted file data to
-     *                              decrypt.
-     * @param string $decryptedFile optional. The name of the file to which the
-     *                              decrypted data should be written. If null
-     *                              or unspecified, the decrypted data is
-     *                              returned as a string.
-     *
-     * @return void|string if the <kbd>$decryptedFile</kbd> parameter is null,
-     *                     a string containing the decrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptFile($encryptedFile, $decryptedFile = null)
-    {
-        return $this->_decrypt($encryptedFile, true, $decryptedFile);
-    }
-
-    // }}}
-    // {{{ decryptAndVerify()
-
-    /**
-     * Decrypts and verifies string data
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string  $encryptedData      the encrypted, signed data to be decrypted
-     *                                    and verified.
-     * @param boolean $ignoreVerifyErrors enables ignoring of signature
-     *                                    verification errors caused by missing public key
-     *                                    When enabled Crypt_GPG_KeyNotFoundException
-     *                                    will not be thrown.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data or the public key to verify the signature
-     *         is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptAndVerify($encryptedData, $ignoreVerifyErrors = false)
-    {
-        return $this->_decryptAndVerify($encryptedData, false, null, $ignoreVerifyErrors);
-    }
-
-    // }}}
-    // {{{ decryptAndVerifyFile()
-
-    /**
-     * Decrypts and verifies a signed, encrypted file
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string  $encryptedFile      the name of the signed, encrypted file to
-     *                                    to decrypt and verify.
-     * @param string  $decryptedFile      optional. The name of the file to which the
-     *                                    decrypted data should be written. If null
-     *                                    or unspecified, the decrypted data is
-     *                                    returned in the results array.
-     * @param boolean $ignoreVerifyErrors enables ignoring of signature
-     *                                    verification errors caused by missing public key
-     *                                    When enabled Crypt_GPG_KeyNotFoundException
-     *                                    will not be thrown.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *               If the decrypted data is written to a file, the 'data'
-     *               element is null.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data or the public key to verify the signature
-     *         is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null, $ignoreVerifyErrors = false)
-    {
-        return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile, $ignoreVerifyErrors);
-    }
-
-    // }}}
-    // {{{ sign()
-
-    /**
-     * Signs data
-     *
-     * Data may be signed using any one of the three available signing modes:
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @param string  $data     the data to be signed.
-     * @param boolean $mode     optional. The data signing mode to use. Should
-     *                          be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                          {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                          {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
-     *                          specified, defaults to
-     *                          <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
-     * @param boolean $armor    optional. If true, ASCII armored data is
-     *                          returned; otherwise, binary data is returned.
-     *                          Defaults to true. This has no effect if the
-     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                          used.
-     * @param boolean $textmode optional. If true, line-breaks in signed data
-     *                          are normalized. Use this option when signing
-     *                          e-mail, or for greater compatibility between
-     *                          systems with different line-break formats.
-     *                          Defaults to false. This has no effect if the
-     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                          used as clear-signing always uses textmode.
-     *
-     * @return string the signed data, or the signature data if a detached
-     *                signature is requested.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function sign(
-        $data,
-        $mode = self::SIGN_MODE_NORMAL,
-        $armor = self::ARMOR_ASCII,
-        $textmode = self::TEXT_RAW
-    ) {
-        return $this->_sign($data, false, null, $mode, $armor, $textmode);
-    }
-
-    // }}}
-    // {{{ signFile()
-
-    /**
-     * Signs a file
-     *
-     * The file may be signed using any one of the three available signing
-     * modes:
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @param string  $filename   the name of the file containing the data to
-     *                            be signed.
-     * @param string  $signedFile optional. The name of the file in which the
-     *                            signed data should be stored. If null or
-     *                            unspecified, the signed data is returned as a
-     *                            string.
-     * @param boolean $mode       optional. The data signing mode to use. Should
-     *                            be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
-     *                            specified, defaults to
-     *                            <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
-     * @param boolean $armor      optional. If true, ASCII armored data is
-     *                            returned; otherwise, binary data is returned.
-     *                            Defaults to true. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used.
-     * @param boolean $textmode   optional. If true, line-breaks in signed data
-     *                            are normalized. Use this option when signing
-     *                            e-mail, or for greater compatibility between
-     *                            systems with different line-break formats.
-     *                            Defaults to false. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used as clear-signing always uses textmode.
-     *
-     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
-     *                     string containing the signed data (or the signature
-     *                     data if a detached signature is requested) is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function signFile(
-        $filename,
-        $signedFile = null,
-        $mode = self::SIGN_MODE_NORMAL,
-        $armor = self::ARMOR_ASCII,
-        $textmode = self::TEXT_RAW
-    ) {
-        return $this->_sign(
-            $filename,
-            true,
-            $signedFile,
-            $mode,
-            $armor,
-            $textmode
-        );
-    }
-
-    // }}}
-    // {{{ verify()
-
-    /**
-     * Verifies signed data
-     *
-     * The {@link Crypt_GPG::decrypt()} method may be used to get the original
-     * message if the signed data is not clearsigned and does not use a
-     * detached signature.
-     *
-     * @param string $signedData the signed data to be verified.
-     * @param string $signature  optional. If verifying data signed using a
-     *                           detached signature, this must be the detached
-     *                           signature data. The data that was signed is
-     *                           specified in <kbd>$signedData</kbd>.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data. For each signature that is valid, the
-     *               {@link Crypt_GPG_Signature::isValid()} will return true.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
-     *         signature verification is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    public function verify($signedData, $signature = '')
-    {
-        return $this->_verify($signedData, false, $signature);
-    }
-
-    // }}}
-    // {{{ verifyFile()
-
-    /**
-     * Verifies a signed file
-     *
-     * The {@link Crypt_GPG::decryptFile()} method may be used to get the
-     * original message if the signed data is not clearsigned and does not use
-     * a detached signature.
-     *
-     * @param string $filename  the signed file to be verified.
-     * @param string $signature optional. If verifying a file signed using a
-     *                          detached signature, this must be the detached
-     *                          signature data. The file that was signed is
-     *                          specified in <kbd>$filename</kbd>.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data. For each signature that is valid, the
-     *               {@link Crypt_GPG_Signature::isValid()} will return true.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
-     *         signature verification is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_FileException if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    public function verifyFile($filename, $signature = '')
-    {
-        return $this->_verify($filename, true, $signature);
-    }
-
-    // }}}
-    // {{{ addDecryptKey()
-
-    /**
-     * Adds a key to use for decryption
-     *
-     * @param mixed  $key        the key to use. This may be a key identifier,
-     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                           {@link Crypt_GPG_SubKey}. The key must be able
-     *                           to encrypt.
-     * @param string $passphrase optional. The passphrase of the key required
-     *                           for decryption.
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::decrypt()
-     * @see Crypt_GPG::decryptFile()
-     * @see Crypt_GPG::clearDecryptKeys()
-     * @see Crypt_GPG::_addKey()
-     *
-     * @sensitive $passphrase
-     */
-    public function addDecryptKey($key, $passphrase = null)
-    {
-        $this->_addKey($this->decryptKeys, false, false, $key, $passphrase);
-        return $this;
-    }
-
-    // }}}
-    // {{{ addEncryptKey()
-
-    /**
-     * Adds a key to use for encryption
-     *
-     * @param mixed $key the key to use. This may be a key identifier, user id
-     *                   user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                   {@link Crypt_GPG_SubKey}. The key must be able to
-     *                   encrypt.
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::encrypt()
-     * @see Crypt_GPG::encryptFile()
-     * @see Crypt_GPG::clearEncryptKeys()
-     * @see Crypt_GPG::_addKey()
-     */
-    public function addEncryptKey($key)
-    {
-        $this->_addKey($this->encryptKeys, true, false, $key);
-        return $this;
-    }
-
-    // }}}
-    // {{{ addSignKey()
-
-    /**
-     * Adds a key to use for signing
-     *
-     * @param mixed  $key        the key to use. This may be a key identifier,
-     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                           {@link Crypt_GPG_SubKey}. The key must be able
-     *                           to sign.
-     * @param string $passphrase optional. The passphrase of the key required
-     *                           for signing.
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     * @see Crypt_GPG::clearSignKeys()
-     * @see Crypt_GPG::_addKey()
-     *
-     * @sensitive $passphrase
-     */
-    public function addSignKey($key, $passphrase = null)
-    {
-        $this->_addKey($this->signKeys, false, true, $key, $passphrase);
-        return $this;
-    }
-
-    // }}}
-    // {{{ addPassphrase()
-
-    /**
-     * Register a private key passphrase for import/export (GnuPG 2.1)
-     *
-     * @param mixed  $key        The key to use. This must be a key identifier,
-     *                           or fingerprint.
-     * @param string $passphrase The passphrase of the key.
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::clearPassphrases()
-     * @see Crypt_GPG::importKey()
-     * @see Crypt_GPG::exportKey()
-     *
-     * @sensitive $passphrase
-     */
-    public function addPassphrase($key, $passphrase)
-    {
-        $this->passphrases[$key] = $passphrase;
-        return $this;
-    }
-
-    // }}}
-    // {{{ clearDecryptKeys()
-
-    /**
-     * Clears all decryption keys
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::decrypt()
-     * @see Crypt_GPG::addDecryptKey()
-     */
-    public function clearDecryptKeys()
-    {
-        $this->decryptKeys = array();
-        return $this;
-    }
-
-    // }}}
-    // {{{ clearEncryptKeys()
-
-    /**
-     * Clears all encryption keys
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::encrypt()
-     * @see Crypt_GPG::addEncryptKey()
-     */
-    public function clearEncryptKeys()
-    {
-        $this->encryptKeys = array();
-        return $this;
-    }
-
-    // }}}
-    // {{{ clearSignKeys()
-
-    /**
-     * Clears all signing keys
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::addSignKey()
-     */
-    public function clearSignKeys()
-    {
-        $this->signKeys = array();
-        return $this;
-    }
-
-    // }}}
-    // {{{ clearPassphrases()
-
-    /**
-     * Clears all private key passphrases
-     *
-     * @return Crypt_GPG the current object, for fluent interface.
-     *
-     * @see Crypt_GPG::importKey()
-     * @see Crypt_GPG::exportKey()
-     * @see Crypt_GPG::addPassphrase()
-     */
-    public function clearPassphrases()
-    {
-        $this->passphrases = array();
-        return $this;
-    }
-
-    // }}}
-    // {{{ hasEncryptKeys()
-
-    /**
-     * Tell if there are encryption keys registered
-     *
-     * @return boolean True if the data shall be encrypted
-     */
-    public function hasEncryptKeys()
-    {
-        return count($this->encryptKeys) > 0;
-    }
-
-    // }}}
-    // {{{ hasSignKeys()
-
-    /**
-     * Tell if there are signing keys registered
-     *
-     * @return boolean True if the data shall be signed
-     */
-    public function hasSignKeys()
-    {
-        return count($this->signKeys) > 0;
-    }
-
-    // }}}
-    // {{{ _addKey()
-
-    /**
-     * Adds a key to one of the internal key arrays
-     *
-     * This handles resolving full key objects from the provided
-     * <kbd>$key</kbd> value.
-     *
-     * @param array   &$array     the array to which the key should be added.
-     * @param boolean $encrypt    whether or not the key must be able to
-     *                            encrypt.
-     * @param boolean $sign       whether or not the key must be able to sign.
-     * @param mixed   $key        the key to add. This may be a key identifier,
-     *                            user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                            {@link Crypt_GPG_SubKey}.
-     * @param string  $passphrase optional. The passphrase associated with the
-     *                            key.
-     *
-     * @return void
-     *
-     * @sensitive $passphrase
-     */
-    protected function _addKey(array &$array, $encrypt, $sign, $key,
-        $passphrase = null
-    ) {
-        $subKeys = array();
-
-        if (is_scalar($key)) {
-            $keys = $this->getKeys($key);
-            if (count($keys) == 0) {
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Key not found: ' . $key,
-                    self::ERROR_KEY_NOT_FOUND,
-                    $key
-                );
-            }
-            $key = $keys[0];
-        }
-
-        if ($key instanceof Crypt_GPG_Key) {
-            if ($encrypt && !$key->canEncrypt()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot encrypt.'
-                );
-            }
-
-            if ($sign && !$key->canSign()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot sign.'
-                );
-            }
-
-            foreach ($key->getSubKeys() as $subKey) {
-                $canEncrypt = $subKey->canEncrypt();
-                $canSign    = $subKey->canSign();
-                if (($encrypt && $sign && $canEncrypt && $canSign)
-                    || ($encrypt && !$sign && $canEncrypt)
-                    || (!$encrypt && $sign && $canSign)
-                    || (!$encrypt && !$sign)
-                ) {
-                    // We add all subkeys that meet the requirements because we
-                    // were not told which subkey is required.
-                    $subKeys[] = $subKey;
-                }
-            }
-        } elseif ($key instanceof Crypt_GPG_SubKey) {
-            $subKeys[] = $key;
-        }
-
-        if (count($subKeys) === 0) {
-            throw new InvalidArgumentException(
-                'Key "' . $key . '" is not in a recognized format.'
-            );
-        }
-
-        foreach ($subKeys as $subKey) {
-            if ($encrypt && !$subKey->canEncrypt()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot encrypt.'
-                );
-            }
-
-            if ($sign && !$subKey->canSign()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot sign.'
-                );
-            }
-
-            $array[$subKey->getId()] = array(
-                'fingerprint' => $subKey->getFingerprint(),
-                'passphrase'  => $passphrase
-            );
-        }
-    }
-
-    // }}}
-    // {{{ _importKey()
-
-    /**
-     * Imports a public or private key into the keyring
-     *
-     * @param string  $key    the key to be imported.
-     * @param boolean $isFile whether or not the input is a filename.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_FileException if the key file is not readable.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addPassphrase()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _importKey($key, $isFile)
-    {
-        $result    = array();
-        $arguments = array();
-        $input     = $this->_prepareInput($key, $isFile, false);
-        $version   = $this->engine->getVersion();
-
-        if (version_compare($version, '1.0.5', 'ge')
-            && version_compare($version, '1.0.7', 'lt')
-        ) {
-            $arguments[] = '--allow-secret-key-import';
-        }
-
-        if (empty($this->passphrases)) {
-            $arguments[] = '--batch';
-        }
-
-        $this->engine->reset();
-        $this->engine->setPins($this->passphrases);
-        $this->engine->setOperation('--import', $arguments);
-        $this->engine->setInput($input);
-        $this->engine->run();
-
-        return $this->engine->getProcessData('Import');
-    }
-
-    // }}}
-    // {{{ _exportKey()
-
-    /**
-     * Exports a private or public key from the keyring
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first key is exported.
-     *
-     * @param string  $keyId   either the full uid of the key, the email
-     *                         part of the uid of the key or the key id.
-     * @param boolean $armor   optional. If true, ASCII armored data is returned;
-     *                         otherwise, binary data is returned. Defaults to
-     *                         true.
-     * @param boolean $private return private instead of public key
-     *
-     * @return string the key data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addPassphrase()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _exportKey($keyId, $armor = true, $private = false)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Key not found: ' . $keyId,
-                self::ERROR_KEY_NOT_FOUND,
-                $keyId
-            );
-        }
-
-        $keyData   = '';
-        $operation = $private ? '--export-secret-keys' : '--export';
-        $operation .= ' ' . escapeshellarg($fingerprint);
-        $arguments = $armor ? array('--armor') : array();
-
-        $this->engine->reset();
-        $this->engine->setPins($this->passphrases);
-        $this->engine->setOutput($keyData);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        return $keyData;
-    }
-
-    // }}}
-    // {{{ _encrypt()
-
-    /**
-     * Encrypts data
-     *
-     * @param string  $data       the data to encrypt.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the filename of the file in which to store
-     *                            the encrypted data. If null, the encrypted
-     *                            data is returned as a string.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the encrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _encrypt($data, $isFile, $outputFile, $armor)
-    {
-        if (!$this->hasEncryptKeys()) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No encryption keys specified.'
-            );
-        }
-
-        $input     = $this->_prepareInput($data, $isFile);
-        $output    = $this->_prepareOutput($outputFile, $input);
-        $arguments = $armor ? array('--armor') : array();
-
-        foreach ($this->encryptKeys as $key) {
-            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--encrypt', $arguments);
-        $this->engine->run();
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _decrypt()
-
-    /**
-     * Decrypts data
-     *
-     * @param string  $data       the data to be decrypted.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file to which the decrypted
-     *                            data should be written. If null, the decrypted
-     *                            data is returned as a string.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the decrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _decrypt($data, $isFile, $outputFile)
-    {
-        $input  = $this->_prepareInput($data, $isFile, false);
-        $output = $this->_prepareOutput($outputFile, $input);
-
-        $this->engine->reset();
-        $this->engine->setPins($this->decryptKeys);
-        $this->engine->setOperation('--decrypt --skip-verify');
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->run();
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _sign()
-
-    /**
-     * Signs data
-     *
-     * @param string  $data       the data to be signed.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file in which the signed data
-     *                            should be stored. If null, the signed data is
-     *                            returned as a string.
-     * @param boolean $mode       the data signing mode to use. Should be one of
-     *                            {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned. This has
-     *                            no effect if the mode
-     *                            <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used.
-     * @param boolean $textmode   if true, line-breaks in signed data be
-     *                            normalized. Use this option when signing
-     *                            e-mail, or for greater compatibility between
-     *                            systems with different line-break formats.
-     *                            Defaults to false. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used as clear-signing always uses textmode.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the signed data (or the signature
-     *                     data if a detached signature is requested) is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _sign($data, $isFile, $outputFile, $mode, $armor,
-        $textmode
-    ) {
-        if (!$this->hasSignKeys()) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No signing keys specified.'
-            );
-        }
-
-        $input  = $this->_prepareInput($data, $isFile);
-        $output = $this->_prepareOutput($outputFile, $input);
-
-        switch ($mode) {
-        case self::SIGN_MODE_DETACHED:
-            $operation = '--detach-sign';
-            break;
-        case self::SIGN_MODE_CLEAR:
-            $operation = '--clearsign';
-            break;
-        case self::SIGN_MODE_NORMAL:
-        default:
-            $operation = '--sign';
-            break;
-        }
-
-        $arguments = array();
-
-        if ($armor) {
-            $arguments[] = '--armor';
-        }
-        if ($textmode) {
-            $arguments[] = '--textmode';
-        }
-
-        foreach ($this->signKeys as $key) {
-            $arguments[] = '--local-user ' .
-                escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->setPins($this->signKeys);
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _encryptAndSign()
-
-    /**
-     * Encrypts and signs data
-     *
-     * @param string  $data       the data to be encrypted and signed.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file in which the encrypted,
-     *                            signed data should be stored. If null, the
-     *                            encrypted, signed data is returned as a
-     *                            string.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the encrypted, signed data is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    protected function _encryptAndSign($data, $isFile, $outputFile, $armor)
-    {
-        if (!$this->hasSignKeys()) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No signing keys specified.'
-            );
-        }
-
-        if (!$this->hasEncryptKeys()) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No encryption keys specified.'
-            );
-        }
-
-        $input     = $this->_prepareInput($data, $isFile);
-        $output    = $this->_prepareOutput($outputFile, $input);
-        $arguments = $armor ? array('--armor') : array();
-
-        foreach ($this->signKeys as $key) {
-            $arguments[] = '--local-user ' .
-                escapeshellarg($key['fingerprint']);
-        }
-
-        foreach ($this->encryptKeys as $key) {
-            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->setPins($this->signKeys);
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--encrypt --sign', $arguments);
-        $this->engine->run();
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _verify()
-
-    /**
-     * Verifies data
-     *
-     * @param string  $data      the signed data to be verified.
-     * @param boolean $isFile    whether or not the data is a filename.
-     * @param string  $signature if verifying a file signed using a detached
-     *                           signature, this must be the detached signature
-     *                           data. Otherwise, specify ''.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
-     *         signature verification is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_FileException if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    protected function _verify($data, $isFile, $signature)
-    {
-        if ($signature == '') {
-            $operation = '--verify';
-            $arguments = array();
-        } else {
-            // Signed data goes in FD_MESSAGE, detached signature data goes in
-            // FD_INPUT.
-            $operation = '--verify - "-&' . Crypt_GPG_Engine::FD_MESSAGE. '"';
-            $arguments = array('--enable-special-filenames');
-        }
-
-        $input = $this->_prepareInput($data, $isFile, false);
-
-        $this->engine->reset();
-
-        if ($signature == '') {
-            // signed or clearsigned data
-            $this->engine->setInput($input);
-        } else {
-            // detached signature
-            $this->engine->setInput($signature);
-            $this->engine->setMessage($input);
-        }
-
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        return $this->engine->getProcessData('Signatures');
-    }
-
-    // }}}
-    // {{{ _decryptAndVerify()
-
-    /**
-     * Decrypts and verifies encrypted, signed data
-     *
-     * @param string  $data               the encrypted signed data to be decrypted and
-     *                                    verified.
-     * @param boolean $isFile             whether or not the data is a filename.
-     * @param string  $outputFile         the name of the file to which the decrypted
-     *                                    data should be written. If null, the decrypted
-     *                                    data is returned in the results array.
-     * @param boolean $ignoreVerifyErrors enables ignoring of signature verification
-     *                                    errors caused by missing public key.
-     *                                    When enabled Crypt_GPG_KeyNotFoundException
-     *                                    will not be thrown.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *               If the decrypted data is written to a file, the 'data'
-     *               element is null.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring or if the public
-     *         key needed for verification is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG signed, encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    protected function _decryptAndVerify($data, $isFile, $outputFile, $ignoreVerifyErrors = false)
-    {
-        $input  = $this->_prepareInput($data, $isFile, false);
-        $output = $this->_prepareOutput($outputFile, $input);
-
-        $this->engine->reset();
-        $this->engine->setPins($this->decryptKeys);
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--decrypt');
-        $this->engine->setProcessData('IgnoreVerifyErrors', $ignoreVerifyErrors);
-        $this->engine->run();
-
-        $return = array(
-            'data'       => null,
-            'signatures' => $this->engine->getProcessData('Signatures')
-        );
-
-        if ($outputFile === null) {
-            $return['data'] = $output;
-        }
-
-        return $return;
-    }
-
-    // }}}
-    // {{{ _prepareInput()
-
-    /**
-     * Prepares command input
-     *
-     * @param string  $data       the input data.
-     * @param boolean $isFile     whether or not the input is a filename.
-     * @param boolean $allowEmpty whether to check if the input is not empty.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing.
-     * @throws Crypt_GPG_FileException if the file is not readable.
-     */
-    protected function _prepareInput($data, $isFile = false, $allowEmpty = true)
-    {
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException(
-                    'Could not open input file "' . $data . '"',
-                    0,
-                    $data
-                );
-            }
-        } else {
-            $input = strval($data);
-            if (!$allowEmpty && $input === '') {
-                throw new Crypt_GPG_NoDataException(
-                    'No valid input data found.',
-                    self::ERROR_NO_DATA
-                );
-            }
-        }
-
-        return $input;
-    }
-
-    // }}}
-    // {{{ _prepareOutput()
-
-    /**
-     * Prepares command output
-     *
-     * @param string  $outputFile the name of the file in which the output
-     *                            data should be stored. If null, the output
-     *                            data is returned as a string.
-     * @param boolean $input      the input resource, in case it would need
-     *                            to be released (closed) on exception.
-     *
-     * @throws Crypt_GPG_FileException if the file is not writeable.
-     */
-    protected function _prepareOutput($outputFile, $input = null)
-    {
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if (is_resource($input)) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException(
-                    'Could not open output file "' . $outputFile . '"',
-                    0,
-                    $outputFile
-                );
-            }
-        }
-
-        return $output;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/Engine.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2089 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains an engine that handles GPG subprocess control and I/O.
- * PHP's process manipulation functions are used to handle the GPG subprocess.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Crypt_GPG base class.
- */
-require_once 'Crypt/GPG.php';
-
-/**
- * GPG exception classes.
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-/**
- * Status/Error handler class.
- */
-require_once 'Crypt/GPG/ProcessHandler.php';
-
-/**
- * Process control methods.
- */
-require_once 'Crypt/GPG/ProcessControl.php';
-
-/**
- * Information about a created signature
- */
-require_once 'Crypt/GPG/SignatureCreationInfo.php';
-
-/**
- * Standard PEAR exception is used if GPG binary is not found.
- */
-require_once 'PEAR/Exception.php';
-
-// {{{ class Crypt_GPG_Engine
-
-/**
- * Native PHP Crypt_GPG I/O engine
- *
- * This class is used internally by Crypt_GPG and does not need be used
- * directly. See the {@link Crypt_GPG} class for end-user API.
- *
- * This engine uses PHP's native process control functions to directly control
- * the GPG process. The GPG executable is required to be on the system.
- *
- * All data is passed to the GPG subprocess using file descriptors. This is the
- * most secure method of passing data to the GPG subprocess.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_Engine
-{
-    // {{{ constants
-
-    /**
-     * Size of data chunks that are sent to and retrieved from the IPC pipes.
-     *
-     * The value of 65536 has been chosen empirically
-     * as the one with best performance.
-     *
-     * @see https://pear.php.net/bugs/bug.php?id=21077
-     */
-    const CHUNK_SIZE = 65536;
-
-    /**
-     * Standard input file descriptor. This is used to pass data to the GPG
-     * process.
-     */
-    const FD_INPUT = 0;
-
-    /**
-     * Standard output file descriptor. This is used to receive normal output
-     * from the GPG process.
-     */
-    const FD_OUTPUT = 1;
-
-    /**
-     * Standard output file descriptor. This is used to receive error output
-     * from the GPG process.
-     */
-    const FD_ERROR = 2;
-
-    /**
-     * GPG status output file descriptor. The status file descriptor outputs
-     * detailed information for many GPG commands. See the second section of
-     * the file <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
-     * description of GPG's status output.
-     */
-    const FD_STATUS = 3;
-
-    /**
-     * Command input file descriptor. This is used for methods requiring
-     * passphrases.
-     */
-    const FD_COMMAND = 4;
-
-    /**
-     * Extra message input file descriptor. This is used for passing signed
-     * data when verifying a detached signature.
-     */
-    const FD_MESSAGE = 5;
-
-    /**
-     * Minimum version of GnuPG that is supported.
-     */
-    const MIN_VERSION = '1.0.2';
-
-    // }}}
-    // {{{ private class properties
-
-    /**
-     * Whether or not to use strict mode
-     *
-     * When set to true, any clock problems (e.g. keys generate in future)
-     * are errors, otherwise they are just warnings.
-     *
-     * Strict mode is disabled by default.
-     *
-     * @var boolean
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_strict = false;
-
-    /**
-     * Whether or not to use debugging mode
-     *
-     * When set to true, every GPG command is echoed before it is run. Sensitive
-     * data is always handled using pipes and is not specified as part of the
-     * command. As a result, sensitive data is never displayed when debug is
-     * enabled. Sensitive data includes private key data and passphrases.
-     *
-     * This can be set to a callable function where first argument is the
-     * debug line to process.
-     *
-     * Debugging is off by default.
-     *
-     * @var mixed
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_debug = false;
-
-    /**
-     * Location of GPG binary
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     * @see Crypt_GPG_Engine::_getBinary()
-     */
-    private $_binary = '';
-
-    /**
-     * Location of GnuPG agent binary
-     *
-     * Only used for GnuPG 2.x
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     * @see Crypt_GPG_Engine::_getAgent()
-     */
-    private $_agent = '';
-
-    /**
-     * Location of GnuPG conf binary
-     *
-     * Only used for GnuPG 2.1.x
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     * @see Crypt_GPG_Engine::_getGPGConf()
-     */
-    private $_gpgconf = null;
-
-    /**
-     * Directory containing the GPG key files
-     *
-     * This property only contains the path when the <i>homedir</i> option
-     * is specified in the constructor.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_homedir = '';
-
-    /**
-     * File path of the public keyring
-     *
-     * This property only contains the file path when the <i>public_keyring</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_publicKeyring = '';
-
-    /**
-     * File path of the private (secret) keyring
-     *
-     * This property only contains the file path when the <i>private_keyring</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_privateKeyring = '';
-
-    /**
-     * File path of the trust database
-     *
-     * This property only contains the file path when the <i>trust_db</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_trustDb = '';
-
-    /**
-     * Array of pipes used for communication with the GPG binary
-     *
-     * This is an array of file descriptor resources.
-     *
-     * @var array
-     */
-    private $_pipes = array();
-
-    /**
-     * Array of pipes used for communication with the gpg-agent binary
-     *
-     * This is an array of file descriptor resources.
-     *
-     * @var array
-     */
-    private $_agentPipes = array();
-
-    /**
-     * Array of currently opened pipes
-     *
-     * This array is used to keep track of remaining opened pipes so they can
-     * be closed when the GPG subprocess is finished. This array is a subset of
-     * the {@link Crypt_GPG_Engine::$_pipes} array and contains opened file
-     * descriptor resources.
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::_closePipe()
-     */
-    private $_openPipes = array();
-
-    /**
-     * A handle for the GPG process
-     *
-     * @var resource
-     */
-    private $_process = null;
-
-    /**
-     * A handle for the gpg-agent process
-     *
-     * @var resource
-     */
-    private $_agentProcess = null;
-
-    /**
-     * GPG agent daemon socket and PID for running gpg-agent
-     *
-     * @var string
-     */
-    private $_agentInfo = null;
-
-    /**
-     * Whether or not the operating system is Darwin (OS X)
-     *
-     * @var boolean
-     */
-    private $_isDarwin = false;
-
-    /**
-     * Message digest algorithm.
-     *
-     * @var string
-     */
-    private $_digest_algo = null;
-
-    /**
-     * Symmetric cipher algorithm.
-     *
-     * @var string
-     */
-    private $_cipher_algo = null;
-
-    /**
-     * Commands to be sent to GPG's command input stream
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::sendCommand()
-     */
-    private $_commandBuffer = '';
-
-    /**
-     * A status/error handler
-     *
-     * @var Crypt_GPG_ProcessHanler
-     */
-    private $_processHandler = null;
-
-    /**
-     * Array of status line handlers
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::addStatusHandler()
-     */
-    private $_statusHandlers = array();
-
-    /**
-     * Array of error line handlers
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::addErrorHandler()
-     */
-    private $_errorHandlers = array();
-
-    /**
-     * The input source
-     *
-     * This is data to send to GPG. Either a string or a stream resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setInput()
-     */
-    private $_input = null;
-
-    /**
-     * The extra message input source
-     *
-     * Either a string or a stream resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setMessage()
-     */
-    private $_message = null;
-
-    /**
-     * The output location
-     *
-     * This is where the output from GPG is sent. Either a string or a stream
-     * resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setOutput()
-     */
-    private $_output = '';
-
-    /**
-     * The GPG operation to execute
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    private $_operation;
-
-    /**
-     * Arguments for the current operation
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    private $_arguments = array();
-
-    /**
-     * The version number of the GPG binary
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::getVersion()
-     */
-    private $_version = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new GPG engine
-     *
-     * Available options are:
-     *
-     * - <kbd>string  homedir</kbd>        - the directory where the GPG
-     *                                       keyring files are stored. If not
-     *                                       specified, Crypt_GPG uses the
-     *                                       default of <kbd>~/.gnupg</kbd>.
-     * - <kbd>string  publicKeyring</kbd>  - the file path of the public
-     *                                       keyring. Use this if the public
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/pubring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  privateKeyring</kbd> - the file path of the private
-     *                                       keyring. Use this if the private
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/secring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  trustDb</kbd>        - the file path of the web-of-trust
-     *                                       database. Use this if the trust
-     *                                       database is not in the homedir, or
-     *                                       if the database is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       trust database with this option
-     *                                       (/foo/bar/trustdb.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  binary</kbd>         - the location of the GPG binary. If
-     *                                       not specified, the driver attempts
-     *                                       to auto-detect the GPG binary
-     *                                       location using a list of known
-     *                                       default locations for the current
-     *                                       operating system. The option
-     *                                       <kbd>gpgBinary</kbd> is a
-     *                                       deprecated alias for this option.
-     * - <kbd>string  agent</kbd>          - the location of the GnuPG agent
-     *                                       binary. The gpg-agent is only
-     *                                       used for GnuPG 2.x. If not
-     *                                       specified, the engine attempts
-     *                                       to auto-detect the gpg-agent
-     *                                       binary location using a list of
-     *                                       know default locations for the
-     *                                       current operating system.
-     * - <kbd>string|false gpgconf</kbd>   - the location of the GnuPG conf
-     *                                       binary. The gpgconf is only
-     *                                       used for GnuPG >= 2.1. If not
-     *                                       specified, the engine attempts
-     *                                       to auto-detect the location using
-     *                                       a list of know default locations.
-     *                                       When set to FALSE `gpgconf --kill`
-     *                                       will not be executed via destructor.
-     * - <kbd>string digest-algo</kbd>     - Sets the message digest algorithm.
-     * - <kbd>string cipher-algo</kbd>     - Sets the symmetric cipher.
-     * - <kbd>boolean strict</kbd>         - In strict mode clock problems on
-     *                                       subkeys and signatures are not ignored
-     *                                       (--ignore-time-conflict
-     *                                       and --ignore-valid-from options)
-     * - <kbd>mixed debug</kbd>            - whether or not to use debug mode.
-     *                                       When debug mode is on, all
-     *                                       communication to and from the GPG
-     *                                       subprocess is logged. This can be
-     *                                       useful to diagnose errors when
-     *                                       using Crypt_GPG.
-     *
-     * @param array $options optional. An array of options used to create the
-     *                       GPG object. All options are optional and are
-     *                       represented as key-value pairs.
-     *
-     * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
-     *         and cannot be created. This can happen if <kbd>homedir</kbd> is
-     *         not specified, Crypt_GPG is run as the web user, and the web
-     *         user has no home directory. This exception is also thrown if any
-     *         of the options <kbd>publicKeyring</kbd>,
-     *         <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
-     *         specified but the files do not exist or are are not readable.
-     *         This can happen if the user running the Crypt_GPG process (for
-     *         example, the Apache user) does not have permission to read the
-     *         files.
-     *
-     * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
-     *         if no <kbd>binary</kbd> is provided and no suitable binary could
-     *         be found.
-     *
-     * @throws PEAR_Exception if the provided <kbd>agent</kbd> is invalid, or
-     *         if no <kbd>agent</kbd> is provided and no suitable gpg-agent
-     *         cound be found.
-     */
-    public function __construct(array $options = array())
-    {
-        $this->_isDarwin = (strncmp(strtoupper(PHP_OS), 'DARWIN', 6) === 0);
-
-        // get homedir
-        if (array_key_exists('homedir', $options)) {
-            $this->_homedir = (string)$options['homedir'];
-        } else {
-            if (extension_loaded('posix')) {
-                // note: this requires the package OS dep exclude 'windows'
-                $info = posix_getpwuid(posix_getuid());
-                $this->_homedir = $info['dir'].'/.gnupg';
-            } else {
-                if (isset($_SERVER['HOME'])) {
-                    $this->_homedir = $_SERVER['HOME'];
-                } else {
-                    $this->_homedir = getenv('HOME');
-                }
-            }
-
-            if ($this->_homedir === false) {
-                throw new Crypt_GPG_FileException(
-                    'Could not locate homedir. Please specify the homedir ' .
-                    'to use with the \'homedir\' option when instantiating ' .
-                    'the Crypt_GPG object.'
-                );
-            }
-        }
-
-        // attempt to create homedir if it does not exist
-        if (!is_dir($this->_homedir)) {
-            if (@mkdir($this->_homedir, 0777, true)) {
-                // Set permissions on homedir. Parent directories are created
-                // with 0777, homedir is set to 0700.
-                chmod($this->_homedir, 0700);
-            } else {
-                throw new Crypt_GPG_FileException(
-                    'The \'homedir\' "' . $this->_homedir . '" is not ' .
-                    'readable or does not exist and cannot be created. This ' .
-                    'can happen if \'homedir\' is not specified in the ' .
-                    'Crypt_GPG options, Crypt_GPG is run as the web user, ' .
-                    'and the web user has no home directory.',
-                    0,
-                    $this->_homedir
-                );
-            }
-        }
-
-        // check homedir permissions (See Bug #19833)
-        if (!is_executable($this->_homedir)) {
-            throw new Crypt_GPG_FileException(
-                'The \'homedir\' "' . $this->_homedir . '" is not enterable ' .
-                'by the current user. Please check the permissions on your ' .
-                'homedir and make sure the current user can both enter and ' .
-                'write to the directory.',
-                0,
-                $this->_homedir
-            );
-        }
-        if (!is_writeable($this->_homedir)) {
-            throw new Crypt_GPG_FileException(
-                'The \'homedir\' "' . $this->_homedir . '" is not writable ' .
-                'by the current user. Please check the permissions on your ' .
-                'homedir and make sure the current user can both enter and ' .
-                'write to the directory.',
-                0,
-                $this->_homedir
-            );
-        }
-
-        // get binary
-        if (array_key_exists('binary', $options)) {
-            $this->_binary = (string)$options['binary'];
-        } elseif (array_key_exists('gpgBinary', $options)) {
-            // deprecated alias
-            $this->_binary = (string)$options['gpgBinary'];
-        } else {
-            $this->_binary = $this->_getBinary();
-        }
-
-        if ($this->_binary == '' || !is_executable($this->_binary)) {
-            throw new PEAR_Exception(
-                'GPG binary not found. If you are sure the GPG binary is ' .
-                'installed, please specify the location of the GPG binary ' .
-                'using the \'binary\' driver option.'
-            );
-        }
-
-        // get agent
-        if (array_key_exists('agent', $options)) {
-            $this->_agent = (string)$options['agent'];
-
-            if ($this->_agent && !is_executable($this->_agent)) {
-                throw new PEAR_Exception(
-                    'Specified gpg-agent binary is not executable.'
-                );
-            }
-        } else {
-            $this->_agent = $this->_getAgent();
-        }
-
-        if (array_key_exists('gpgconf', $options)) {
-            $this->_gpgconf = $options['gpgconf'];
-
-            if ($this->_gpgconf && !is_executable($this->_gpgconf)) {
-                throw new PEAR_Exception(
-                    'Specified gpgconf binary is not executable.'
-                );
-            }
-        }
-
-        /*
-         * Note:
-         *
-         * Normally, GnuPG expects keyrings to be in the homedir and expects
-         * to be able to write temporary files in the homedir. Sometimes,
-         * keyrings are not in the homedir, or location of the keyrings does
-         * not allow writing temporary files. In this case, the <i>homedir</i>
-         * option by itself is not enough to specify the keyrings because GnuPG
-         * can not write required temporary files. Additional options are
-         * provided so you can specify the location of the keyrings separately
-         * from the homedir.
-         */
-
-        // get public keyring
-        if (array_key_exists('publicKeyring', $options)) {
-            $this->_publicKeyring = (string)$options['publicKeyring'];
-            if (!is_readable($this->_publicKeyring)) {
-                throw new Crypt_GPG_FileException(
-                    'The \'publicKeyring\' "' . $this->_publicKeyring .
-                    '" does not exist or is not readable. Check the location ' .
-                    'and ensure the file permissions are correct.',
-                    0, $this->_publicKeyring
-                );
-            }
-        }
-
-        // get private keyring
-        if (array_key_exists('privateKeyring', $options)) {
-            $this->_privateKeyring = (string)$options['privateKeyring'];
-            if (!is_readable($this->_privateKeyring)) {
-                throw new Crypt_GPG_FileException(
-                    'The \'privateKeyring\' "' . $this->_privateKeyring .
-                    '" does not exist or is not readable. Check the location ' .
-                    'and ensure the file permissions are correct.',
-                    0, $this->_privateKeyring
-                );
-            }
-        }
-
-        // get trust database
-        if (array_key_exists('trustDb', $options)) {
-            $this->_trustDb = (string)$options['trustDb'];
-            if (!is_readable($this->_trustDb)) {
-                throw new Crypt_GPG_FileException(
-                    'The \'trustDb\' "' . $this->_trustDb .
-                    '" does not exist or is not readable. Check the location ' .
-                    'and ensure the file permissions are correct.',
-                    0, $this->_trustDb
-                );
-            }
-        }
-
-        if (array_key_exists('debug', $options)) {
-            $this->_debug = $options['debug'];
-        }
-
-        $this->_strict = !empty($options['strict']);
-
-        if (!empty($options['digest-algo'])) {
-            $this->_digest_algo = $options['digest-algo'];
-        }
-
-        if (!empty($options['cipher-algo'])) {
-            $this->_cipher_algo = $options['cipher-algo'];
-        }
-    }
-
-    // }}}
-    // {{{ __destruct()
-
-    /**
-     * Closes open GPG subprocesses when this object is destroyed
-     *
-     * Subprocesses should never be left open by this class unless there is
-     * an unknown error and unexpected script termination occurs.
-     */
-    public function __destruct()
-    {
-        $this->_closeSubprocess();
-        $this->_closeIdleAgents();
-    }
-
-    // }}}
-    // {{{ addErrorHandler()
-
-    /**
-     * Adds an error handler method
-     *
-     * The method is run every time a new error line is received from the GPG
-     * subprocess. The handler method must accept the error line to be handled
-     * as its first parameter.
-     *
-     * @param callback $callback the callback method to use.
-     * @param array    $args     optional. Additional arguments to pass as
-     *                           parameters to the callback method.
-     *
-     * @return void
-     */
-    public function addErrorHandler($callback, array $args = array())
-    {
-        $this->_errorHandlers[] = array(
-            'callback' => $callback,
-            'args'     => $args
-        );
-    }
-
-    // }}}
-    // {{{ addStatusHandler()
-
-    /**
-     * Adds a status handler method
-     *
-     * The method is run every time a new status line is received from the
-     * GPG subprocess. The handler method must accept the status line to be
-     * handled as its first parameter.
-     *
-     * @param callback $callback the callback method to use.
-     * @param array    $args     optional. Additional arguments to pass as
-     *                           parameters to the callback method.
-     *
-     * @return void
-     */
-    public function addStatusHandler($callback, array $args = array())
-    {
-        $this->_statusHandlers[] = array(
-            'callback' => $callback,
-            'args'     => $args
-        );
-    }
-
-    // }}}
-    // {{{ sendCommand()
-
-    /**
-     * Sends a command to the GPG subprocess over the command file-descriptor
-     * pipe
-     *
-     * @param string $command the command to send.
-     *
-     * @return void
-     *
-     * @sensitive $command
-     */
-    public function sendCommand($command)
-    {
-        if (array_key_exists(self::FD_COMMAND, $this->_openPipes)) {
-            $this->_commandBuffer .= $command . PHP_EOL;
-        }
-    }
-
-    // }}}
-    // {{{ reset()
-
-    /**
-     * Resets the GPG engine, preparing it for a new operation
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::run()
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    public function reset()
-    {
-        $this->_operation      = '';
-        $this->_arguments      = array();
-        $this->_input          = null;
-        $this->_message        = null;
-        $this->_output         = '';
-        $this->_commandBuffer  = '';
-
-        $this->_statusHandlers = array();
-        $this->_errorHandlers  = array();
-
-        if ($this->_debug) {
-            $this->addStatusHandler(array($this, '_handleDebugStatus'));
-            $this->addErrorHandler(array($this, '_handleDebugError'));
-        }
-
-        $this->_processHandler = new Crypt_GPG_ProcessHandler($this);
-
-        $this->addStatusHandler(array($this->_processHandler, 'handleStatus'));
-        $this->addErrorHandler(array($this->_processHandler, 'handleError'));
-    }
-
-    // }}}
-    // {{{ run()
-
-    /**
-     * Runs the current GPG operation.
-     *
-     * This creates and manages the GPG subprocess.
-     * This will close input/output file handles.
-     *
-     * The operation must be set with {@link Crypt_GPG_Engine::setOperation()}
-     * before this method is called.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_InvalidOperationException if no operation is specified.
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *
-     * @see Crypt_GPG_Engine::reset()
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    public function run()
-    {
-        if ($this->_operation === '') {
-            throw new Crypt_GPG_InvalidOperationException(
-                'No GPG operation specified. Use Crypt_GPG_Engine::setOperation() ' .
-                'before calling Crypt_GPG_Engine::run().'
-            );
-        }
-
-        $this->_openSubprocess();
-        $this->_process();
-        $this->_closeSubprocess();
-    }
-
-    // }}}
-    // {{{ setInput()
-
-    /**
-     * Sets the input source for the current GPG operation
-     *
-     * @param string|resource &$input either a reference to the string
-     *                                containing the input data or an open
-     *                                stream resource containing the input
-     *                                data.
-     *
-     * @return void
-     */
-    public function setInput(&$input)
-    {
-        $this->_input =& $input;
-    }
-
-    // }}}
-    // {{{ setMessage()
-
-    /**
-     * Sets the message source for the current GPG operation
-     *
-     * Detached signature data should be specified here.
-     *
-     * @param string|resource &$message either a reference to the string
-     *                                  containing the message data or an open
-     *                                  stream resource containing the message
-     *                                  data.
-     *
-     * @return void
-     */
-    public function setMessage(&$message)
-    {
-        $this->_message =& $message;
-    }
-
-    // }}}
-    // {{{ setOutput()
-
-    /**
-     * Sets the output destination for the current GPG operation
-     *
-     * @param string|resource &$output either a reference to the string in
-     *                                 which to store GPG output or an open
-     *                                 stream resource to which the output data
-     *                                 should be written.
-     *
-     * @return void
-     */
-    public function setOutput(&$output)
-    {
-        $this->_output =& $output;
-    }
-
-    // }}}
-    // {{{ setOperation()
-
-    /**
-     * Sets the operation to perform
-     *
-     * @param string $operation the operation to perform. This should be one
-     *                          of GPG's operations. For example,
-     *                          <kbd>--encrypt</kbd>, <kbd>--decrypt</kbd>,
-     *                          <kbd>--sign</kbd>, etc.
-     * @param array  $arguments optional. Additional arguments for the GPG
-     *                          subprocess. See the GPG manual for specific
-     *                          values.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::reset()
-     * @see Crypt_GPG_Engine::run()
-     */
-    public function setOperation($operation, array $arguments = array())
-    {
-        $this->_operation = $operation;
-        $this->_arguments = $arguments;
-
-        $this->_processHandler->setOperation($operation);
-    }
-
-    // }}}
-    // {{{ setPins()
-
-    /**
-     * Sets the PINENTRY_USER_DATA environment variable with the currently
-     * added keys and passphrases
-     *
-     * Keys and passphrases are stored as an indexed array of passphrases
-     * in JSON encoded to a flat string.
-     *
-     * For GnuPG 2.x this is how passphrases are passed. For GnuPG 1.x the
-     * environment variable is set but not used.
-     *
-     * @param array $keys the internal key array to use.
-     *
-     * @return void
-     */
-    public function setPins(array $keys)
-    {
-        $envKeys = array();
-
-        foreach ($keys as $keyId => $key) {
-            $envKeys[$keyId] = is_array($key) ? $key['passphrase'] : $key;
-        }
-
-        $_ENV['PINENTRY_USER_DATA'] = json_encode($envKeys);
-    }
-
-    // }}}
-    // {{{ getVersion()
-
-    /**
-     * Gets the version of the GnuPG binary
-     *
-     * @return string a version number string containing the version of GnuPG
-     *                being used. This value is suitable to use with PHP's
-     *                version_compare() function.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @throws Crypt_GPG_UnsupportedException if the provided binary is not
-     *         GnuPG or if the GnuPG version is less than 1.0.2.
-     */
-    public function getVersion()
-    {
-        if ($this->_version == '') {
-            $options = array(
-                'homedir' => $this->_homedir,
-                'binary'  => $this->_binary,
-                'debug'   => $this->_debug,
-                'agent'   => $this->_agent,
-            );
-
-            $engine = new self($options);
-            $info   = '';
-
-            // Set a garbage version so we do not end up looking up the version
-            // recursively.
-            $engine->_version = '1.0.0';
-
-            $engine->reset();
-            $engine->setOutput($info);
-            $engine->setOperation('--version');
-            $engine->run();
-
-            $matches    = array();
-            $expression = '#gpg \(GnuPG[A-Za-z0-9/]*?\) (\S+)#';
-
-            if (preg_match($expression, $info, $matches) === 1) {
-                $this->_version = $matches[1];
-            } else {
-                throw new Crypt_GPG_Exception(
-                    'No GnuPG version information provided by the binary "' .
-                    $this->_binary . '". Are you sure it is GnuPG?'
-                );
-            }
-
-            if (version_compare($this->_version, self::MIN_VERSION, 'lt')) {
-                throw new Crypt_GPG_Exception(
-                    'The version of GnuPG being used (' . $this->_version .
-                    ') is not supported by Crypt_GPG. The minimum version ' .
-                    'required by Crypt_GPG is ' . self::MIN_VERSION
-                );
-            }
-        }
-
-
-        return $this->_version;
-    }
-
-    // }}}
-    // {{{ getProcessData()
-
-    /**
-     * Get data from the last process execution.
-     *
-     * @param string $name Data element name (e.g. 'SignatureInfo')
-     *
-     * @return mixed
-     * @see    Crypt_GPG_ProcessHandler::getData()
-     */
-    public function getProcessData($name)
-    {
-        if ($this->_processHandler) {
-            switch ($name) {
-            case 'SignatureInfo':
-                if ($data = $this->_processHandler->getData('SigCreated')) {
-                    return new Crypt_GPG_SignatureCreationInfo($data);
-                }
-                break;
-
-            case 'Signatures':
-                return (array) $this->_processHandler->getData('Signatures');
-
-            default:
-                return $this->_processHandler->getData($name);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ setProcessData()
-
-    /**
-     * Set some data for the process execution.
-     *
-     * @param string $name  Data element name (e.g. 'Handle')
-     * @param mixed  $value Data value
-     *
-     * @return void
-     */
-    public function setProcessData($name, $value)
-    {
-        if ($this->_processHandler) {
-            $this->_processHandler->setData($name, $value);
-        }
-    }
-
-    // }}}
-    // {{{ _handleDebugStatus()
-
-    /**
-     * Displays debug output for status lines
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    private function _handleDebugStatus($line)
-    {
-        $this->_debug('STATUS: ' . $line);
-    }
-
-    // }}}
-    // {{{ _handleDebugError()
-
-    /**
-     * Displays debug output for error lines
-     *
-     * @param string $line the error line to handle.
-     *
-     * @return void
-     */
-    private function _handleDebugError($line)
-    {
-        $this->_debug('ERROR: ' . $line);
-    }
-
-    // }}}
-    // {{{ _process()
-
-    /**
-     * Performs internal streaming operations for the subprocess using either
-     * strings or streams as input / output points
-     *
-     * This is the main I/O loop for streaming to and from the GPG subprocess.
-     *
-     * The implementation of this method is verbose mainly for performance
-     * reasons. Adding streams to a lookup array and looping the array inside
-     * the main I/O loop would be siginficantly slower for large streams.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_Exception if there is an error selecting streams for
-     *         reading or writing. If this occurs, please file a bug report at
-     *         http://pear.php.net/bugs/report.php?package=Crypt_GPG.
-     */
-    private function _process()
-    {
-        $this->_debug('BEGIN PROCESSING');
-
-        $this->_commandBuffer = '';    // buffers input to GPG
-        $messageBuffer        = '';    // buffers input to GPG
-        $inputBuffer          = '';    // buffers input to GPG
-        $outputBuffer         = '';    // buffers output from GPG
-        $statusBuffer         = '';    // buffers output from GPG
-        $errorBuffer          = '';    // buffers output from GPG
-        $inputComplete        = false; // input stream is completely buffered
-        $messageComplete      = false; // message stream is completely buffered
-
-        if (is_string($this->_input)) {
-            $inputBuffer   = $this->_input;
-            $inputComplete = true;
-        }
-
-        if (is_string($this->_message)) {
-            $messageBuffer   = $this->_message;
-            $messageComplete = true;
-        }
-
-        if (is_string($this->_output)) {
-            $outputBuffer =& $this->_output;
-        }
-
-        // convenience variables
-        $fdInput   = $this->_pipes[self::FD_INPUT];
-        $fdOutput  = $this->_pipes[self::FD_OUTPUT];
-        $fdError   = $this->_pipes[self::FD_ERROR];
-        $fdStatus  = $this->_pipes[self::FD_STATUS];
-        $fdCommand = $this->_pipes[self::FD_COMMAND];
-        $fdMessage = $this->_pipes[self::FD_MESSAGE];
-
-        // select loop delay in milliseconds
-        $delay         = 0;
-        $inputPosition = 0;
-        $eolLength     = mb_strlen(PHP_EOL, '8bit');
-
-        while (true) {
-            $inputStreams     = array();
-            $outputStreams    = array();
-            $exceptionStreams = array();
-
-            // set up input streams
-            if (is_resource($this->_input) && !$inputComplete) {
-                if (feof($this->_input)) {
-                    $inputComplete = true;
-                } else {
-                    $inputStreams[] = $this->_input;
-                }
-            }
-
-            // close GPG input pipe if there is no more data
-            if ($inputBuffer == '' && $inputComplete) {
-                $this->_debug('=> closing GPG input pipe');
-                $this->_closePipe(self::FD_INPUT);
-            }
-
-            if (is_resource($this->_message) && !$messageComplete) {
-                if (feof($this->_message)) {
-                    $messageComplete = true;
-                } else {
-                    $inputStreams[] = $this->_message;
-                }
-            }
-
-            // close GPG message pipe if there is no more data
-            if ($messageBuffer == '' && $messageComplete) {
-                $this->_debug('=> closing GPG message pipe');
-                $this->_closePipe(self::FD_MESSAGE);
-            }
-
-            if (!feof($fdOutput)) {
-                $inputStreams[] = $fdOutput;
-            }
-
-            if (!feof($fdStatus)) {
-                $inputStreams[] = $fdStatus;
-            }
-
-            if (!feof($fdError)) {
-                $inputStreams[] = $fdError;
-            }
-
-            // set up output streams
-            if ($outputBuffer != '' && is_resource($this->_output)) {
-                $outputStreams[] = $this->_output;
-            }
-
-            if ($this->_commandBuffer != '' && is_resource($fdCommand)) {
-                $outputStreams[] = $fdCommand;
-            }
-
-            if ($messageBuffer != '' && is_resource($fdMessage)) {
-                $outputStreams[] = $fdMessage;
-            }
-
-            if ($inputBuffer != '' && is_resource($fdInput)) {
-                $outputStreams[] = $fdInput;
-            }
-
-            // no streams left to read or write, we're all done
-            if (count($inputStreams) === 0 && count($outputStreams) === 0) {
-                break;
-            }
-
-            $this->_debug('selecting streams');
-
-            $ready = stream_select(
-                $inputStreams,
-                $outputStreams,
-                $exceptionStreams,
-                null
-            );
-
-            $this->_debug('=> got ' . $ready);
-
-            if ($ready === false) {
-                throw new Crypt_GPG_Exception(
-                    'Error selecting stream for communication with GPG ' .
-                    'subprocess. Please file a bug report at: ' .
-                    'http://pear.php.net/bugs/report.php?package=Crypt_GPG'
-                );
-            }
-
-            if ($ready === 0) {
-                throw new Crypt_GPG_Exception(
-                    'stream_select() returned 0. This can not happen! Please ' .
-                    'file a bug report at: ' .
-                    'http://pear.php.net/bugs/report.php?package=Crypt_GPG'
-                );
-            }
-
-            // write input (to GPG)
-            if (in_array($fdInput, $outputStreams, true)) {
-                $this->_debug('GPG is ready for input');
-
-                $chunk  = mb_substr($inputBuffer, $inputPosition, self::CHUNK_SIZE, '8bit');
-                $length = mb_strlen($chunk, '8bit');
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG input'
-                );
-
-                $length = fwrite($fdInput, $chunk, $length);
-                if ($length === 0) {
-                    // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since
-                    // the pipe was seleted for writing, we assume it was EPIPE.
-                    // There's no way to get the actual error code in PHP. See
-                    // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598
-                    $this->_debug('=> broken pipe on GPG input');
-                    $this->_debug('=> closing pipe GPG input');
-                    $this->_closePipe(self::FD_INPUT);
-                } else {
-                    $this->_debug('=> wrote ' . $length . ' bytes');
-                    // Move the position pointer, don't modify $inputBuffer (#21081)
-                    if (is_string($this->_input)) {
-                        $inputPosition += $length;
-                    } else {
-                        $inputPosition = 0;
-                        $inputBuffer   = mb_substr($inputBuffer, $length, null, '8bit');
-                    }
-                }
-            }
-
-            // read input (from PHP stream)
-            // If the buffer is too big wait until it's smaller, we don't want
-            // to use too much memory
-            if (in_array($this->_input, $inputStreams, true)
-                && mb_strlen($inputBuffer, '8bit') < self::CHUNK_SIZE
-            ) {
-                $this->_debug('input stream is ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from input stream'
-                );
-
-                $chunk        = fread($this->_input, self::CHUNK_SIZE);
-                $length       = mb_strlen($chunk, '8bit');
-                $inputBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // write message (to GPG)
-            if (in_array($fdMessage, $outputStreams, true)) {
-                $this->_debug('GPG is ready for message data');
-
-                $chunk  = mb_substr($messageBuffer, 0, self::CHUNK_SIZE, '8bit');
-                $length = mb_strlen($chunk, '8bit');
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG message'
-                );
-
-                $length = fwrite($fdMessage, $chunk, $length);
-                if ($length === 0) {
-                    // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since
-                    // the pipe was seleted for writing, we assume it was EPIPE.
-                    // There's no way to get the actual error code in PHP. See
-                    // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598
-                    $this->_debug('=> broken pipe on GPG message');
-                    $this->_debug('=> closing pipe GPG message');
-                    $this->_closePipe(self::FD_MESSAGE);
-                } else {
-                    $this->_debug('=> wrote ' . $length . ' bytes');
-                    $messageBuffer = mb_substr($messageBuffer, $length, null, '8bit');
-                }
-            }
-
-            // read message (from PHP stream)
-            if (in_array($this->_message, $inputStreams, true)) {
-                $this->_debug('message stream is ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from message stream'
-                );
-
-                $chunk          = fread($this->_message, self::CHUNK_SIZE);
-                $length         = mb_strlen($chunk, '8bit');
-                $messageBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // read output (from GPG)
-            if (in_array($fdOutput, $inputStreams, true)) {
-                $this->_debug('GPG output stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG output'
-                );
-
-                $chunk         = fread($fdOutput, self::CHUNK_SIZE);
-                $length        = mb_strlen($chunk, '8bit');
-                $outputBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // write output (to PHP stream)
-            if (in_array($this->_output, $outputStreams, true)) {
-                $this->_debug('output stream is ready for data');
-
-                $chunk  = mb_substr($outputBuffer, 0, self::CHUNK_SIZE, '8bit');
-                $length = mb_strlen($chunk, '8bit');
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to output stream'
-                );
-
-                $length       = fwrite($this->_output, $chunk, $length);
-                $outputBuffer = mb_substr($outputBuffer, $length, null, '8bit');
-
-                $this->_debug('=> wrote ' . $length . ' bytes');
-            }
-
-            // read error (from GPG)
-            if (in_array($fdError, $inputStreams, true)) {
-                $this->_debug('GPG error stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG error'
-                );
-
-                $chunk        = fread($fdError, self::CHUNK_SIZE);
-                $length       = mb_strlen($chunk, '8bit');
-                $errorBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-
-                // pass lines to error handlers
-                while (($pos = strpos($errorBuffer, PHP_EOL)) !== false) {
-                    $line = mb_substr($errorBuffer, 0, $pos, '8bit');
-                    foreach ($this->_errorHandlers as $handler) {
-                        array_unshift($handler['args'], $line);
-                        call_user_func_array(
-                            $handler['callback'],
-                            $handler['args']
-                        );
-
-                        array_shift($handler['args']);
-                    }
-
-                    $errorBuffer = mb_substr($errorBuffer, $pos + $eolLength, null, '8bit');
-                }
-            }
-
-            // read status (from GPG)
-            if (in_array($fdStatus, $inputStreams, true)) {
-                $this->_debug('GPG status stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG status'
-                );
-
-                $chunk         = fread($fdStatus, self::CHUNK_SIZE);
-                $length        = mb_strlen($chunk, '8bit');
-                $statusBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-
-                // pass lines to status handlers
-                while (($pos = strpos($statusBuffer, PHP_EOL)) !== false) {
-                    $line = mb_substr($statusBuffer, 0, $pos, '8bit');
-                    // only pass lines beginning with magic prefix
-                    if (mb_substr($line, 0, 9, '8bit') == '[GNUPG:] ') {
-                        $line = mb_substr($line, 9, null, '8bit');
-                        foreach ($this->_statusHandlers as $handler) {
-                            array_unshift($handler['args'], $line);
-                            call_user_func_array(
-                                $handler['callback'],
-                                $handler['args']
-                            );
-
-                            array_shift($handler['args']);
-                        }
-                    }
-
-                    $statusBuffer = mb_substr($statusBuffer, $pos + $eolLength, null, '8bit');
-                }
-            }
-
-            // write command (to GPG)
-            if (in_array($fdCommand, $outputStreams, true)) {
-                $this->_debug('GPG is ready for command data');
-
-                // send commands
-                $chunk  = mb_substr($this->_commandBuffer, 0, self::CHUNK_SIZE, '8bit');
-                $length = mb_strlen($chunk, '8bit');
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG command'
-                );
-
-                $length = fwrite($fdCommand, $chunk, $length);
-                if ($length === 0) {
-                    // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since
-                    // the pipe was seleted for writing, we assume it was EPIPE.
-                    // There's no way to get the actual error code in PHP. See
-                    // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598
-                    $this->_debug('=> broken pipe on GPG command');
-                    $this->_debug('=> closing pipe GPG command');
-                    $this->_closePipe(self::FD_COMMAND);
-                } else {
-                    $this->_debug('=> wrote ' . $length);
-                    $this->_commandBuffer = mb_substr($this->_commandBuffer, $length, null, '8bit');
-                }
-            }
-
-            if (count($outputStreams) === 0 || count($inputStreams) === 0) {
-                // we have an I/O imbalance, increase the select loop delay
-                // to smooth things out
-                $delay += 10;
-            } else {
-                // things are running smoothly, decrease the delay
-                $delay -= 8;
-                $delay = max(0, $delay);
-            }
-
-            if ($delay > 0) {
-                usleep($delay);
-            }
-
-        } // end loop while streams are open
-
-        $this->_debug('END PROCESSING');
-    }
-
-    // }}}
-    // {{{ _openSubprocess()
-
-    /**
-     * Opens an internal GPG subprocess for the current operation
-     *
-     * Opens a GPG subprocess, then connects the subprocess to some pipes. Sets
-     * the private class property {@link Crypt_GPG_Engine::$_process} to
-     * the new subprocess.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_OpenSubprocessException if the subprocess could not be
-     *         opened.
-     *
-     * @see Crypt_GPG_Engine::setOperation()
-     * @see Crypt_GPG_Engine::_closeSubprocess()
-     * @see Crypt_GPG_Engine::$_process
-     */
-    private function _openSubprocess()
-    {
-        $version = $this->getVersion();
-
-        // log versions, but not when looking for the version number
-        if ($version !== '1.0.0') {
-            $this->_debug('USING GPG ' . $version . ' with PHP ' . PHP_VERSION);
-        }
-
-        // Binary operations will not work on Windows with PHP < 5.2.6. This is
-        // in case stream_select() ever works on Windows.
-        $rb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'r' : 'rb';
-        $wb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'w' : 'wb';
-
-        $env = $_ENV;
-
-        // Newer versions of GnuPG return localized results. Crypt_GPG only
-        // works with English, so set the locale to 'C' for the subprocess.
-        $env['LC_ALL'] = 'C';
-
-        // If using GnuPG 2.x < 2.1.13 start the gpg-agent
-        if (version_compare($version, '2.0.0', 'ge')
-            && version_compare($version, '2.1.13', 'lt')
-        ) {
-            if (!$this->_agent) {
-                throw new Crypt_GPG_OpenSubprocessException(
-                    'Unable to open gpg-agent subprocess (gpg-agent not found). ' .
-                    'Please specify location of the gpg-agent binary ' .
-                    'using the \'agent\' driver option.'
-                );
-            }
-
-            $agentArguments = array(
-                '--daemon',
-                '--options /dev/null', // ignore any saved options
-                '--csh', // output is easier to parse
-                '--keep-display', // prevent passing --display to pinentry
-                '--no-grab',
-                '--ignore-cache-for-signing',
-                '--pinentry-touch-file /dev/null',
-                '--disable-scdaemon',
-                '--no-use-standard-socket',
-                '--pinentry-program ' . escapeshellarg($this->_getPinEntry())
-            );
-
-            if ($this->_homedir) {
-                $agentArguments[] = '--homedir ' .
-                    escapeshellarg($this->_homedir);
-            }
-
-            if ($version21 = version_compare($version, '2.1.0', 'ge')) {
-                // This is needed to get socket file location in stderr output
-                // Note: This does not help when the agent already is running
-                $agentArguments[] = '--verbose';
-            }
-
-            $agentCommandLine = $this->_agent . ' ' . implode(' ', $agentArguments);
-
-            $agentDescriptorSpec = array(
-                self::FD_INPUT   => array('pipe', $rb), // stdin
-                self::FD_OUTPUT  => array('pipe', $wb), // stdout
-                self::FD_ERROR   => array('pipe', $wb)  // stderr
-            );
-
-            $this->_debug('OPENING GPG-AGENT SUBPROCESS WITH THE FOLLOWING COMMAND:');
-            $this->_debug($agentCommandLine);
-
-            $this->_agentProcess = proc_open(
-                $agentCommandLine,
-                $agentDescriptorSpec,
-                $this->_agentPipes,
-                null,
-                $env,
-                array('binary_pipes' => true)
-            );
-
-            if (!is_resource($this->_agentProcess)) {
-                throw new Crypt_GPG_OpenSubprocessException(
-                    'Unable to open gpg-agent subprocess.',
-                    0,
-                    $agentCommandLine
-                );
-            }
-
-            // Get GPG_AGENT_INFO and set environment variable for gpg process.
-            // This is a blocking read, but is only 1 line.
-            $agentInfo = fread($this->_agentPipes[self::FD_OUTPUT], self::CHUNK_SIZE);
-
-            // For GnuPG 2.1 we need to read both stderr and stdout
-            if ($version21) {
-                $agentInfo .= "\n" . fread($this->_agentPipes[self::FD_ERROR], self::CHUNK_SIZE);
-            }
-
-            if ($agentInfo) {
-                foreach (explode("\n", $agentInfo) as $line) {
-                    if ($version21) {
-                        if (preg_match('/listening on socket \'([^\']+)/', $line, $m)) {
-                            $this->_agentInfo = $m[1];
-                        } else if (preg_match('/gpg-agent\[([0-9]+)\].* started/', $line, $m)) {
-                            $this->_agentInfo .= ':' . $m[1] . ':1';
-                        }
-                    } else if (preg_match('/GPG_AGENT_INFO[=\s]([^;]+)/', $line, $m)) {
-                        $this->_agentInfo = $m[1];
-                        break;
-                    }
-                }
-            }
-
-            $this->_debug('GPG-AGENT-INFO: ' . $this->_agentInfo);
-
-            $env['GPG_AGENT_INFO'] = $this->_agentInfo;
-
-            // gpg-agent daemon is started, we can close the launching process
-            $this->_closeAgentLaunchProcess();
-
-            // Terminate processes if something went wrong
-            register_shutdown_function(array($this, '__destruct'));
-        }
-
-        // "Register" GPGConf existence for _closeIdleAgents()
-        if (version_compare($version, '2.1.0', 'ge')) {
-            if ($this->_gpgconf === null) {
-                $this->_gpgconf = $this->_getGPGConf();
-            }
-        } else {
-            $this->_gpgconf = false;
-        }
-
-        $commandLine = $this->_binary;
-
-        $defaultArguments = array(
-            '--status-fd ' . escapeshellarg(self::FD_STATUS),
-            '--command-fd ' . escapeshellarg(self::FD_COMMAND),
-            '--no-secmem-warning',
-            '--no-tty',
-            '--no-default-keyring', // ignored if keying files are not specified
-            '--no-options'          // prevent creation of ~/.gnupg directory
-        );
-
-        if (version_compare($version, '1.0.7', 'ge')) {
-            if (version_compare($version, '2.0.0', 'lt')) {
-                $defaultArguments[] = '--no-use-agent';
-            }
-            $defaultArguments[] = '--no-permission-warning';
-        }
-
-        if (version_compare($version, '1.4.2', 'ge')) {
-            $defaultArguments[] = '--exit-on-status-write-error';
-        }
-
-        if (version_compare($version, '1.3.2', 'ge')) {
-            $defaultArguments[] = '--trust-model always';
-        } else {
-            $defaultArguments[] = '--always-trust';
-        }
-
-        // Since 2.1.13 we can use "loopback mode" instead of gpg-agent
-        if (version_compare($version, '2.1.13', 'ge')) {
-            $defaultArguments[] = '--pinentry-mode loopback';
-        }
-
-        if (!$this->_strict) {
-            $defaultArguments[] = '--ignore-time-conflict';
-            $defaultArguments[] = '--ignore-valid-from';
-        }
-
-        if (!empty($this->_digest_algo)) {
-            $defaultArguments[] = '--digest-algo ' . escapeshellarg($this->_digest_algo);
-            $defaultArguments[] = '--s2k-digest-algo ' . escapeshellarg($this->_digest_algo);
-        }
-
-        if (!empty($this->_cipher_algo)) {
-            $defaultArguments[] = '--cipher-algo ' . escapeshellarg($this->_cipher_algo);
-            $defaultArguments[] = '--s2k-cipher-algo ' . escapeshellarg($this->_cipher_algo);
-        }
-
-        $arguments = array_merge($defaultArguments, $this->_arguments);
-
-        if ($this->_homedir) {
-            $arguments[] = '--homedir ' . escapeshellarg($this->_homedir);
-
-            // the random seed file makes subsequent actions faster so only
-            // disable it if we have to.
-            if (!is_writeable($this->_homedir)) {
-                $arguments[] = '--no-random-seed-file';
-            }
-        }
-
-        if ($this->_publicKeyring) {
-            $arguments[] = '--keyring ' . escapeshellarg($this->_publicKeyring);
-        }
-
-        if ($this->_privateKeyring) {
-            $arguments[] = '--secret-keyring ' .
-                escapeshellarg($this->_privateKeyring);
-        }
-
-        if ($this->_trustDb) {
-            $arguments[] = '--trustdb-name ' . escapeshellarg($this->_trustDb);
-        }
-
-        $commandLine .= ' ' . implode(' ', $arguments) . ' ' .
-            $this->_operation;
-
-        $descriptorSpec = array(
-            self::FD_INPUT   => array('pipe', $rb), // stdin
-            self::FD_OUTPUT  => array('pipe', $wb), // stdout
-            self::FD_ERROR   => array('pipe', $wb), // stderr
-            self::FD_STATUS  => array('pipe', $wb), // status
-            self::FD_COMMAND => array('pipe', $rb), // command
-            self::FD_MESSAGE => array('pipe', $rb)  // message
-        );
-
-        $this->_debug('OPENING GPG SUBPROCESS WITH THE FOLLOWING COMMAND:');
-        $this->_debug($commandLine);
-
-        $this->_process = proc_open(
-            $commandLine,
-            $descriptorSpec,
-            $this->_pipes,
-            null,
-            $env,
-            array('binary_pipes' => true)
-        );
-
-        if (!is_resource($this->_process)) {
-            throw new Crypt_GPG_OpenSubprocessException(
-                'Unable to open GPG subprocess.', 0, $commandLine
-            );
-        }
-
-        // Set streams as non-blocking. See Bug #18618.
-        foreach ($this->_pipes as $pipe) {
-            stream_set_blocking($pipe, 0);
-            stream_set_write_buffer($pipe, self::CHUNK_SIZE);
-            stream_set_chunk_size($pipe, self::CHUNK_SIZE);
-            stream_set_read_buffer($pipe, self::CHUNK_SIZE);
-        }
-
-        $this->_openPipes = $this->_pipes;
-    }
-
-    // }}}
-    // {{{ _closeSubprocess()
-
-    /**
-     * Closes the internal GPG subprocess
-     *
-     * Closes the internal GPG subprocess. Sets the private class property
-     * {@link Crypt_GPG_Engine::$_process} to null.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::_openSubprocess()
-     * @see Crypt_GPG_Engine::$_process
-     */
-    private function _closeSubprocess()
-    {
-        // clear PINs from environment if they were set
-        $_ENV['PINENTRY_USER_DATA'] = null;
-
-        if (is_resource($this->_process)) {
-            $this->_debug('CLOSING GPG SUBPROCESS');
-
-            // close remaining open pipes
-            foreach (array_keys($this->_openPipes) as $pipeNumber) {
-                $this->_closePipe($pipeNumber);
-            }
-
-            $status   = proc_get_status($this->_process);
-            $exitCode = proc_close($this->_process);
-
-            // proc_close() can return -1 in some cases,
-            // get the real exit code from the process status
-            if ($exitCode < 0 && $status && !$status['running']) {
-                $exitCode = $status['exitcode'];
-            }
-
-            if ($exitCode > 0) {
-                $this->_debug(
-                    '=> subprocess returned an unexpected exit code: ' .
-                    $exitCode
-                );
-            }
-
-            $this->_process = null;
-            $this->_pipes   = array();
-
-            // close file handles before throwing an exception
-            if (is_resource($this->_input)) {
-                fclose($this->_input);
-            }
-
-            if (is_resource($this->_output)) {
-                fclose($this->_output);
-            }
-
-            $this->_processHandler->throwException($exitCode);
-        }
-
-        $this->_closeAgentLaunchProcess();
-
-        if ($this->_agentInfo !== null) {
-            $parts = explode(':', $this->_agentInfo, 3);
-
-            if (!empty($parts[1])) {
-                $this->_debug('STOPPING GPG-AGENT DAEMON');
-
-                $process = new Crypt_GPG_ProcessControl($parts[1]);
-
-                // terminate agent daemon
-                $process->terminate();
-
-                while ($process->isRunning()) {
-                    usleep(10000); // 10 ms
-                    $process->terminate();
-                }
-
-                $this->_debug('GPG-AGENT DAEMON STOPPED');
-            }
-
-            $this->_agentInfo = null;
-        }
-    }
-
-    // }}}
-    // {{{ _closeAgentLaunchProcess()
-
-    /**
-     * Closes a the internal GPG-AGENT subprocess
-     *
-     * Closes the internal GPG-AGENT subprocess. Sets the private class property
-     * {@link Crypt_GPG_Engine::$_agentProcess} to null.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::_openSubprocess()
-     * @see Crypt_GPG_Engine::$_agentProcess
-     */
-    private function _closeAgentLaunchProcess()
-    {
-        if (is_resource($this->_agentProcess)) {
-            $this->_debug('CLOSING GPG-AGENT LAUNCH PROCESS');
-
-            // close agent pipes
-            foreach ($this->_agentPipes as $pipe) {
-                fflush($pipe);
-                fclose($pipe);
-            }
-
-            // close agent launching process
-            proc_close($this->_agentProcess);
-
-            $this->_agentProcess = null;
-            $this->_agentPipes   = array();
-
-            $this->_debug('GPG-AGENT LAUNCH PROCESS CLOSED');
-        }
-    }
-
-    // }}}
-    // {{{ _closePipe()
-
-    /**
-     * Closes an opened pipe used to communicate with the GPG subprocess
-     *
-     * If the pipe is already closed, it is ignored. If the pipe is open, it
-     * is flushed and then closed.
-     *
-     * @param integer $pipeNumber the file descriptor number of the pipe to
-     *                            close.
-     *
-     * @return void
-     */
-    private function _closePipe($pipeNumber)
-    {
-        $pipeNumber = intval($pipeNumber);
-        if (array_key_exists($pipeNumber, $this->_openPipes)) {
-            fflush($this->_openPipes[$pipeNumber]);
-            fclose($this->_openPipes[$pipeNumber]);
-            unset($this->_openPipes[$pipeNumber]);
-        }
-    }
-
-    // }}}
-    // {{{ _closeIdleAgents()
-
-    /**
-     * Forces automatically started gpg-agent process to cleanup and exit
-     * within a minute.
-     *
-     * This is needed in GnuPG 2.1 where agents are started
-     * automatically by gpg process, not our code.
-     *
-     * @return void
-     */
-    private function _closeIdleAgents()
-    {
-        if ($this->_gpgconf) {
-            // before 2.1.13 --homedir wasn't supported, use env variable
-            $env = array('GNUPGHOME' => $this->_homedir);
-            $cmd = $this->_gpgconf . ' --kill gpg-agent';
-
-            if ($process = proc_open($cmd, array(), $pipes, null, $env)) {
-                proc_close($process);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ _getBinary()
-
-    /**
-     * Gets the name of the GPG binary for the current operating system
-     *
-     * This method is called if the '<kbd>binary</kbd>' option is <i>not</i>
-     * specified when creating this driver.
-     *
-     * @return string the name of the GPG binary for the current operating
-     *                system. If no suitable binary could be found, an empty
-     *                string is returned.
-     */
-    private function _getBinary()
-    {
-        if ($binary = $this->_findBinary('gpg')) {
-            return $binary;
-        }
-
-        return $this->_findBinary('gpg2');
-    }
-
-    // }}}
-    // {{{ _getAgent()
-
-    /**
-     * Gets the name of the GPG-AGENT binary for the current operating system
-     *
-     * @return string the name of the GPG-AGENT binary for the current operating
-     *                system. If no suitable binary could be found, an empty
-     *                string is returned.
-     */
-    private function _getAgent()
-    {
-        return $this->_findBinary('gpg-agent');
-    }
-
-    // }}}
-    // {{{ _getGPGConf()
-
-    /**
-     * Gets the name of the GPGCONF binary for the current operating system
-     *
-     * @return string the name of the GPGCONF binary for the current operating
-     *                system. If no suitable binary could be found, an empty
-     *                string is returned.
-     */
-    private function _getGPGConf()
-    {
-        return $this->_findBinary('gpgconf');
-    }
-
-    // }}}
-    // {{{ _findBinary()
-
-    /**
-     * Gets the location of a binary for the current operating system
-     *
-     * @param string $name Name of a binary program
-     *
-     * @return string The location of the binary for the current operating
-     *                system. If no suitable binary could be found, an empty
-     *                string is returned.
-     */
-    private function _findBinary($name)
-    {
-        $binary = '';
-
-        if ($this->_isDarwin) {
-            $locations = array(
-                '/opt/local/bin/', // MacPorts
-                '/usr/local/bin/', // Mac GPG
-                '/sw/bin/',        // Fink
-                '/usr/bin/'
-            );
-        } else {
-            $locations = array(
-                '/usr/bin/',
-                '/usr/local/bin/'
-            );
-        }
-
-        foreach ($locations as $location) {
-            if (is_executable($location . $name)) {
-                $binary = $location . $name;
-                break;
-            }
-        }
-
-        return $binary;
-    }
-
-    // }}}
-    // {{{ _getPinEntry()
-
-    /**
-     * Gets the location of the PinEntry script
-     *
-     * @return string the location of the PinEntry script.
-     */
-    private function _getPinEntry()
-    {
-        // Find PinEntry program depending on the way how the package is installed
-        $ds    = DIRECTORY_SEPARATOR;
-        $root  = __DIR__ . $ds . '..' . $ds . '..' . $ds;
-        $paths = array(
-            '@bin-dir@', // PEAR
-             $root . 'scripts', // Git
-             $root . 'bin', // Composer
-        );
-
-        foreach ($paths as $path) {
-            if (file_exists($path . $ds . 'crypt-gpg-pinentry')) {
-                return $path . $ds . 'crypt-gpg-pinentry';
-            }
-        }
-    }
-
-    // }}}
-    // {{{ _debug()
-
-    /**
-     * Displays debug text if debugging is turned on
-     *
-     * Debugging text is prepended with a debug identifier and echoed to stdout.
-     *
-     * @param string $text the debugging text to display.
-     *
-     * @return void
-     */
-    private function _debug($text)
-    {
-        if ($this->_debug) {
-            if (php_sapi_name() === 'cli') {
-                foreach (explode(PHP_EOL, $text) as $line) {
-                    echo "Crypt_GPG DEBUG: ", $line, PHP_EOL;
-                }
-            } else if (is_callable($this->_debug)) {
-                call_user_func($this->_debug, $text);
-            } else {
-                // running on a web server, format debug output nicely
-                foreach (explode(PHP_EOL, $text) as $line) {
-                    echo "Crypt_GPG DEBUG: <strong>", htmlspecialchars($line),
-                        '</strong><br />', PHP_EOL;
-                }
-            }
-        }
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/Exceptions.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,597 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Various exception handling classes for Crypt_GPG
- *
- * Crypt_GPG provides an object oriented interface to GNU Privacy
- * Guard (GPG). It requires the GPG executable to be on the system.
- *
- * This file contains various exception classes used by the Crypt_GPG package.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2011 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * PEAR Exception handler and base class
- */
-require_once 'PEAR/Exception.php';
-
-// {{{ class Crypt_GPG_Exception
-
-/**
- * An exception thrown by the Crypt_GPG package
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_Exception extends PEAR_Exception
-{
-}
-
-// }}}
-// {{{ class Crypt_GPG_FileException
-
-/**
- * An exception thrown when a file is used in ways it cannot be used
- *
- * For example, if an output file is specified and the file is not writeable, or
- * if an input file is specified and the file is not readable, this exception
- * is thrown.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2007-2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_FileException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The name of the file that caused this exception
-     *
-     * @var string
-     */
-    private $_filename = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_FileException
-     *
-     * @param string  $message  an error message.
-     * @param integer $code     a user defined error code.
-     * @param string  $filename the name of the file that caused this exception.
-     */
-    public function __construct($message, $code = 0, $filename = '')
-    {
-        $this->_filename = $filename;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getFilename()
-
-    /**
-     * Returns the filename of the file that caused this exception
-     *
-     * @return string the filename of the file that caused this exception.
-     *
-     * @see Crypt_GPG_FileException::$_filename
-     */
-    public function getFilename()
-    {
-        return $this->_filename;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_OpenSubprocessException
-
-/**
- * An exception thrown when the GPG subprocess cannot be opened
- *
- * This exception is thrown when the {@link Crypt_GPG_Engine} tries to open a
- * new subprocess and fails.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_OpenSubprocessException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The command used to try to open the subprocess
-     *
-     * @var string
-     */
-    private $_command = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_OpenSubprocessException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $command the command that was called to open the
-     *                         new subprocess.
-     *
-     * @see Crypt_GPG::_openSubprocess()
-     */
-    public function __construct($message, $code = 0, $command = '')
-    {
-        $this->_command = $command;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getCommand()
-
-    /**
-     * Returns the contents of the internal _command property
-     *
-     * @return string the command used to open the subprocess.
-     *
-     * @see Crypt_GPG_OpenSubprocessException::$_command
-     */
-    public function getCommand()
-    {
-        return $this->_command;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_InvalidOperationException
-
-/**
- * An exception thrown when an invalid GPG operation is attempted
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_InvalidOperationException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The attempted operation
-     *
-     * @var string
-     */
-    private $_operation = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_OpenSubprocessException
-     *
-     * @param string  $message   an error message.
-     * @param integer $code      a user defined error code.
-     * @param string  $operation the operation.
-     */
-    public function __construct($message, $code = 0, $operation = '')
-    {
-        $this->_operation = $operation;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getOperation()
-
-    /**
-     * Returns the contents of the internal _operation property
-     *
-     * @return string the attempted operation.
-     *
-     * @see Crypt_GPG_InvalidOperationException::$_operation
-     */
-    public function getOperation()
-    {
-        return $this->_operation;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_KeyNotFoundException
-
-/**
- * An exception thrown when Crypt_GPG fails to find the key for various
- * operations
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_KeyNotFoundException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The key identifier that was searched for
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_KeyNotFoundException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $keyId   the key identifier of the key.
-     */
-    public function __construct($message, $code = 0, $keyId= '')
-    {
-        $this->_keyId = $keyId;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the key identifier of the key that was not found
-     *
-     * @return string the key identifier of the key that was not found.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_NoDataException
-
-/**
- * An exception thrown when Crypt_GPG cannot find valid data for various
- * operations
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2006 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_NoDataException extends Crypt_GPG_Exception
-{
-}
-
-// }}}
-// {{{ class Crypt_GPG_BadPassphraseException
-
-/**
- * An exception thrown when a required passphrase is incorrect or missing
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2006-2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_BadPassphraseException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * Keys for which the passhprase is missing
-     *
-     * This contains primary user ids indexed by sub-key id.
-     *
-     * @var array
-     */
-    private $_missingPassphrases = array();
-
-    /**
-     * Keys for which the passhprase is incorrect
-     *
-     * This contains primary user ids indexed by sub-key id.
-     *
-     * @var array
-     */
-    private $_badPassphrases = array();
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_BadPassphraseException
-     *
-     * @param string  $message            an error message.
-     * @param integer $code               a user defined error code.
-     * @param array   $badPassphrases     an array containing user ids of keys
-     *                                    for which the passphrase is incorrect.
-     * @param array   $missingPassphrases an array containing user ids of keys
-     *                                    for which the passphrase is missing.
-     */
-    public function __construct($message, $code = 0,
-        array $badPassphrases = array(), array $missingPassphrases = array()
-    ) {
-        $this->_badPassphrases     = (array) $badPassphrases;
-        $this->_missingPassphrases = (array) $missingPassphrases;
-
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getBadPassphrases()
-
-    /**
-     * Gets keys for which the passhprase is incorrect
-     *
-     * @return array an array of keys for which the passphrase is incorrect.
-     *               The array contains primary user ids indexed by the sub-key
-     *               id.
-     */
-    public function getBadPassphrases()
-    {
-        return $this->_badPassphrases;
-    }
-
-    // }}}
-    // {{{ getMissingPassphrases()
-
-    /**
-     * Gets keys for which the passhprase is missing 
-     *
-     * @return array an array of keys for which the passphrase is missing.
-     *               The array contains primary user ids indexed by the sub-key
-     *               id.
-     */
-    public function getMissingPassphrases()
-    {
-        return $this->_missingPassphrases;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_DeletePrivateKeyException
-
-/**
- * An exception thrown when an attempt is made to delete public key that has an
- * associated private key on the keyring
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_DeletePrivateKeyException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The key identifier the deletion attempt was made upon
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_DeletePrivateKeyException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $keyId   the key identifier of the public key that was
-     *                         attempted to delete.
-     *
-     * @see Crypt_GPG::deletePublicKey()
-     */
-    public function __construct($message, $code = 0, $keyId = '')
-    {
-        $this->_keyId = $keyId;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the key identifier of the key that was not found
-     *
-     * @return string the key identifier of the key that was not found.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_KeyNotCreatedException
-
-/**
- * An exception thrown when an attempt is made to generate a key and the
- * attempt fails
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2011 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_KeyNotCreatedException extends Crypt_GPG_Exception
-{
-}
-
-// }}}
-// {{{ class Crypt_GPG_InvalidKeyParamsException
-
-/**
- * An exception thrown when an attempt is made to generate a key and the
- * key parameters set on the key generator are invalid
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2011 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_InvalidKeyParamsException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The key algorithm
-     *
-     * @var integer
-     */
-    private $_algorithm = 0;
-
-    /**
-     * The key size
-     *
-     * @var integer
-     */
-    private $_size = 0;
-
-    /**
-     * The key usage
-     *
-     * @var integer
-     */
-    private $_usage = 0;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_InvalidKeyParamsException
-     *
-     * @param string  $message   an error message.
-     * @param integer $code      a user defined error code.
-     * @param string  $algorithm the key algorithm.
-     * @param string  $size      the key size.
-     * @param string  $usage     the key usage.
-     */
-    public function __construct(
-        $message,
-        $code = 0,
-        $algorithm = 0,
-        $size = 0,
-        $usage = 0
-    ) {
-        parent::__construct($message, $code);
-
-        $this->_algorithm = $algorithm;
-        $this->_size      = $size;
-        $this->_usage     = $usage;
-    }
-
-    // }}}
-    // {{{ getAlgorithm()
-
-    /**
-     * Gets the key algorithm
-     *
-     * @return integer the key algorithm.
-     */
-    public function getAlgorithm()
-    {
-        return $this->_algorithm;
-    }
-
-    // }}}
-    // {{{ getSize()
-
-    /**
-     * Gets the key size
-     *
-     * @return integer the key size.
-     */
-    public function getSize()
-    {
-        return $this->_size;
-    }
-
-    // }}}
-    // {{{ getUsage()
-
-    /**
-     * Gets the key usage
-     *
-     * @return integer the key usage.
-     */
-    public function getUsage()
-    {
-        return $this->_usage;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/Key.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a class representing GPG keys
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * Sub-key class definition
- */
-require_once 'Crypt/GPG/SubKey.php';
-
-/**
- * User id class definition
- */
-require_once 'Crypt/GPG/UserId.php';
-
-// {{{ class Crypt_GPG_Key
-
-/**
- * A data class for GPG key information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- */
-class Crypt_GPG_Key
-{
-    // {{{ class properties
-
-    /**
-     * The user ids associated with this key
-     *
-     * This is an array of {@link Crypt_GPG_UserId} objects.
-     *
-     * @var array
-     *
-     * @see Crypt_GPG_Key::addUserId()
-     * @see Crypt_GPG_Key::getUserIds()
-     */
-    private $_userIds = array();
-
-    /**
-     * The subkeys of this key
-     *
-     * This is an array of {@link Crypt_GPG_SubKey} objects.
-     *
-     * @var array
-     *
-     * @see Crypt_GPG_Key::addSubKey()
-     * @see Crypt_GPG_Key::getSubKeys()
-     */
-    private $_subKeys = array();
-
-    // }}}
-    // {{{ getSubKeys()
-
-    /**
-     * Gets the sub-keys of this key
-     *
-     * @return array the sub-keys of this key.
-     *
-     * @see Crypt_GPG_Key::addSubKey()
-     */
-    public function getSubKeys()
-    {
-        return $this->_subKeys;
-    }
-
-    // }}}
-    // {{{ getUserIds()
-
-    /**
-     * Gets the user ids of this key
-     *
-     * @return array the user ids of this key.
-     *
-     * @see Crypt_GPG_Key::addUserId()
-     */
-    public function getUserIds()
-    {
-        return $this->_userIds;
-    }
-
-    // }}}
-    // {{{ getPrimaryKey()
-
-    /**
-     * Gets the primary sub-key of this key
-     *
-     * The primary key is the first added sub-key.
-     *
-     * @return Crypt_GPG_SubKey the primary sub-key of this key.
-     */
-    public function getPrimaryKey()
-    {
-        $primary_key = null;
-        if (count($this->_subKeys) > 0) {
-            $primary_key = $this->_subKeys[0];
-        }
-        return $primary_key;
-    }
-
-    // }}}
-    // {{{ canSign()
-
-    /**
-     * Gets whether or not this key can sign data
-     *
-     * This key can sign data if any sub-key of this key can sign data.
-     *
-     * @return boolean true if this key can sign data and false if this key
-     *                 cannot sign data.
-     */
-    public function canSign()
-    {
-        $canSign = false;
-        foreach ($this->_subKeys as $subKey) {
-            if ($subKey->canSign()) {
-                $canSign = true;
-                break;
-            }
-        }
-        return $canSign;
-    }
-
-    // }}}
-    // {{{ canEncrypt()
-
-    /**
-     * Gets whether or not this key can encrypt data
-     *
-     * This key can encrypt data if any sub-key of this key can encrypt data.
-     *
-     * @return boolean true if this key can encrypt data and false if this
-     *                 key cannot encrypt data.
-     */
-    public function canEncrypt()
-    {
-        $canEncrypt = false;
-        foreach ($this->_subKeys as $subKey) {
-            if ($subKey->canEncrypt()) {
-                $canEncrypt = true;
-                break;
-            }
-        }
-        return $canEncrypt;
-    }
-
-    // }}}
-    // {{{ addSubKey()
-
-    /**
-     * Adds a sub-key to this key
-     *
-     * The first added sub-key will be the primary key of this key.
-     *
-     * @param Crypt_GPG_SubKey $subKey the sub-key to add.
-     *
-     * @return Crypt_GPG_Key the current object, for fluent interface.
-     */
-    public function addSubKey(Crypt_GPG_SubKey $subKey)
-    {
-        $this->_subKeys[] = $subKey;
-        return $this;
-    }
-
-    // }}}
-    // {{{ addUserId()
-
-    /**
-     * Adds a user id to this key
-     *
-     * @param Crypt_GPG_UserId $userId the user id to add.
-     *
-     * @return Crypt_GPG_Key the current object, for fluent interface.
-     */
-    public function addUserId(Crypt_GPG_UserId $userId)
-    {
-        $this->_userIds[] = $userId;
-        return $this;
-    }
-
-    // }}}
-    // {{{ __toString()
-
-    /**
-     * String representation of the key
-     *
-     * @return string The key ID.
-     */
-    public function __toString()
-    {
-        foreach ($this->_subKeys as $subKey) {
-            if ($id = $subKey->getId()) {
-                return $id;
-            }
-        }
-
-        return '';
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/KeyGenerator.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,683 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains an object that handles GnuPG key generation.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2011-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Base class for GPG methods
- */
-require_once 'Crypt/GPGAbstract.php';
-
-// {{{ class Crypt_GPG_KeyGenerator
-
-/**
- * GnuPG key generator
- *
- * This class provides an object oriented interface for generating keys with
- * the GNU Privacy Guard (GPG).
- *
- * Secure key generation requires true random numbers, and as such can be slow.
- * If the operating system runs out of entropy, key generation will block until
- * more entropy is available.
- *
- * If quick key generation is important, a hardware entropy generator, or an
- * entropy gathering daemon may be installed. For example, administrators of
- * Debian systems may want to install the 'randomsound' package.
- *
- * This class uses the experimental automated key generation support available
- * in GnuPG. See <b>doc/DETAILS</b> in the
- * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
- * information on the key generation format.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_KeyGenerator extends Crypt_GPGAbstract
-{
-    // {{{ protected properties
-
-    /**
-     * The expiration date of generated keys
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setExpirationDate()
-     */
-    protected $expirationDate = 0;
-
-    /**
-     * The passphrase of generated keys
-     *
-     * @var string
-     *
-     * @see Crypt_GPG_KeyGenerator::setPassphrase()
-     */
-    protected $passphrase = '';
-
-    /**
-     * The algorithm for generated primary keys
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setKeyParams()
-     */
-    protected $keyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_DSA;
-
-    /**
-     * The size of generated primary keys
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setKeyParams()
-     */
-    protected $keySize = 1024;
-
-    /**
-     * The usages of generated primary keys
-     *
-     * This is a bitwise combination of the usage constants in
-     * {@link Crypt_GPG_SubKey}.
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setKeyParams()
-     */
-    protected $keyUsage = 6; // USAGE_SIGN | USAGE_CERTIFY
-
-    /**
-     * The algorithm for generated sub-keys
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
-     */
-    protected $subKeyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC;
-
-    /**
-     * The size of generated sub-keys
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
-     */
-    protected $subKeySize = 2048;
-
-    /**
-     * The usages of generated sub-keys
-     *
-     * This is a bitwise combination of the usage constants in
-     * {@link Crypt_GPG_SubKey}.
-     *
-     * @var integer
-     *
-     * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
-     */
-    protected $subKeyUsage = Crypt_GPG_SubKey::USAGE_ENCRYPT;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new GnuPG key generator
-     *
-     * Available options are:
-     *
-     * - <kbd>string  homedir</kbd>        - the directory where the GPG
-     *                                       keyring files are stored. If not
-     *                                       specified, Crypt_GPG uses the
-     *                                       default of <kbd>~/.gnupg</kbd>.
-     * - <kbd>string  publicKeyring</kbd>  - the file path of the public
-     *                                       keyring. Use this if the public
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/pubring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  privateKeyring</kbd> - the file path of the private
-     *                                       keyring. Use this if the private
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/secring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  trustDb</kbd>        - the file path of the web-of-trust
-     *                                       database. Use this if the trust
-     *                                       database is not in the homedir, or
-     *                                       if the database is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       trust database with this option
-     *                                       (/foo/bar/trustdb.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  binary</kbd>         - the location of the GPG binary. If
-     *                                       not specified, the driver attempts
-     *                                       to auto-detect the GPG binary
-     *                                       location using a list of known
-     *                                       default locations for the current
-     *                                       operating system. The option
-     *                                       <kbd>gpgBinary</kbd> is a
-     *                                       deprecated alias for this option.
-     * - <kbd>string  agent</kbd>          - the location of the GnuPG agent
-     *                                       binary. The gpg-agent is only
-     *                                       used for GnuPG 2.x. If not
-     *                                       specified, the engine attempts
-     *                                       to auto-detect the gpg-agent
-     *                                       binary location using a list of
-     *                                       know default locations for the
-     *                                       current operating system.
-     * - <kbd>mixed debug</kbd>            - whether or not to use debug mode.
-     *                                       When debug mode is on, all
-     *                                       communication to and from the GPG
-     *                                       subprocess is logged. This can be
-     *
-     * @param array $options optional. An array of options used to create the
-     *                       GPG object. All options are optional and are
-     *                       represented as key-value pairs.
-     *
-     * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
-     *         and cannot be created. This can happen if <kbd>homedir</kbd> is
-     *         not specified, Crypt_GPG is run as the web user, and the web
-     *         user has no home directory. This exception is also thrown if any
-     *         of the options <kbd>publicKeyring</kbd>,
-     *         <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
-     *         specified but the files do not exist or are are not readable.
-     *         This can happen if the user running the Crypt_GPG process (for
-     *         example, the Apache user) does not have permission to read the
-     *         files.
-     *
-     * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
-     *         if no <kbd>binary</kbd> is provided and no suitable binary could
-     *         be found.
-     *
-     * @throws PEAR_Exception if the provided <kbd>agent</kbd> is invalid, or
-     *         if no <kbd>agent</kbd> is provided and no suitable gpg-agent
-     *         cound be found.
-     */
-    public function __construct(array $options = array())
-    {
-        parent::__construct($options);
-    }
-
-    // }}}
-    // {{{ setExpirationDate()
-
-    /**
-     * Sets the expiration date of generated keys
-     *
-     * @param string|integer $date either a string that may be parsed by
-     *                             PHP's strtotime() function, or an integer
-     *                             timestamp representing the number of seconds
-     *                             since the UNIX epoch. This date must be at
-     *                             least one date in the future. Keys that
-     *                             expire in the past may not be generated. Use
-     *                             an expiration date of 0 for keys that do not
-     *                             expire.
-     *
-     * @throws InvalidArgumentException if the date is not a valid format, or
-     *                                  if the date is not at least one day in
-     *                                  the future, or if the date is greater
-     *                                  than 2038-01-19T03:14:07.
-     *
-     * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
-     */
-    public function setExpirationDate($date)
-    {
-        if (is_int($date) || ctype_digit(strval($date))) {
-            $expirationDate = intval($date);
-        } else {
-            $expirationDate = strtotime($date);
-        }
-
-        if ($expirationDate === false) {
-            throw new InvalidArgumentException(
-                sprintf(
-                    'Invalid expiration date format: "%s". Please use a ' .
-                    'format compatible with PHP\'s strtotime().',
-                    $date
-                )
-            );
-        }
-
-        if ($expirationDate !== 0 && $expirationDate < time() + 86400) {
-            throw new InvalidArgumentException(
-                'Expiration date must be at least a day in the future.'
-            );
-        }
-
-        // GnuPG suffers from the 2038 bug
-        if ($expirationDate > 2147483647) {
-            throw new InvalidArgumentException(
-                'Expiration date must not be greater than 2038-01-19T03:14:07.'
-            );
-        }
-
-        $this->expirationDate = $expirationDate;
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ setPassphrase()
-
-    /**
-     * Sets the passphrase of generated keys
-     *
-     * @param string $passphrase the passphrase to use for generated keys. Use
-     *                           null or an empty string for no passphrase.
-     *
-     * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
-     */
-    public function setPassphrase($passphrase)
-    {
-        $this->passphrase = strval($passphrase);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setKeyParams()
-
-    /**
-     * Sets the parameters for the primary key of generated key-pairs
-     *
-     * @param integer $algorithm the algorithm used by the key. This should be
-     *                           one of the Crypt_GPG_SubKey::ALGORITHM_*
-     *                           constants.
-     * @param integer $size      optional. The size of the key. Different
-     *                           algorithms have different size requirements.
-     *                           If not specified, the default size for the
-     *                           specified algorithm will be used. If an
-     *                           invalid key size is used, GnuPG will do its
-     *                           best to round it to a valid size.
-     * @param integer $usage     optional. A bitwise combination of key usages.
-     *                           If not specified, the primary key will be used
-     *                           only to sign and certify. This is the default
-     *                           behavior of GnuPG in interactive mode. Use
-     *                           the Crypt_GPG_SubKey::USAGE_* constants here.
-     *                           The primary key may be used to certify even
-     *                           if the certify usage is not specified.
-     *
-     * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
-     */
-    public function setKeyParams($algorithm, $size = 0, $usage = 0)
-    {
-        $algorithm = intval($algorithm);
-
-        if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC) {
-            throw new Crypt_GPG_InvalidKeyParamsException(
-                'Primary key algorithm must be capable of signing. The ' .
-                'Elgamal algorithm can only encrypt.',
-                0,
-                $algorithm,
-                $size,
-                $usage
-            );
-        }
-
-        if ($size != 0) {
-            $size = intval($size);
-        }
-
-        if ($usage != 0) {
-            $usage = intval($usage);
-        }
-
-        $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT;
-
-        if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA
-            && ($usage & $usageEncrypt) === $usageEncrypt
-        ) {
-            throw new Crypt_GPG_InvalidKeyParamsException(
-                'The DSA algorithm is not capable of encrypting. Please ' .
-                'specify a different algorithm or do not include encryption ' .
-                'as a usage for the primary key.',
-                0,
-                $algorithm,
-                $size,
-                $usage
-            );
-        }
-
-        $this->keyAlgorithm = $algorithm;
-
-        if ($size != 0) {
-            $this->keySize = $size;
-        }
-
-        if ($usage != 0) {
-            $this->keyUsage = $usage;
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ setSubKeyParams()
-
-    /**
-     * Sets the parameters for the sub-key of generated key-pairs
-     *
-     * @param integer $algorithm the algorithm used by the key. This should be
-     *                           one of the Crypt_GPG_SubKey::ALGORITHM_*
-     *                           constants.
-     * @param integer $size      optional. The size of the key. Different
-     *                           algorithms have different size requirements.
-     *                           If not specified, the default size for the
-     *                           specified algorithm will be used. If an
-     *                           invalid key size is used, GnuPG will do its
-     *                           best to round it to a valid size.
-     * @param integer $usage     optional. A bitwise combination of key usages.
-     *                           If not specified, the sub-key will be used
-     *                           only to encrypt. This is the default behavior
-     *                           of GnuPG in interactive mode. Use the
-     *                           Crypt_GPG_SubKey::USAGE_* constants here.
-     *
-     * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
-     */
-    public function setSubKeyParams($algorithm, $size = '', $usage = 0)
-    {
-        $algorithm = intval($algorithm);
-
-        if ($size != 0) {
-            $size = intval($size);
-        }
-
-        if ($usage != 0) {
-            $usage = intval($usage);
-        }
-
-        $usageSign = Crypt_GPG_SubKey::USAGE_SIGN;
-
-        if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC
-            && ($usage & $usageSign) === $usageSign
-        ) {
-            throw new Crypt_GPG_InvalidKeyParamsException(
-                'The Elgamal algorithm is not capable of signing. Please ' .
-                'specify a different algorithm or do not include signing ' .
-                'as a usage for the sub-key.',
-                0,
-                $algorithm,
-                $size,
-                $usage
-            );
-        }
-
-        $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT;
-
-        if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA
-            && ($usage & $usageEncrypt) === $usageEncrypt
-        ) {
-            throw new Crypt_GPG_InvalidKeyParamsException(
-                'The DSA algorithm is not capable of encrypting. Please ' .
-                'specify a different algorithm or do not include encryption ' .
-                'as a usage for the sub-key.',
-                0,
-                $algorithm,
-                $size,
-                $usage
-            );
-        }
-
-        $this->subKeyAlgorithm = $algorithm;
-
-        if ($size != 0) {
-            $this->subKeySize = $size;
-        }
-
-        if ($usage != 0) {
-            $this->subKeyUsage = $usage;
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ generateKey()
-
-    /**
-     * Generates a new key-pair in the current keyring
-     *
-     * Secure key generation requires true random numbers, and as such can be
-     * solw. If the operating system runs out of entropy, key generation will
-     * block until more entropy is available.
-     *
-     * If quick key generation is important, a hardware entropy generator, or
-     * an entropy gathering daemon may be installed. For example,
-     * administrators of Debian systems may want to install the 'randomsound'
-     * package.
-     *
-     * @param string|Crypt_GPG_UserId $name    either a {@link Crypt_GPG_UserId}
-     *                                         object, or a string containing
-     *                                         the name of the user id.
-     * @param string                  $email   optional. If <i>$name</i> is
-     *                                         specified as a string, this is
-     *                                         the email address of the user id.
-     * @param string                  $comment optional. If <i>$name</i> is
-     *                                         specified as a string, this is
-     *                                         the comment of the user id.
-     *
-     * @return Crypt_GPG_Key the newly generated key.
-     *
-     * @throws Crypt_GPG_KeyNotCreatedException if the key parameters are
-     *         incorrect, if an unknown error occurs during key generation, or
-     *         if the newly generated key is not found in the keyring.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function generateKey($name, $email = '', $comment = '')
-    {
-        $handle = uniqid('key', true);
-
-        $userId = $this->getUserId($name, $email, $comment);
-
-        $keyParams = array(
-            'Key-Type'      => $this->keyAlgorithm,
-            'Key-Length'    => $this->keySize,
-            'Key-Usage'     => $this->getUsage($this->keyUsage),
-            'Subkey-Type'   => $this->subKeyAlgorithm,
-            'Subkey-Length' => $this->subKeySize,
-            'Subkey-Usage'  => $this->getUsage($this->subKeyUsage),
-            'Name-Real'     => $userId->getName(),
-            'Handle'        => $handle,
-        );
-
-        if ($this->expirationDate != 0) {
-            // GnuPG only accepts granularity of days
-            $expirationDate = date('Y-m-d', $this->expirationDate);
-            $keyParams['Expire-Date'] = $expirationDate;
-        }
-
-        if (strlen($this->passphrase)) {
-            $keyParams['Passphrase'] = $this->passphrase;
-        }
-
-        if ($userId->getEmail() != '') {
-            $keyParams['Name-Email'] = $userId->getEmail();
-        }
-
-        if ($userId->getComment() != '') {
-            $keyParams['Name-Comment'] = $userId->getComment();
-        }
-
-        $keyParamsFormatted = array();
-        foreach ($keyParams as $name => $value) {
-            $keyParamsFormatted[] = $name . ': ' . $value;
-        }
-
-        // This is required in GnuPG 2.1
-        if (!strlen($this->passphrase)) {
-            $keyParamsFormatted[] = '%no-protection';
-        }
-
-        $input = implode("\n", $keyParamsFormatted) . "\n%commit\n";
-
-        $this->engine->reset();
-        $this->engine->setProcessData('Handle', $handle);
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--gen-key', array('--batch'));
-
-        try {
-            $this->engine->run();
-        } catch (Crypt_GPG_InvalidKeyParamsException $e) {
-            switch ($this->engine->getProcessData('LineNumber')) {
-            case 1:
-                throw new Crypt_GPG_InvalidKeyParamsException(
-                    'Invalid primary key algorithm specified.',
-                    0,
-                    $this->keyAlgorithm,
-                    $this->keySize,
-                    $this->keyUsage
-                );
-            case 4:
-                throw new Crypt_GPG_InvalidKeyParamsException(
-                    'Invalid sub-key algorithm specified.',
-                    0,
-                    $this->subKeyAlgorithm,
-                    $this->subKeySize,
-                    $this->subKeyUsage
-                );
-            default:
-                throw $e;
-            }
-        }
-
-        $fingerprint = $this->engine->getProcessData('KeyCreated');
-        $keys        = $this->_getKeys($fingerprint);
-
-        if (count($keys) === 0) {
-            throw new Crypt_GPG_KeyNotCreatedException(
-                sprintf(
-                    'Newly created key "%s" not found in keyring.',
-                    $fingerprint
-                )
-            );
-        }
-
-        return $keys[0];
-    }
-
-    // }}}
-    // {{{ getUsage()
-
-    /**
-     * Builds a GnuPG key usage string suitable for key generation
-     *
-     * See <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
-     * information on the key usage format.
-     *
-     * @param integer $usage a bitwise combination of the key usages. This is
-     *                       a combination of the Crypt_GPG_SubKey::USAGE_*
-     *                       constants.
-     *
-     * @return string the key usage string.
-     */
-    protected function getUsage($usage)
-    {
-        $map = array(
-            Crypt_GPG_SubKey::USAGE_ENCRYPT        => 'encrypt',
-            Crypt_GPG_SubKey::USAGE_SIGN           => 'sign',
-            Crypt_GPG_SubKey::USAGE_CERTIFY        => 'cert',
-            Crypt_GPG_SubKey::USAGE_AUTHENTICATION => 'auth',
-        );
-
-        // cert is always used for primary keys and does not need to be
-        // specified
-        $usage &= ~Crypt_GPG_SubKey::USAGE_CERTIFY;
-
-        $usageArray = array();
-
-        foreach ($map as $key => $value) {
-            if (($usage & $key) === $key) {
-                $usageArray[] = $value;
-            }
-        }
-
-        return implode(',', $usageArray);
-    }
-
-    // }}}
-    // {{{ getUserId()
-
-    /**
-     * Gets a user id object from parameters
-     *
-     * @param string|Crypt_GPG_UserId $name    either a {@link Crypt_GPG_UserId}
-     *                                         object, or a string containing
-     *                                         the name of the user id.
-     * @param string                  $email   optional. If <i>$name</i> is
-     *                                         specified as a string, this is
-     *                                         the email address of the user id.
-     * @param string                  $comment optional. If <i>$name</i> is
-     *                                         specified as a string, this is
-     *                                         the comment of the user id.
-     *
-     * @return Crypt_GPG_UserId a user id object for the specified parameters.
-     */
-    protected function getUserId($name, $email = '', $comment = '')
-    {
-        if ($name instanceof Crypt_GPG_UserId) {
-            $userId = $name;
-        } else {
-            $userId = new Crypt_GPG_UserId();
-            $userId->setName($name)->setEmail($email)->setComment($comment);
-        }
-
-        return $userId;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/PinEntry.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,853 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a class implementing automatic pinentry for gpg-agent
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * CLI user-interface and parser.
- */
-require_once 'Console/CommandLine.php';
-
-// {{{ class Crypt_GPG_PinEntry
-
-/**
- * A command-line dummy pinentry program for use with gpg-agent and Crypt_GPG
- *
- * This pinentry receives passphrases through en environment variable and
- * automatically enters the PIN in response to gpg-agent requests. No user-
- * interaction required.
- *
- * The pinentry can be run independently for testing and debugging with the
- * following syntax:
- *
- * <pre>
- * Usage:
- *   crypt-gpg-pinentry [options]
- *
- * Options:
- *   -l log, --log=log  Optional location to log pinentry activity.
- *   -v, --verbose      Sets verbosity level. Use multiples for more detail
- *                      (e.g. "-vv").
- *   -h, --help         show this help message and exit
- *   --version          show the program version and exit
- * </pre>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- */
-class Crypt_GPG_PinEntry
-{
-    // {{{ class constants
-
-    /**
-     * Verbosity level for showing no output.
-     */
-    const VERBOSITY_NONE = 0;
-
-    /**
-     * Verbosity level for showing error output.
-     */
-    const VERBOSITY_ERRORS = 1;
-
-    /**
-     * Verbosity level for showing all output, including Assuan protocol
-     * messages.
-     */
-    const VERBOSITY_ALL = 2;
-
-    /**
-     * Length of buffer for reading lines from the Assuan server.
-     *
-     * PHP reads 8192 bytes. If this is set to less than 8192, PHP reads 8192
-     * and buffers the rest so we might as well just read 8192.
-     *
-     * Using values other than 8192 also triggers PHP bugs.
-     *
-     * @see http://bugs.php.net/bug.php?id=35224
-     */
-    const CHUNK_SIZE = 8192;
-
-    // }}}
-    // {{{ protected properties
-
-    /**
-     * File handle for the input stream
-     *
-     * @var resource
-     */
-    protected $stdin = null;
-
-    /**
-     * File handle for the output stream
-     *
-     * @var resource
-     */
-    protected $stdout = null;
-
-    /**
-     * File handle for the log file if a log file is used
-     *
-     * @var resource
-     */
-    protected $logFile = null;
-
-    /**
-     * Whether or not this pinentry is finished and is exiting
-     *
-     * @var boolean
-     */
-    protected $moribund = false;
-
-    /**
-     * Verbosity level
-     *
-     * One of:
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_NONE},
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_ERRORS}, or
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_ALL}
-     *
-     * @var integer
-     */
-    protected $verbosity = self::VERBOSITY_NONE;
-
-    /**
-     * The command-line interface parser for this pinentry
-     *
-     * @var Console_CommandLine
-     *
-     * @see Crypt_GPG_PinEntry::getParser()
-     */
-    protected $parser = null;
-
-    /**
-     * PINs to be entered by this pinentry
-     *
-     * An indexed array of associative arrays in the form:
-     * <code>
-     * <?php
-     *   array(
-     *     array(
-     *       'keyId'      => $keyId,
-     *       'passphrase' => $passphrase
-     *     ),
-     *     ...
-     *   );
-     * ?>
-     * </code>
-     *
-     * This array is parsed from the environment variable
-     * <kbd>PINENTRY_USER_DATA</kbd>.
-     *
-     * @var array
-     *
-     * @see Crypt_GPG_PinEntry::initPinsFromENV()
-     */
-    protected $pins = array();
-
-    /**
-     * The PIN currently being requested by the Assuan server
-     *
-     * If set, this is an associative array in the form:
-     * <code>
-     * <?php
-     *   array(
-     *     'keyId'  => $shortKeyId,
-     *     'userId' => $userIdString
-     *   );
-     * ?>
-     * </code>
-     *
-     * @var array|null
-     */
-    protected $currentPin = null;
-
-    // }}}
-    // {{{ __invoke()
-
-    /**
-     * Runs this pinentry
-     *
-     * @return void
-     */
-    public function __invoke()
-    {
-        $this->parser = $this->getCommandLineParser();
-
-        try {
-            $result = $this->parser->parse();
-
-            $this->setVerbosity($result->options['verbose']);
-            $this->setLogFilename($result->options['log']);
-
-            $this->connect();
-            $this->initPinsFromENV();
-
-            while (($line = fgets($this->stdin, self::CHUNK_SIZE)) !== false) {
-                $this->parseCommand(mb_substr($line, 0, -1, '8bit'));
-                if ($this->moribund) {
-                    break;
-                }
-            }
-
-            $this->disconnect();
-
-        } catch (Console_CommandLineException $e) {
-            $this->log($e->getMessage() . PHP_EOL, slf::VERBOSITY_ERRORS);
-            exit(1);
-        } catch (Exception $e) {
-            $this->log($e->getMessage() . PHP_EOL, self::VERBOSITY_ERRORS);
-            $this->log($e->getTraceAsString() . PHP_EOL, self::VERBOSITY_ERRORS);
-            exit(1);
-        }
-    }
-
-    // }}}
-    // {{{ setVerbosity()
-
-    /**
-     * Sets the verbosity of logging for this pinentry
-     *
-     * Verbosity levels are:
-     *
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_NONE}   - no logging.
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_ERRORS} - log errors only.
-     * - {@link Crypt_GPG_PinEntry::VERBOSITY_ALL}    - log everything, including
-     *                                                  the assuan protocol.
-     *
-     * @param integer $verbosity the level of verbosity of this pinentry.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    public function setVerbosity($verbosity)
-    {
-        $this->verbosity = (integer)$verbosity;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setLogFilename()
-
-    /**
-     * Sets the log file location
-     *
-     * @param string $filename the new log filename to use. If an empty string
-     *                         is used, file-based logging is disabled.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    public function setLogFilename($filename)
-    {
-        if (is_resource($this->logFile)) {
-            fflush($this->logFile);
-            fclose($this->logFile);
-            $this->logFile = null;
-        }
-
-        if ($filename != '') {
-            if (($this->logFile = fopen($filename, 'w')) === false) {
-                $this->log(
-                    'Unable to open log file "' . $filename . '" '
-                    . 'for writing.' . PHP_EOL,
-                    self::VERBOSITY_ERRORS
-                );
-                exit(1);
-            } else {
-                stream_set_write_buffer($this->logFile, 0);
-            }
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ getUIXML()
-
-    /**
-     * Gets the CLI user-interface definition for this pinentry
-     *
-     * Detects whether or not this package is PEAR-installed and appropriately
-     * locates the XML UI definition.
-     *
-     * @return string the location of the CLI user-interface definition XML.
-     */
-    protected function getUIXML()
-    {
-        // Find PinEntry config depending on the way how the package is installed
-        $ds    = DIRECTORY_SEPARATOR;
-        $root  = __DIR__ . $ds . '..' . $ds . '..' . $ds;
-        $paths = array(
-            '@data-dir@' . $ds . '@package-name@' . $ds . 'data', // PEAR
-            $root . 'data', // Git
-            $root . 'data' . $ds . 'Crypt_GPG' . $ds . 'data', // Composer
-        );
-
-        foreach ($paths as $path) {
-            if (file_exists($path . $ds . 'pinentry-cli.xml')) {
-                return $path . $ds . 'pinentry-cli.xml';
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getCommandLineParser()
-
-    /**
-     * Gets the CLI parser for this pinentry
-     *
-     * @return Console_CommandLine the CLI parser for this pinentry.
-     */
-    protected function getCommandLineParser()
-    {
-        return Console_CommandLine::fromXmlFile($this->getUIXML());
-    }
-
-    // }}}
-    // {{{ log()
-
-    /**
-     * Logs a message at the specified verbosity level
-     *
-     * If a log file is used, the message is written to the log. Otherwise,
-     * the message is sent to STDERR.
-     *
-     * @param string  $data  the message to log.
-     * @param integer $level the verbosity level above which the message should
-     *                       be logged.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function log($data, $level)
-    {
-        if ($this->verbosity >= $level) {
-            if (is_resource($this->logFile)) {
-                fwrite($this->logFile, $data);
-                fflush($this->logFile);
-            } else {
-                $this->parser->outputter->stderr($data);
-            }
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ connect()
-
-    /**
-     * Connects this pinentry to the assuan server
-     *
-     * Opens I/O streams and sends initial handshake.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function connect()
-    {
-        // Binary operations will not work on Windows with PHP < 5.2.6.
-        $rb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'r' : 'rb';
-        $wb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'w' : 'wb';
-
-        $this->stdin  = fopen('php://stdin', $rb);
-        $this->stdout = fopen('php://stdout', $wb);
-
-        if (function_exists('stream_set_read_buffer')) {
-            stream_set_read_buffer($this->stdin, 0);
-        }
-        stream_set_write_buffer($this->stdout, 0);
-
-        // initial handshake
-        $this->send($this->getOK('Crypt_GPG pinentry ready and waiting'));
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ parseCommand()
-
-    /**
-     * Parses an assuan command and performs the appropriate action
-     *
-     * Documentation of the assuan commands for pinentry is limited to
-     * non-existent. Most of these commands were taken from the C source code
-     * to gpg-agent and pinentry.
-     *
-     * Additional context was provided by using strace -f when calling the
-     * gpg-agent.
-     *
-     * @param string $line the assuan command line to parse
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function parseCommand($line)
-    {
-        $this->log('<- ' . $line . PHP_EOL, self::VERBOSITY_ALL);
-
-        $parts = explode(' ', $line, 2);
-
-        $command = $parts[0];
-
-        if (count($parts) === 2) {
-            $data = $parts[1];
-        } else {
-            $data = null;
-        }
-
-        switch ($command) {
-        case 'SETDESC':
-            return $this->sendSetDescription($data);
-
-        case 'MESSAGE':
-            return $this->sendMessage();
-
-        case 'CONFIRM':
-            return $this->sendConfirm();
-
-        case 'GETINFO':
-            return $this->sendGetInfo($data);
-
-        case 'GETPIN':
-            return $this->sendGetPin($data);
-
-        case 'RESET':
-            return $this->sendReset();
-
-        case 'BYE':
-            return $this->sendBye();
-
-        default:
-            return $this->sendNotImplementedOK();
-        }
-    }
-
-    // }}}
-    // {{{ initPinsFromENV()
-
-    /**
-     * Initializes the PINs to be entered by this pinentry from the environment
-     * variable PINENTRY_USER_DATA
-     *
-     * The PINs are parsed from a JSON-encoded string.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function initPinsFromENV()
-    {
-        if (($userData = getenv('PINENTRY_USER_DATA')) !== false) {
-            $pins = json_decode($userData, true);
-            if ($pins === null) {
-                $this->log(
-                    '-- failed to parse user data' . PHP_EOL,
-                    self::VERBOSITY_ERRORS
-                );
-            } else {
-                $this->pins = $pins;
-                $this->log(
-                    '-- got user data [not showing passphrases]' . PHP_EOL,
-                    self::VERBOSITY_ALL
-                );
-            }
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ disconnect()
-
-    /**
-     * Disconnects this pinentry from the Assuan server
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function disconnect()
-    {
-        $this->log('-- disconnecting' . PHP_EOL, self::VERBOSITY_ALL);
-
-        fflush($this->stdout);
-        fclose($this->stdout);
-        fclose($this->stdin);
-
-        $this->stdin  = null;
-        $this->stdout = null;
-
-        $this->log('-- disconnected' . PHP_EOL, self::VERBOSITY_ALL);
-
-        if (is_resource($this->logFile)) {
-            fflush($this->logFile);
-            fclose($this->logFile);
-            $this->logFile = null;
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ sendNotImplementedOK()
-
-    /**
-     * Sends an OK response for a not implemented feature
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendNotImplementedOK()
-    {
-        return $this->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ sendSetDescription()
-
-    /**
-     * Parses the currently requested key identifier and user identifier from
-     * the description passed to this pinentry
-     *
-     * @param string $text the raw description sent from gpg-agent.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendSetDescription($text)
-    {
-        $text = rawurldecode($text);
-        $matches = array();
-        // TODO: handle user id with quotation marks
-        $exp = '/\n"(.+)"\n.*\sID ([A-Z0-9]+),\n/mu';
-        if (preg_match($exp, $text, $matches) === 1) {
-            $userId = $matches[1];
-            $keyId  = $matches[2];
-
-            if ($this->currentPin === null || $this->currentPin['keyId'] !== $keyId) {
-                $this->currentPin = array(
-                    'userId' => $userId,
-                    'keyId'  => $keyId
-                );
-                $this->log(
-                    '-- looking for PIN for ' . $keyId . PHP_EOL,
-                    self::VERBOSITY_ALL
-                );
-            }
-        }
-
-        return $this->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ sendConfirm()
-
-    /**
-     * Tells the assuan server to confirm the operation
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendConfirm()
-    {
-        return $this->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ sendMessage()
-
-    /**
-     * Tells the assuan server that any requested pop-up messages were confirmed
-     * by pressing the fake 'close' button
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendMessage()
-    {
-        return $this->sendButtonInfo('close');
-    }
-
-    // }}}
-    // {{{ sendButtonInfo()
-
-    /**
-     * Sends information about pressed buttons to the assuan server
-     *
-     * This is used to fake a user-interface for this pinentry.
-     *
-     * @param string $text the button status to send.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendButtonInfo($text)
-    {
-        return $this->send('BUTTON_INFO ' . $text . "\n");
-    }
-
-    // }}}
-    // {{{ sendGetPin()
-
-    /**
-     * Sends the PIN value for the currently requested key
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendGetPin()
-    {
-        $foundPin = '';
-
-        if (is_array($this->currentPin)) {
-            $keyIdLength = mb_strlen($this->currentPin['keyId'], '8bit');
-
-            // search for the pin
-            foreach ($this->pins as $_keyId => $pin) {
-                // Warning: GnuPG 2.1 asks 3 times for passphrase if it is invalid
-                $keyId        = $this->currentPin['keyId'];
-                $_keyIdLength = mb_strlen($_keyId, '8bit');
-
-                // Get last X characters of key identifier to compare
-                // Most GnuPG versions use 8 characters, but recent ones can use 16,
-                // We support 8 for backward compatibility
-                if ($keyIdLength < $_keyIdLength) {
-                    $_keyId = mb_substr($_keyId, -$keyIdLength, $keyIdLength, '8bit');
-                } else if ($keyIdLength > $_keyIdLength) {
-                    $keyId = mb_substr($keyId, -$_keyIdLength, $_keyIdLength, '8bit');
-                }
-
-                if ($_keyId === $keyId) {
-                    $foundPin = $pin;
-                    break;
-                }
-            }
-        }
-
-        return $this
-            ->send($this->getData($foundPin))
-            ->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ sendGetInfo()
-
-    /**
-     * Sends information about this pinentry
-     *
-     * @param string $data the information requested by the assuan server.
-     *                     Currently only 'pid' is supported. Other requests
-     *                     return no information.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendGetInfo($data)
-    {
-        $parts   = explode(' ', $data, 2);
-        $command = reset($parts);
-
-        switch ($command) {
-        case 'pid':
-            return $this->sendGetInfoPID();
-        default:
-            return $this->send($this->getOK());
-        }
-
-        return $this;
-    }
-    // }}}
-    // {{{ sendGetInfoPID()
-
-    /**
-     * Sends the PID of this pinentry to the assuan server
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendGetInfoPID()
-    {
-        return $this
-            ->send($this->getData(getmypid()))
-            ->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ sendBye()
-
-    /**
-     * Flags this pinentry for disconnection and sends an OK response
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendBye()
-    {
-        $return = $this->send($this->getOK('closing connection'));
-        $this->moribund = true;
-        return $return;
-    }
-
-    // }}}
-    // {{{ sendReset()
-
-    /**
-     * Resets this pinentry and sends an OK response
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function sendReset()
-    {
-        $this->currentPin = null;
-        return $this->send($this->getOK());
-    }
-
-    // }}}
-    // {{{ getOK()
-
-    /**
-     * Gets an OK response to send to the assuan server
-     *
-     * @param string $data an optional message to include with the OK response.
-     *
-     * @return string the OK response.
-     */
-    protected function getOK($data = null)
-    {
-        $return = 'OK';
-
-        if ($data) {
-            $return .= ' ' . $data;
-        }
-
-        return $return . "\n";
-    }
-
-    // }}}
-    // {{{ getData()
-
-    /**
-     * Gets data ready to send to the assuan server
-     *
-     * Data is appropriately escaped and long lines are wrapped.
-     *
-     * @param string $data the data to send to the assuan server.
-     *
-     * @return string the properly escaped, formatted data.
-     *
-     * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html
-     */
-    protected function getData($data)
-    {
-        // Escape data. Only %, \n and \r need to be escaped but other
-        // values are allowed to be escaped. See
-        // http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html
-        $data = rawurlencode($data);
-        $data = $this->getWordWrappedData($data, 'D');
-        return $data;
-    }
-
-    // }}}
-    // {{{ getComment()
-
-    /**
-     * Gets a comment ready to send to the assuan server
-     *
-     * @param string $data the comment to send to the assuan server.
-     *
-     * @return string the properly formatted comment.
-     *
-     * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html
-     */
-    protected function getComment($data)
-    {
-        return $this->getWordWrappedData($data, '#');
-    }
-
-    // }}}
-    // {{{ getWordWrappedData()
-
-    /**
-     * Wraps strings at 1,000 bytes without splitting UTF-8 multibyte
-     * characters
-     *
-     * Each line is prepended with the specified line prefix. Wrapped lines
-     * are automatically appended with \ characters.
-     *
-     * Protocol strings are UTF-8 but maximum line length is 1,000 bytes.
-     * <kbd>mb_strcut()</kbd> is used so we can limit line length by bytes
-     * and not split characters across multiple lines.
-     *
-     * @param string $data   the data to wrap.
-     * @param string $prefix a single character to use as the line prefix. For
-     *                       example, 'D' or '#'.
-     *
-     * @return string the word-wrapped, prefixed string.
-     *
-     * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html
-     */
-    protected function getWordWrappedData($data, $prefix)
-    {
-        $lines = array();
-
-        do {
-            if (mb_strlen($data, '8bit') > 997) {
-                $line = $prefix . ' ' . mb_strcut($data, 0, 996, 'utf-8') . "\\\n";
-                $lines[] = $line;
-                $lineLength = mb_strlen($line, '8bit') - 1;
-                $dataLength = mb_substr($data, '8bit');
-                $data = mb_substr(
-                    $data,
-                    $lineLength,
-                    $dataLength - $lineLength,
-                    '8bit'
-                );
-            } else {
-                $lines[] = $prefix . ' ' . $data . "\n";
-                $data = '';
-            }
-        } while ($data != '');
-
-        return implode('', $lines);
-    }
-
-    // }}}
-    // {{{ send()
-
-    /**
-     * Sends raw data to the assuan server
-     *
-     * @param string $data the data to send.
-     *
-     * @return Crypt_GPG_PinEntry the current object, for fluent interface.
-     */
-    protected function send($data)
-    {
-        $this->log('-> ' . $data, self::VERBOSITY_ALL);
-        fwrite($this->stdout, $data);
-        fflush($this->stdout);
-        return $this;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/ProcessControl.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A class for monitoring and terminating processes
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-// {{{ class Crypt_GPG_ProcessControl
-
-/**
- * A class for monitoring and terminating processes by PID
- *
- * This is used to safely terminate the gpg-agent for GnuPG 2.x. This class
- * is limited in its abilities and can only check if a PID is running and
- * send a PID SIGTERM.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_ProcessControl
-{
-    // {{{ protected properties
-
-    /**
-     * The PID (process identifier) being monitored
-     *
-     * @var integer
-     */
-    protected $pid;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new process controller from the given PID (process identifier)
-     *
-     * @param integer $pid the PID (process identifier).
-     */
-    public function __construct($pid)
-    {
-        $this->pid = $pid;
-    }
-
-    // }}}
-    // {{{ public function getPid()
-
-    /**
-     * Gets the PID (process identifier) being controlled
-     *
-     * @return integer the PID being controlled.
-     */
-    public function getPid()
-    {
-        return $this->pid;
-    }
-
-    // }}}
-    // {{{ isRunning()
-
-    /**
-     * Checks if the process is running
-     *
-     * If the <kbd>posix</kbd> extension is available, <kbd>posix_getpgid()</kbd>
-     * is used. Otherwise <kbd>ps</kbd> is used on UNIX-like systems and
-     * <kbd>tasklist</kbd> on Windows.
-     *
-     * @return boolean true if the process is running, false if not.
-     */
-    public function isRunning()
-    {
-        $running = false;
-
-        if (function_exists('posix_getpgid')) {
-            $running = false !== posix_getpgid($this->pid);
-        } elseif (PHP_OS === 'WINNT') {
-            $command = 'tasklist /fo csv /nh /fi '
-                . escapeshellarg('PID eq ' . $this->pid);
-
-            $result  = exec($command);
-            $parts   = explode(',', $result);
-            $running = (count($parts) > 1 && trim($parts[1], '"') == $this->pid);
-        } else {
-            $result  = exec('ps -p ' . escapeshellarg($this->pid) . ' -o pid=');
-            $running = (trim($result) == $this->pid);
-        }
-
-        return $running;
-    }
-
-    // }}}
-    // {{{ terminate()
-
-    /**
-     * Ends the process gracefully
-     *
-     * The signal SIGTERM is sent to the process. The gpg-agent process will
-     * end gracefully upon receiving the SIGTERM signal. Upon 3 consecutive
-     * SIGTERM signals the gpg-agent will forcefully shut down.
-     *
-     * If the <kbd>posix</kbd> extension is available, <kbd>posix_kill()</kbd>
-     * is used. Otherwise <kbd>kill</kbd> is used on UNIX-like systems and
-     * <kbd>taskkill</kbd> is used in Windows.
-     *
-     * @return void
-     */
-    public function terminate()
-    {
-        if (function_exists('posix_kill')) {
-            posix_kill($this->pid, 15);
-        } elseif (PHP_OS === 'WINNT') {
-            exec('taskkill /PID ' . escapeshellarg($this->pid));
-        } else {
-            exec('kill -15 ' . escapeshellarg($this->pid));
-        }
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/ProcessHandler.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,928 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains handler for status and error pipes of GPG process.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Aleksander Machniak <alec@alec.pl>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * GPG exception classes.
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-/**
- * Signature object class definition
- */
-require_once 'Crypt/GPG/Signature.php';
-
-// {{{ class Crypt_GPG_ProcessHandler
-
-/**
- * Status/Error handler for GPG process pipes.
- *
- * This class is used internally by Crypt_GPG_Engine and does not need to be used
- * directly. See the {@link Crypt_GPG} class for end-user API.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Aleksander Machniak <alec@alec.pl>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_ProcessHandler
-{
-    // {{{ protected class properties
-
-    /**
-     * Engine used to control the GPG subprocess
-     *
-     * @var Crypt_GPG_Engine
-     */
-    protected $engine;
-
-    /**
-     * The error code of the current operation
-     *
-     * @var integer
-     */
-    protected $errorCode = Crypt_GPG::ERROR_NONE;
-
-    /**
-     * The number of currently needed passphrases
-     *
-     * If this is not zero when the GPG command is completed, the error code is
-     * set to {@link Crypt_GPG::ERROR_MISSING_PASSPHRASE}.
-     *
-     * @var integer
-     */
-    protected $needPassphrase = 0;
-
-    /**
-     * Some data collected while processing the operation
-     * or set for the operation
-     *
-     * @var array
-     * @see self::setData()
-     * @see self::getData()
-     */
-    protected $data = array();
-
-    /**
-     * The name of the current operation
-     *
-     * @var string
-     * @see self::setOperation()
-     */
-    protected $operation = null;
-
-    /**
-     * The value of the argument of current operation
-     *
-     * @var string
-     * @see self::setOperation()
-     */
-    protected $operationArg = null;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new instance
-     *
-     * @param Crypt_GPG_Engine $engine Engine object
-     */
-    public function __construct($engine)
-    {
-        $this->engine = $engine;
-    }
-
-    // }}}
-    // {{{ setOperation()
-
-    /**
-     * Sets the operation that is being performed by the engine.
-     *
-     * @param string $operation The GPG operation to perform.
-     *
-     * @return void
-     */
-    public function setOperation($operation)
-    {
-        $op    = null;
-        $opArg = null;
-
-        // Regexp matching all GPG "operational" arguments
-        $regexp = '/--('
-            . 'version|import|list-public-keys|list-secret-keys'
-            . '|list-keys|delete-key|delete-secret-key|encrypt|sign|clearsign'
-            . '|detach-sign|decrypt|verify|export-secret-keys|export|gen-key'
-            . ')/';
-
-        if (strpos($operation, ' ') === false) {
-            $op = trim($operation, '- ');
-        } else if (preg_match($regexp, $operation, $matches, PREG_OFFSET_CAPTURE)) {
-            $op      = trim($matches[0][0], '-');
-            $op_len  = $matches[0][1] + mb_strlen($op, '8bit') + 3;
-            $command = mb_substr($operation, $op_len, null, '8bit');
-
-            // we really need the argument if it is a key ID/fingerprint or email
-            // address se we can use simplified regexp to "revert escapeshellarg()"
-            if (preg_match('/^[\'"]([a-zA-Z0-9:@._-]+)[\'"]/', $command, $matches)) {
-                $opArg = $matches[1];
-            }
-        }
-
-        $this->operation    = $op;
-        $this->operationArg = $opArg;
-    }
-
-    // }}}
-    // {{{ handleStatus()
-
-    /**
-     * Handles error values in the status output from GPG
-     *
-     * This method is responsible for setting the
-     * {@link self::$errorCode}. See <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
-     * information on GPG's status output.
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    public function handleStatus($line)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'NODATA':
-            $this->errorCode = Crypt_GPG::ERROR_NO_DATA;
-            break;
-
-        case 'DECRYPTION_OKAY':
-            // If the message is encrypted, this is the all-clear signal.
-            $this->data['DecryptionOkay'] = true;
-            $this->errorCode = Crypt_GPG::ERROR_NONE;
-            break;
-
-        case 'DELETE_PROBLEM':
-            if ($tokens[1] == '1') {
-                $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-                break;
-            } elseif ($tokens[1] == '2') {
-                $this->errorCode = Crypt_GPG::ERROR_DELETE_PRIVATE_KEY;
-                break;
-            }
-            break;
-
-        case 'IMPORT_OK':
-            $this->data['Import']['fingerprint'] = $tokens[2];
-
-            if (empty($this->data['Import']['fingerprints'])) {
-                $this->data['Import']['fingerprints'] = array($tokens[2]);
-            } else if (!in_array($tokens[2], $this->data['Import']['fingerprints'])) {
-                $this->data['Import']['fingerprints'][] = $tokens[2];
-            }
-
-            break;
-
-        case 'IMPORT_RES':
-            $this->data['Import']['public_imported']   = intval($tokens[3]);
-            $this->data['Import']['public_unchanged']  = intval($tokens[5]);
-            $this->data['Import']['private_imported']  = intval($tokens[11]);
-            $this->data['Import']['private_unchanged'] = intval($tokens[12]);
-            break;
-
-        case 'NO_PUBKEY':
-        case 'NO_SECKEY':
-            $this->data['ErrorKeyId'] = $tokens[1];
-
-            if ($this->errorCode != Crypt_GPG::ERROR_MISSING_PASSPHRASE
-                && $this->errorCode != Crypt_GPG::ERROR_BAD_PASSPHRASE
-            ) {
-                $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-
-            // note: this message is also received if there are multiple
-            // recipients and a previous key had a correct passphrase.
-            $this->data['MissingKeys'][$tokens[1]] = $tokens[1];
-
-            // @FIXME: remove missing passphrase registered in ENC_TO handler
-            //         This is for GnuPG 2.1
-            unset($this->data['MissingPassphrases'][$tokens[1]]);
-            break;
-
-        case 'KEY_CONSIDERED':
-            // In GnuPG 2.1.x exporting/importing a secret key requires passphrase
-            // However, no NEED_PASSPRASE is returned, https://bugs.gnupg.org/gnupg/issue2667
-            // So, handling KEY_CONSIDERED and GET_HIDDEN is needed.
-            if (!array_key_exists('KeyConsidered', $this->data)) {
-                $this->data['KeyConsidered'] = $tokens[1];
-            }
-            break;
-
-        case 'USERID_HINT':
-            // remember the user id for pretty exception messages
-            // GnuPG 2.1.15 gives me: "USERID_HINT 0000000000000000 [?]"
-            $keyId = $tokens[1];
-            if (strcspn($keyId, '0')) {
-                $username = implode(' ', array_splice($tokens, 2));
-                $this->data['BadPassphrases'][$keyId] = $username;
-            }
-            break;
-
-        case 'ENC_TO':
-            // Now we know the message is encrypted. Set flag to check if
-            // decryption succeeded.
-            $this->data['DecryptionOkay'] = false;
-
-            // this is the new key message
-            $this->data['CurrentSubKeyId'] = $keyId = $tokens[1];
-
-            // For some reason in GnuPG 2.1.11 I get only ENC_TO and no
-            // NEED_PASSPHRASE/MISSING_PASSPHRASE/USERID_HINT
-            // This is not needed for GnuPG 2.1.15
-            if (!empty($_ENV['PINENTRY_USER_DATA'])) {
-                $passphrases = json_decode($_ENV['PINENTRY_USER_DATA'], true);
-            } else {
-                $passphrases = array();
-            }
-
-            // @TODO: Get user name/email
-            $this->data['BadPassphrases'][$keyId] = $keyId;
-            if (empty($passphrases) || empty($passphrases[$keyId])) {
-                $this->data['MissingPassphrases'][$keyId] = $keyId;
-            }
-            break;
-
-        case 'GOOD_PASSPHRASE':
-            // if we got a good passphrase, remove the key from the list of
-            // bad passphrases.
-            if (isset($this->data['CurrentSubKeyId'])) {
-                unset($this->data['BadPassphrases'][$this->data['CurrentSubKeyId']]);
-                unset($this->data['MissingPassphrases'][$this->data['CurrentSubKeyId']]);
-            }
-
-            $this->needPassphrase--;
-            break;
-
-        case 'BAD_PASSPHRASE':
-            $this->errorCode = Crypt_GPG::ERROR_BAD_PASSPHRASE;
-            break;
-
-        case 'MISSING_PASSPHRASE':
-            if (isset($this->data['CurrentSubKeyId'])) {
-                $this->data['MissingPassphrases'][$this->data['CurrentSubKeyId']]
-                    = $this->data['CurrentSubKeyId'];
-            }
-
-            $this->errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-            break;
-
-        case 'GET_HIDDEN':
-            if ($tokens[1] == 'passphrase.enter' && isset($this->data['KeyConsidered'])) {
-                $tokens[1] = $this->data['KeyConsidered'];
-            } else {
-                break;
-            }
-            // no break
-
-        case 'NEED_PASSPHRASE':
-            $passphrase = $this->getPin($tokens[1]);
-
-            $this->engine->sendCommand($passphrase);
-
-            if ($passphrase === '') {
-                $this->needPassphrase++;
-            }
-            break;
-
-        case 'SIG_CREATED':
-            $this->data['SigCreated'] = $line;
-            break;
-
-        case 'SIG_ID':
-            // note: signature id comes before new signature line and may not
-            // exist for some signature types
-            $this->data['SignatureId'] = $tokens[1];
-            break;
-
-        case 'EXPSIG':
-        case 'EXPKEYSIG':
-        case 'REVKEYSIG':
-        case 'BADSIG':
-        case 'ERRSIG':
-            $this->errorCode = Crypt_GPG::ERROR_BAD_SIGNATURE;
-            // no break
-        case 'GOODSIG':
-            $signature = new Crypt_GPG_Signature();
-
-            // if there was a signature id, set it on the new signature
-            if (!empty($this->data['SignatureId'])) {
-                $signature->setId($this->data['SignatureId']);
-                $this->data['SignatureId'] = '';
-            }
-
-            // Detect whether fingerprint or key id was returned and set
-            // signature values appropriately. Key ids are strings of either
-            // 16 or 8 hexadecimal characters. Fingerprints are strings of 40
-            // hexadecimal characters. The key id is the last 16 characters of
-            // the key fingerprint.
-            if (mb_strlen($tokens[1], '8bit') > 16) {
-                $signature->setKeyFingerprint($tokens[1]);
-                $signature->setKeyId(mb_substr($tokens[1], -16, null, '8bit'));
-            } else {
-                $signature->setKeyId($tokens[1]);
-            }
-
-            // get user id string
-            if ($tokens[0] != 'ERRSIG') {
-                $string = implode(' ', array_splice($tokens, 2));
-                $string = rawurldecode($string);
-
-                $signature->setUserId(Crypt_GPG_UserId::parse($string));
-            }
-
-            $this->data['Signatures'][] = $signature;
-            break;
-
-        case 'VALIDSIG':
-            if (empty($this->data['Signatures'])) {
-                break;
-            }
-
-            $signature = end($this->data['Signatures']);
-
-            $signature->setValid(true);
-            $signature->setKeyFingerprint($tokens[1]);
-
-            if (strpos($tokens[3], 'T') === false) {
-                $signature->setCreationDate($tokens[3]);
-            } else {
-                $signature->setCreationDate(strtotime($tokens[3]));
-            }
-
-            if (array_key_exists(4, $tokens)) {
-                if (strpos($tokens[4], 'T') === false) {
-                    $signature->setExpirationDate($tokens[4]);
-                } else {
-                    $signature->setExpirationDate(strtotime($tokens[4]));
-                }
-            }
-
-            break;
-
-        case 'KEY_CREATED':
-            if (isset($this->data['Handle']) && $tokens[3] == $this->data['Handle']) {
-                $this->data['KeyCreated'] = $tokens[2];
-            }
-            break;
-
-        case 'KEY_NOT_CREATED':
-            if (isset($this->data['Handle']) && $tokens[1] == $this->data['Handle']) {
-                $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_CREATED;
-            }
-            break;
-
-        case 'PROGRESS':
-            // todo: at some point, support reporting status async
-            break;
-
-        // GnuPG 2.1 uses FAILURE and ERROR responses
-        case 'FAILURE':
-        case 'ERROR':
-            $errnum  = (int) $tokens[2];
-            $source  = $errnum >> 24;
-            $errcode = $errnum & 0xFFFFFF;
-
-            switch ($errcode) {
-            case 11: // bad passphrase
-            case 87: // bad PIN
-                $this->errorCode = Crypt_GPG::ERROR_BAD_PASSPHRASE;
-                break;
-
-            case 177: // no passphrase
-            case 178: // no PIN
-                $this->errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-                break;
-
-            case 58:
-                $this->errorCode = Crypt_GPG::ERROR_NO_DATA;
-                break;
-            }
-
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ handleError()
-
-    /**
-     * Handles error values in the error output from GPG
-     *
-     * This method is responsible for setting the
-     * {@link Crypt_GPG_Engine::$_errorCode}.
-     *
-     * @param string $line the error line to handle.
-     *
-     * @return void
-     */
-    public function handleError($line)
-    {
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/no valid OpenPGP data found/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->errorCode = Crypt_GPG::ERROR_NO_DATA;
-            }
-        }
-
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/No secret key|secret key not available/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-        }
-
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/No public key|public key not found/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-        }
-
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $matches = array();
-            $pattern = '/can\'t (?:access|open) `(.*?)\'/';
-            if (preg_match($pattern, $line, $matches) === 1) {
-                $this->data['ErrorFilename'] = $matches[1];
-                $this->errorCode = Crypt_GPG::ERROR_FILE_PERMISSIONS;
-            }
-        }
-
-        // GnuPG 2.1: It should return MISSING_PASSPHRASE, but it does not
-        // we have to detect it this way. This happens e.g. on private key import
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $matches = array();
-            $pattern = '/key ([0-9A-F]+).* (Bad|No) passphrase/';
-            if (preg_match($pattern, $line, $matches) === 1) {
-                $keyId = $matches[1];
-                // @TODO: Get user name/email
-                if (empty($this->data['BadPassphrases'][$keyId])) {
-                    $this->data['BadPassphrases'][$keyId] = $keyId;
-                }
-                if ($matches[2] == 'Bad') {
-                    $this->errorCode = Crypt_GPG::ERROR_BAD_PASSPHRASE;
-                } else {
-                    $this->errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-                    if (empty($this->data['MissingPassphrases'][$keyId])) {
-                        $this->data['MissingPassphrases'][$keyId] = $keyId;
-                    }
-                }
-            }
-        }
-
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE && $this->operation == 'gen-key') {
-            $pattern = '/:([0-9]+): invalid algorithm$/';
-            if (preg_match($pattern, $line, $matches) === 1) {
-                $this->errorCode          = Crypt_GPG::ERROR_BAD_KEY_PARAMS;
-                $this->data['LineNumber'] = intval($matches[1]);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ throwException()
-
-    /**
-     * On error throws exception
-     *
-     * @param int $exitcode GPG process exit code
-     *
-     * @return void
-     * @throws Crypt_GPG_Exception
-     */
-    public function throwException($exitcode = 0)
-    {
-        if ($exitcode > 0 && $this->errorCode === Crypt_GPG::ERROR_NONE) {
-            $this->errorCode = $this->setErrorCode($exitcode);
-        }
-
-        if ($this->errorCode === Crypt_GPG::ERROR_NONE) {
-            return;
-        }
-
-        $code = $this->errorCode;
-        $note = "Please use the 'debug' option when creating the Crypt_GPG " .
-            "object, and file a bug report at " . Crypt_GPG::BUG_URI;
-
-        switch ($this->operation) {
-        case 'version':
-            throw new Crypt_GPG_Exception(
-                'Unknown error getting GnuPG version information. ' . $note,
-                $code
-            );
-
-        case 'list-secret-keys':
-        case 'list-public-keys':
-        case 'list-keys':
-            switch ($code) {
-            case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-                // ignore not found key errors
-                break;
-
-            case Crypt_GPG::ERROR_FILE_PERMISSIONS:
-                if (!empty($this->data['ErrorFilename'])) {
-                    throw new Crypt_GPG_FileException(
-                        sprintf(
-                            'Error reading GnuPG data file \'%s\'. Check to make ' .
-                            'sure it is readable by the current user.',
-                            $this->data['ErrorFilename']
-                        ),
-                        $code,
-                        $this->data['ErrorFilename']
-                    );
-                }
-                throw new Crypt_GPG_FileException(
-                    'Error reading GnuPG data file. Check to make sure that ' .
-                    'GnuPG data files are readable by the current user.',
-                    $code
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error getting keys. ' . $note, $code
-                );
-            }
-            break;
-
-        case 'delete-key':
-        case 'delete-secret-key':
-            switch ($code) {
-            case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Key not found: ' . $this->operationArg,
-                    $code,
-                    $this->operationArg
-                );
-
-            case Crypt_GPG::ERROR_DELETE_PRIVATE_KEY:
-                throw new Crypt_GPG_DeletePrivateKeyException(
-                    'Private key must be deleted before public key can be ' .
-                    'deleted.',
-                    $code,
-                    $this->operationArg
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error deleting key. ' . $note, $code
-                );
-            }
-            break;
-
-        case 'import':
-            switch ($code) {
-            case Crypt_GPG::ERROR_NO_DATA:
-                throw new Crypt_GPG_NoDataException(
-                    'No valid GPG key data found.', $code
-                );
-
-            case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-                throw $this->badPassException($code, 'Cannot import private key.');
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error importing GPG key. ' . $note, $code
-                );
-            }
-            break;
-
-        case 'export':
-        case 'export-secret-keys':
-            switch ($code) {
-            case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-                throw $this->badPassException($code, 'Cannot export private key.');
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error exporting a key. ' . $note, $code
-                );
-            }
-            break;
-
-        case 'encrypt':
-        case 'sign':
-        case 'clearsign':
-        case 'detach-sign':
-            switch ($code) {
-            case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Cannot sign data. Private key not found. Import the '.
-                    'private key before trying to sign data.',
-                    $code,
-                    !empty($this->data['ErrorKeyId']) ? $this->data['ErrorKeyId'] : null
-                );
-
-            case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-                throw new Crypt_GPG_BadPassphraseException(
-                    'Cannot sign data. Incorrect passphrase provided.', $code
-                );
-
-            case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-                throw new Crypt_GPG_BadPassphraseException(
-                    'Cannot sign data. No passphrase provided.', $code
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    "Unknown error {$this->operation}ing data. $note", $code
-                );
-            }
-            break;
-
-        case 'verify':
-            switch ($code) {
-            case Crypt_GPG::ERROR_BAD_SIGNATURE:
-                // ignore bad signature errors
-                break;
-
-            case Crypt_GPG::ERROR_NO_DATA:
-                throw new Crypt_GPG_NoDataException(
-                    'No valid signature data found.', $code
-                );
-
-            case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Public key required for data verification not in keyring.',
-                    $code,
-                    !empty($this->data['ErrorKeyId']) ? $this->data['ErrorKeyId'] : null
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error validating signature details. ' . $note,
-                    $code
-                );
-            }
-            break;
-
-        case 'decrypt':
-            switch ($code) {
-            case Crypt_GPG::ERROR_BAD_SIGNATURE:
-                // ignore bad signature errors
-                break;
-
-            case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-                if (!empty($this->data['MissingKeys'])) {
-                    $keyId = reset($this->data['MissingKeys']);
-                } else {
-                    $keyId = '';
-                }
-
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Cannot decrypt data. No suitable private key is in the ' .
-                    'keyring. Import a suitable private key before trying to ' .
-                    'decrypt this data.',
-                    $code,
-                    $keyId
-                );
-
-            case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-                throw $this->badPassException($code, 'Cannot decrypt data.');
-
-            case Crypt_GPG::ERROR_NO_DATA:
-                throw new Crypt_GPG_NoDataException(
-                    'Cannot decrypt data. No PGP encrypted data was found in '.
-                    'the provided data.',
-                    $code
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error decrypting data.', $code
-                );
-            }
-            break;
-
-        case 'gen-key':
-            switch ($code) {
-            case Crypt_GPG::ERROR_BAD_KEY_PARAMS:
-                throw new Crypt_GPG_InvalidKeyParamsException(
-                    'Invalid key algorithm specified.', $code
-                );
-
-            default:
-                throw new Crypt_GPG_Exception(
-                    'Unknown error generating key-pair. ' . $note, $code
-                );
-            }
-        }
-    }
-
-    // }}}
-    // {{{ throwException()
-
-    /**
-     * Check exit code of the GPG operation.
-     *
-     * @param int $exitcode GPG process exit code
-     *
-     * @return int Internal error code
-     */
-    protected function setErrorCode($exitcode)
-    {
-        if ($this->needPassphrase > 0) {
-            return Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-        }
-
-        if ($this->operation == 'import') {
-            return Crypt_GPG::ERROR_NONE;
-        }
-
-        if ($this->operation == 'decrypt' && !empty($this->data['DecryptionOkay'])) {
-            if (!empty($this->data['IgnoreVerifyErrors'])) {
-                return Crypt_GPG::ERROR_NONE;
-            }
-            if (!empty($this->data['MissingKeys'])) {
-                return Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-        }
-
-        return Crypt_GPG::ERROR_UNKNOWN;
-    }
-
-    // }}}
-    // {{{ getData()
-
-    /**
-     * Get data from the last process execution.
-     *
-     * @param string $name Data element name:
-     *               - SigCreated: The last SIG_CREATED status.
-     *               - KeyConsidered: The last KEY_CONSIDERED status identifier.
-     *               - KeyCreated: The KEY_CREATED status (for specified Handle).
-     *               - Signatures: Signatures data from verification process.
-     *               - LineNumber: Number of the gen-key error line.
-     *               - Import: Result of IMPORT_OK/IMPORT_RES
-     *
-     * @return mixed
-     */
-    public function getData($name)
-    {
-        return isset($this->data[$name]) ? $this->data[$name] : null;
-    }
-
-    // }}}
-    // {{{ setData()
-
-    /**
-     * Set data for the process execution.
-     *
-     * @param string $name  Data element name:
-     *               - Handle: The unique key handle used by this handler
-     *                         The key handle is used to track GPG status output
-     *                         for a particular key on --gen-key command before
-     *                         the key has its own identifier.
-     *               - IgnoreVerifyErrors: Do not throw exceptions
-     *                         when signature verification failes because
-     *                         of a missing public key.
-     * @param mixed  $value Data element value
-     *
-     * @return void
-     */
-    public function setData($name, $value)
-    {
-        switch ($name) {
-        case 'Handle':
-            $this->data[$name] = strval($value);
-            break;
-
-        case 'IgnoreVerifyErrors':
-            $this->data[$name] = (bool) $value;
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ setData()
-
-    /**
-     * Create Crypt_GPG_BadPassphraseException from operation data.
-     *
-     * @param int    $code    Error code
-     * @param string $message Error message
-     *
-     * @return Crypt_GPG_BadPassphraseException
-     */
-    protected function badPassException($code, $message)
-    {
-        $badPassphrases = array_diff_key(
-            isset($this->data['BadPassphrases']) ? $this->data['BadPassphrases'] : array(),
-            isset($this->data['MissingPassphrases']) ? $this->data['MissingPassphrases'] : array()
-        );
-
-        $missingPassphrases = array_intersect_key(
-            isset($this->data['BadPassphrases']) ? $this->data['BadPassphrases'] : array(),
-            isset($this->data['MissingPassphrases']) ? $this->data['MissingPassphrases'] : array()
-        );
-
-        if (count($badPassphrases) > 0) {
-            $message .= ' Incorrect passphrase provided for keys: "' .
-                implode('", "', $badPassphrases) . '".';
-        }
-        if (count($missingPassphrases) > 0) {
-            $message .= ' No passphrase provided for keys: "' .
-                implode('", "', $missingPassphrases) . '".';
-        }
-
-        return new Crypt_GPG_BadPassphraseException(
-            $message,
-            $code,
-            $badPassphrases,
-            $missingPassphrases
-        );
-    }
-
-    // }}}
-    // {{{ getPin()
-
-    /**
-     * Get registered passphrase for specified key.
-     *
-     * @param string $key Key identifier
-     *
-     * @return string Passphrase
-     */
-    protected function getPin($key)
-    {
-        $passphrase  = '';
-        $keyIdLength = mb_strlen($key, '8bit');
-
-        if ($keyIdLength && !empty($_ENV['PINENTRY_USER_DATA'])) {
-            $passphrases = json_decode($_ENV['PINENTRY_USER_DATA'], true);
-            foreach ($passphrases as $_keyId => $pass) {
-                $keyId        = $key;
-                $_keyIdLength = mb_strlen($_keyId, '8bit');
-
-                // Get last X characters of key identifier to compare
-                if ($keyIdLength < $_keyIdLength) {
-                    $_keyId = mb_substr($_keyId, -$keyIdLength, null, '8bit');
-                } else if ($keyIdLength > $_keyIdLength) {
-                    $keyId = mb_substr($keyId, -$_keyIdLength, null, '8bit');
-                }
-
-                if ($_keyId === $keyId) {
-                    $passphrase = $pass;
-                    break;
-                }
-            }
-        }
-
-        return $passphrase;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/Signature.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,426 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A class representing GPG signatures
- *
- * This file contains a data class representing a GPG signature.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * User id class definition
- */
-require_once 'Crypt/GPG/UserId.php';
-
-// {{{ class Crypt_GPG_Signature
-
-/**
- * A class for GPG signature information
- *
- * This class is used to store the results of the Crypt_GPG::verify() method.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::verify()
- */
-class Crypt_GPG_Signature
-{
-    // {{{ class properties
-
-    /**
-     * A base64-encoded string containing a unique id for this signature if
-     * this signature has been verified as ok
-     *
-     * This id is used to prevent replay attacks and is not present for all
-     * types of signatures.
-     *
-     * @var string
-     */
-    private $_id = '';
-
-    /**
-     * The fingerprint of the key used to create the signature
-     *
-     * @var string
-     */
-    private $_keyFingerprint = '';
-
-    /**
-     * The id of the key used to create the signature
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    /**
-     * The creation date of this signature
-     *
-     * This is a Unix timestamp.
-     *
-     * @var integer
-     */
-    private $_creationDate = 0;
-
-    /**
-     * The expiration date of the signature
-     *
-     * This is a Unix timestamp. If this signature does not expire, this will
-     * be zero.
-     *
-     * @var integer
-     */
-    private $_expirationDate = 0;
-
-    /**
-     * The user id associated with this signature
-     *
-     * @var Crypt_GPG_UserId
-     */
-    private $_userId = null;
-
-    /**
-     * Whether or not this signature is valid
-     *
-     * @var boolean
-     */
-    private $_isValid = false;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new signature
-     *
-     * Signatures can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  id</kbd>          - the unique id of this signature.
-     * - <kbd>string  fingerprint</kbd> - the fingerprint of the key used to
-     *                                    create the signature. The fingerprint
-     *                                    should not contain formatting
-     *                                    characters.
-     * - <kbd>string  keyId</kbd>       - the id of the key used to create the
-     *                                    the signature.
-     * - <kbd>integer creation</kbd>    - the date the signature was created.
-     *                                    This is a UNIX timestamp.
-     * - <kbd>integer expiration</kbd>  - the date the signature expired. This
-     *                                    is a UNIX timestamp. If the signature
-     *                                    does not expire, use 0.
-     * - <kbd>boolean valid</kbd>       - whether or not the signature is valid.
-     * - <kbd>string  userId</kbd>      - the user id associated with the
-     *                                    signature. This may also be a
-     *                                    {@link Crypt_GPG_UserId} object.
-     *
-     * @param Crypt_GPG_Signature|array $signature optional. Either an existing
-     *        signature object, which is copied; or an array of initial values.
-     */
-    public function __construct($signature = null)
-    {
-        // copy from object
-        if ($signature instanceof Crypt_GPG_Signature) {
-            $this->_id             = $signature->_id;
-            $this->_keyFingerprint = $signature->_keyFingerprint;
-            $this->_keyId          = $signature->_keyId;
-            $this->_creationDate   = $signature->_creationDate;
-            $this->_expirationDate = $signature->_expirationDate;
-            $this->_isValid        = $signature->_isValid;
-
-            if ($signature->_userId instanceof Crypt_GPG_UserId) {
-                $this->_userId = clone $signature->_userId;
-            }
-        }
-
-        // initialize from array
-        if (is_array($signature)) {
-            if (array_key_exists('id', $signature)) {
-                $this->setId($signature['id']);
-            }
-
-            if (array_key_exists('fingerprint', $signature)) {
-                $this->setKeyFingerprint($signature['fingerprint']);
-            }
-
-            if (array_key_exists('keyId', $signature)) {
-                $this->setKeyId($signature['keyId']);
-            }
-
-            if (array_key_exists('creation', $signature)) {
-                $this->setCreationDate($signature['creation']);
-            }
-
-            if (array_key_exists('expiration', $signature)) {
-                $this->setExpirationDate($signature['expiration']);
-            }
-
-            if (array_key_exists('valid', $signature)) {
-                $this->setValid($signature['valid']);
-            }
-
-            if (array_key_exists('userId', $signature)) {
-                $userId = new Crypt_GPG_UserId($signature['userId']);
-                $this->setUserId($userId);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getId()
-
-    /**
-     * Gets the id of this signature
-     *
-     * @return string a base64-encoded string containing a unique id for this
-     *                signature. This id is used to prevent replay attacks and
-     *                is not present for all types of signatures.
-     */
-    public function getId()
-    {
-        return $this->_id;
-    }
-
-    // }}}
-    // {{{ getKeyFingerprint()
-
-    /**
-     * Gets the fingerprint of the key used to create this signature
-     *
-     * @return string the fingerprint of the key used to create this signature.
-     */
-    public function getKeyFingerprint()
-    {
-        return $this->_keyFingerprint;
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the id of the key used to create this signature
-     *
-     * Whereas the fingerprint of the signing key may not always be available
-     * (for example if the signature is bad), the id should always be
-     * available.
-     *
-     * @return string the id of the key used to create this signature.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-    // {{{ getCreationDate()
-
-    /**
-     * Gets the creation date of this signature
-     *
-     * @return integer the creation date of this signature. This is a Unix
-     *                 timestamp.
-     */
-    public function getCreationDate()
-    {
-        return $this->_creationDate;
-    }
-
-    // }}}
-    // {{{ getExpirationDate()
-
-    /**
-     * Gets the expiration date of the signature
-     *
-     * @return integer the expiration date of this signature. This is a Unix
-     *                 timestamp. If this signature does not expire, this will
-     *                 be zero.
-     */
-    public function getExpirationDate()
-    {
-        return $this->_expirationDate;
-    }
-
-    // }}}
-    // {{{ getUserId()
-
-    /**
-     * Gets the user id associated with this signature
-     *
-     * @return Crypt_GPG_UserId the user id associated with this signature.
-     */
-    public function getUserId()
-    {
-        return $this->_userId;
-    }
-
-    // }}}
-    // {{{ isValid()
-
-    /**
-     * Gets whether or no this signature is valid
-     *
-     * @return boolean true if this signature is valid and false if it is not.
-     */
-    public function isValid()
-    {
-        return $this->_isValid;
-    }
-
-    // }}}
-    // {{{ setId()
-
-    /**
-     * Sets the id of this signature
-     *
-     * @param string $id a base64-encoded string containing a unique id for
-     *                   this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     *
-     * @see Crypt_GPG_Signature::getId()
-     */
-    public function setId($id)
-    {
-        $this->_id = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setKeyFingerprint()
-
-    /**
-     * Sets the key fingerprint of this signature
-     *
-     * @param string $fingerprint the key fingerprint of this signature. This
-     *                            is the fingerprint of the primary key used to
-     *                            create this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setKeyFingerprint($fingerprint)
-    {
-        $this->_keyFingerprint = strval($fingerprint);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setKeyId()
-
-    /**
-     * Sets the key id of this signature
-     *
-     * @param string $id the key id of this signature. This is the id of the
-     *                   primary key used to create this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setKeyId($id)
-    {
-        $this->_keyId = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCreationDate()
-
-    /**
-     * Sets the creation date of this signature
-     *
-     * @param integer $creationDate the creation date of this signature. This
-     *                              is a Unix timestamp.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setCreationDate($creationDate)
-    {
-        $this->_creationDate = intval($creationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setExpirationDate()
-
-    /**
-     * Sets the expiration date of this signature
-     *
-     * @param integer $expirationDate the expiration date of this signature.
-     *                                This is a Unix timestamp. Specify zero if
-     *                                this signature does not expire.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setExpirationDate($expirationDate)
-    {
-        $this->_expirationDate = intval($expirationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setUserId()
-
-    /**
-     * Sets the user id associated with this signature
-     *
-     * @param Crypt_GPG_UserId $userId the user id associated with this
-     *                                 signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setUserId(Crypt_GPG_UserId $userId)
-    {
-        $this->_userId = $userId;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setValid()
-
-    /**
-     * Sets whether or not this signature is valid
-     *
-     * @param boolean $isValid true if this signature is valid and false if it
-     *                         is not.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setValid($isValid)
-    {
-        $this->_isValid = ($isValid) ? true : false;
-        return $this;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/SignatureCreationInfo.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-<?php
-/**
- * Part of Crypt_GPG
- *
- * PHP version 5
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Christian Weiske <cweiske@php.net>
- * @copyright 2015 PEAR
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Information about a recently created signature.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Christian Weiske <cweiske@php.net>
- * @copyright 2015 PEAR
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_SignatureCreationInfo
-{
-    /**
-     * One of the three signature types:
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @var integer
-     */
-    protected $mode;
-
-    /**
-     * Public Key algorithm
-     *
-     * @var integer
-     */
-    protected $pkAlgorithm;
-
-    /**
-     * Algorithm to hash the data
-     *
-     * @see RFC 2440 / 9.4. Hash Algorithm
-     * @var integer
-     */
-    protected $hashAlgorithm;
-
-    /**
-     * OpenPGP signature class
-     *
-     * @var mixed
-     */
-    protected $class;
-
-    /**
-     * Unix timestamp when the signature was created
-     *
-     * @var integer
-     */
-    protected $timestamp;
-
-    /**
-     * Key fingerprint
-     *
-     * @var string
-     */
-    protected $keyFingerprint;
-
-    /**
-     * If the line given to the constructor was valid
-     *
-     * @var boolean
-     */
-    protected $valid;
-
-    /**
-     * Names for the hash algorithm IDs.
-     *
-     * Names taken from RFC 3156, without the leading "pgp-".
-     *
-     * @see RFC 2440 / 9.4. Hash Algorithm
-     * @see RFC 3156 / 5. OpenPGP signed data
-     * @var array
-     */
-    protected static $hashAlgorithmNames = array(
-        1 => 'md5',
-        2 => 'sha1',
-        3 => 'ripemd160',
-        5 => 'md2',
-        6 => 'tiger192',
-        7 => 'haval-5-160',
-        8 => 'sha256',
-        9 => 'sha384',
-        10 => 'sha512',
-        11 => 'sha224',
-    );
-
-    /**
-     * Parse a SIG_CREATED line from gnupg
-     *
-     * @param string $sigCreatedLine Line beginning with "SIG_CREATED "
-     */
-    public function __construct($sigCreatedLine = null)
-    {
-        if ($sigCreatedLine === null) {
-            $this->valid = false;
-            return;
-        }
-
-        $parts = explode(' ', $sigCreatedLine);
-        if (count($parts) !== 7) {
-            $this->valid = false;
-            return;
-        }
-        list(
-            $title, $mode, $pkAlgorithm, $hashAlgorithm,
-            $class, $timestamp, $keyFingerprint
-        ) = $parts;
-
-        switch (strtoupper($mode[0])) {
-        case 'D':
-            $this->mode = Crypt_GPG::SIGN_MODE_DETACHED;
-            break;
-        case 'C':
-            $this->mode = Crypt_GPG::SIGN_MODE_CLEAR;
-            break;
-        case 'S':
-            $this->mode = Crypt_GPG::SIGN_MODE_NORMAL;
-            break;
-        }
-
-        $this->pkAlgorithm    = (int) $pkAlgorithm;
-        $this->hashAlgorithm  = (int) $hashAlgorithm;
-        $this->class          = $class;
-        if (is_numeric($timestamp)) {
-            $this->timestamp  = (int) $timestamp;
-        } else {
-            $this->timestamp  = strtotime($timestamp);
-        }
-        $this->keyFingerprint = $keyFingerprint;
-        $this->valid = true;
-    }
-
-    /**
-     * Get the signature type
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @return integer
-     */
-    public function getMode()
-    {
-        return $this->mode;
-    }
-
-    /**
-     * Return the public key algorithm used.
-     *
-     * @return integer
-     */
-    public function getPkAlgorithm()
-    {
-        return $this->pkAlgorithm;
-    }
-
-    /**
-     * Return the hash algorithm used to hash the data to sign.
-     *
-     * @return integer
-     */
-    public function getHashAlgorithm()
-    {
-        return $this->hashAlgorithm;
-    }
-
-    /**
-     * Get a name for the used hashing algorithm.
-     *
-     * @return string|null
-     */
-    public function getHashAlgorithmName()
-    {
-        if (!isset(self::$hashAlgorithmNames[$this->hashAlgorithm])) {
-            return null;
-        }
-        return self::$hashAlgorithmNames[$this->hashAlgorithm];
-    }
-
-    /**
-     * Return the timestamp at which the signature was created
-     *
-     * @return integer
-     */
-    public function getTimestamp()
-    {
-        return $this->timestamp;
-    }
-
-    /**
-     * Return the key's fingerprint
-     *
-     * @return string
-     */
-    public function getKeyFingerprint()
-    {
-        return $this->keyFingerprint;
-    }
-
-    /**
-     * Tell if the fingerprint line given to the constructor was valid
-     *
-     * @return boolean
-     */
-    public function isValid()
-    {
-        return $this->valid;
-    }
-}
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/SubKey.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,715 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a class representing GPG sub-keys and constants for GPG algorithms
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-// {{{ class Crypt_GPG_SubKey
-
-/**
- * A class for GPG sub-key information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method. Sub-key objects are members of a {@link Crypt_GPG_Key} object.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- * @see       Crypt_GPG_Key::getSubKeys()
- */
-class Crypt_GPG_SubKey
-{
-    // {{{ algorithm class constants
-
-    /**
-     * RSA encryption algorithm.
-     */
-    const ALGORITHM_RSA = 1;
-
-    /**
-     * Elgamal encryption algorithm (encryption only).
-     */
-    const ALGORITHM_ELGAMAL_ENC = 16;
-
-    /**
-     * DSA encryption algorithm (sometimes called DH, sign only).
-     */
-    const ALGORITHM_DSA = 17;
-
-    /**
-     * Elgamal encryption algorithm (signage and encryption - should not be
-     * used).
-     */
-    const ALGORITHM_ELGAMAL_ENC_SGN = 20;
-
-    // }}}
-    // {{{ usage class constants
-
-    /**
-     * Key can be used to encrypt
-     */
-    const USAGE_ENCRYPT = 1;
-
-    /**
-     * Key can be used to sign
-     */
-    const USAGE_SIGN = 2;
-
-    /**
-     * Key can be used to certify other keys
-     */
-    const USAGE_CERTIFY = 4;
-
-    /**
-     * Key can be used for authentication
-     */
-    const USAGE_AUTHENTICATION = 8;
-
-    // }}}
-    // {{{ class properties
-
-    /**
-     * The id of this sub-key
-     *
-     * @var string
-     */
-    private $_id = '';
-
-    /**
-     * The algorithm used to create this sub-key
-     *
-     * The value is one of the Crypt_GPG_SubKey::ALGORITHM_* constants.
-     *
-     * @var integer
-     */
-    private $_algorithm = 0;
-
-    /**
-     * The fingerprint of this sub-key
-     *
-     * @var string
-     */
-    private $_fingerprint = '';
-
-    /**
-     * Length of this sub-key in bits
-     *
-     * @var integer
-     */
-    private $_length = 0;
-
-    /**
-     * Date this sub-key was created
-     *
-     * This is a Unix timestamp.
-     *
-     * @var integer
-     */
-    private $_creationDate = 0;
-
-    /**
-     * Date this sub-key expires
-     *
-     * This is a Unix timestamp. If this sub-key does not expire, this will be
-     * zero.
-     *
-     * @var integer
-     */
-    private $_expirationDate = 0;
-
-    /**
-     * Contains usage flags of this sub-key
-     *
-     * @var int
-     */
-    private $_usage = 0;
-
-    /**
-     * Whether or not the private key for this sub-key exists in the keyring
-     *
-     * @var boolean
-     */
-    private $_hasPrivate = false;
-
-    /**
-     * Whether or not this sub-key is revoked
-     *
-     * @var boolean
-     */
-    private $_isRevoked = false;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new sub-key object
-     *
-     * Sub-keys can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  id</kbd>          - the key id of the sub-key.
-     * - <kbd>integer algorithm</kbd>   - the encryption algorithm of the
-     *                                    sub-key.
-     * - <kbd>string  fingerprint</kbd> - the fingerprint of the sub-key. The
-     *                                    fingerprint should not contain
-     *                                    formatting characters.
-     * - <kbd>integer length</kbd>      - the length of the sub-key in bits.
-     * - <kbd>integer creation</kbd>    - the date the sub-key was created.
-     *                                    This is a UNIX timestamp.
-     * - <kbd>integer expiration</kbd>  - the date the sub-key expires. This
-     *                                    is a UNIX timestamp. If the sub-key
-     *                                    does not expire, use 0.
-     * - <kbd>boolean canSign</kbd>     - whether or not the sub-key can be
-     *                                    used to sign data.
-     * - <kbd>boolean canEncrypt</kbd>  - whether or not the sub-key can be
-     *                                    used to encrypt data.
-     * - <kbd>integer usage</kbd>       - the sub-key usage flags
-     * - <kbd>boolean hasPrivate</kbd>  - whether or not the private key for
-     *                                    the sub-key exists in the keyring.
-     * - <kbd>boolean isRevoked</kbd>   - whether or not this sub-key is
-     *                                    revoked.
-     *
-     * @param Crypt_GPG_SubKey|string|array $key optional. Either an existing
-     *        sub-key object, which is copied; a sub-key string, which is
-     *        parsed; or an array of initial values.
-     */
-    public function __construct($key = null)
-    {
-        // parse from string
-        if (is_string($key)) {
-            $key = self::parse($key);
-        }
-
-        // copy from object
-        if ($key instanceof Crypt_GPG_SubKey) {
-            $this->_id             = $key->_id;
-            $this->_algorithm      = $key->_algorithm;
-            $this->_fingerprint    = $key->_fingerprint;
-            $this->_length         = $key->_length;
-            $this->_creationDate   = $key->_creationDate;
-            $this->_expirationDate = $key->_expirationDate;
-            $this->_usage          = $key->_usage;
-            $this->_hasPrivate     = $key->_hasPrivate;
-            $this->_isRevoked      = $key->_isRevoked;
-        }
-
-        // initialize from array
-        if (is_array($key)) {
-            if (array_key_exists('id', $key)) {
-                $this->setId($key['id']);
-            }
-
-            if (array_key_exists('algorithm', $key)) {
-                $this->setAlgorithm($key['algorithm']);
-            }
-
-            if (array_key_exists('fingerprint', $key)) {
-                $this->setFingerprint($key['fingerprint']);
-            }
-
-            if (array_key_exists('length', $key)) {
-                $this->setLength($key['length']);
-            }
-
-            if (array_key_exists('creation', $key)) {
-                $this->setCreationDate($key['creation']);
-            }
-
-            if (array_key_exists('expiration', $key)) {
-                $this->setExpirationDate($key['expiration']);
-            }
-
-            if (array_key_exists('usage', $key)) {
-                $this->setUsage($key['usage']);
-            }
-
-            if (array_key_exists('canSign', $key)) {
-                $this->setCanSign($key['canSign']);
-            }
-
-            if (array_key_exists('canEncrypt', $key)) {
-                $this->setCanEncrypt($key['canEncrypt']);
-            }
-
-            if (array_key_exists('hasPrivate', $key)) {
-                $this->setHasPrivate($key['hasPrivate']);
-            }
-
-            if (array_key_exists('isRevoked', $key)) {
-                $this->setRevoked($key['isRevoked']);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getId()
-
-    /**
-     * Gets the id of this sub-key
-     *
-     * @return string the id of this sub-key.
-     */
-    public function getId()
-    {
-        return $this->_id;
-    }
-
-    // }}}
-    // {{{ getAlgorithm()
-
-    /**
-     * Gets the algorithm used by this sub-key
-     *
-     * The algorithm should be one of the Crypt_GPG_SubKey::ALGORITHM_*
-     * constants.
-     *
-     * @return integer the algorithm used by this sub-key.
-     */
-    public function getAlgorithm()
-    {
-        return $this->_algorithm;
-    }
-
-    // }}}
-    // {{{ getCreationDate()
-
-    /**
-     * Gets the creation date of this sub-key
-     *
-     * This is a Unix timestamp.
-     *
-     * @return integer the creation date of this sub-key.
-     */
-    public function getCreationDate()
-    {
-        return $this->_creationDate;
-    }
-
-    // }}}
-    // {{{ getExpirationDate()
-
-    /**
-     * Gets the date this sub-key expires
-     *
-     * This is a Unix timestamp. If this sub-key does not expire, this will be
-     * zero.
-     *
-     * @return integer the date this sub-key expires.
-     */
-    public function getExpirationDate()
-    {
-        return $this->_expirationDate;
-    }
-
-    // }}}
-    // {{{ getFingerprint()
-
-    /**
-     * Gets the fingerprint of this sub-key
-     *
-     * @return string the fingerprint of this sub-key.
-     */
-    public function getFingerprint()
-    {
-        return $this->_fingerprint;
-    }
-
-    // }}}
-    // {{{ getLength()
-
-    /**
-     * Gets the length of this sub-key in bits
-     *
-     * @return integer the length of this sub-key in bits.
-     */
-    public function getLength()
-    {
-        return $this->_length;
-    }
-
-    // }}}
-    // {{{ canSign()
-
-    /**
-     * Gets whether or not this sub-key can sign data
-     *
-     * @return boolean true if this sub-key can sign data and false if this
-     *                 sub-key can not sign data.
-     */
-    public function canSign()
-    {
-        return ($this->_usage & self::USAGE_SIGN) != 0;
-    }
-
-    // }}}
-    // {{{ canEncrypt()
-
-    /**
-     * Gets whether or not this sub-key can encrypt data
-     *
-     * @return boolean true if this sub-key can encrypt data and false if this
-     *                 sub-key can not encrypt data.
-     */
-    public function canEncrypt()
-    {
-        return ($this->_usage & self::USAGE_ENCRYPT) != 0;
-    }
-
-    // }}}
-    // {{{ usage()
-
-    /**
-     * Gets usage flags of this sub-key
-     *
-     * @return int Sum of usage flags
-     */
-    public function usage()
-    {
-        return $this->_usage;
-    }
-
-    // }}}
-    // {{{ hasPrivate()
-
-    /**
-     * Gets whether or not the private key for this sub-key exists in the
-     * keyring
-     *
-     * @return boolean true the private key for this sub-key exists in the
-     *                 keyring and false if it does not.
-     */
-    public function hasPrivate()
-    {
-        return $this->_hasPrivate;
-    }
-
-    // }}}
-    // {{{ isRevoked()
-
-    /**
-     * Gets whether or not this sub-key is revoked
-     *
-     * @return boolean true if this sub-key is revoked and false if it is not.
-     */
-    public function isRevoked()
-    {
-        return $this->_isRevoked;
-    }
-
-    // }}}
-    // {{{ setCreationDate()
-
-    /**
-     * Sets the creation date of this sub-key
-     *
-     * The creation date is a Unix timestamp.
-     *
-     * @param integer $creationDate the creation date of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCreationDate($creationDate)
-    {
-        $this->_creationDate = intval($creationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setExpirationDate()
-
-    /**
-     * Sets the expiration date of this sub-key
-     *
-     * The expiration date is a Unix timestamp. Specify zero if this sub-key
-     * does not expire.
-     *
-     * @param integer $expirationDate the expiration date of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setExpirationDate($expirationDate)
-    {
-        $this->_expirationDate = intval($expirationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setId()
-
-    /**
-     * Sets the id of this sub-key
-     *
-     * @param string $id the id of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setId($id)
-    {
-        $this->_id = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setAlgorithm()
-
-    /**
-     * Sets the algorithm used by this sub-key
-     *
-     * @param integer $algorithm the algorithm used by this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setAlgorithm($algorithm)
-    {
-        $this->_algorithm = intval($algorithm);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setFingerprint()
-
-    /**
-     * Sets the fingerprint of this sub-key
-     *
-     * @param string $fingerprint the fingerprint of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setFingerprint($fingerprint)
-    {
-        $this->_fingerprint = strval($fingerprint);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setLength()
-
-    /**
-     * Sets the length of this sub-key in bits
-     *
-     * @param integer $length the length of this sub-key in bits.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setLength($length)
-    {
-        $this->_length = intval($length);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCanSign()
-
-    /**
-     * Sets whether or not this sub-key can sign data
-     *
-     * @param boolean $canSign true if this sub-key can sign data and false if
-     *                         it can not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCanSign($canSign)
-    {
-        if ($canSign) {
-            $this->_usage |= self::USAGE_SIGN;
-        } else {
-            $this->_usage &= ~self::USAGE_SIGN;
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCanEncrypt()
-
-    /**
-     * Sets whether or not this sub-key can encrypt data
-     *
-     * @param boolean $canEncrypt true if this sub-key can encrypt data and
-     *                            false if it can not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCanEncrypt($canEncrypt)
-    {
-        if ($canEncrypt) {
-            $this->_usage |= self::USAGE_ENCRYPT;
-        } else {
-            $this->_usage &= ~self::USAGE_ENCRYPT;
-        }
-
-        return $this;
-    }
-
-    // }}}
-    // {{{ setUsage()
-
-    /**
-     * Sets usage flags of the sub-key
-     *
-     * @param integer $usage Usage flags
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setUsage($usage)
-    {
-        $this->_usage = (int) $usage;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setHasPrivate()
-
-    /**
-     * Sets whether of not the private key for this sub-key exists in the
-     * keyring
-     *
-     * @param boolean $hasPrivate true if the private key for this sub-key
-     *                            exists in the keyring and false if it does
-     *                            not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setHasPrivate($hasPrivate)
-    {
-        $this->_hasPrivate = ($hasPrivate) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setRevoked()
-
-    /**
-     * Sets whether or not this sub-key is revoked
-     *
-     * @param boolean $isRevoked whether or not this sub-key is revoked.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setRevoked($isRevoked)
-    {
-        $this->_isRevoked = ($isRevoked) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ parse()
-
-    /**
-     * Parses a sub-key object from a sub-key string
-     *
-     * See <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for information
-     * on how the sub-key string is parsed.
-     *
-     * @param string $string the string containing the sub-key.
-     *
-     * @return Crypt_GPG_SubKey the sub-key object parsed from the string.
-     */
-    public static function parse($string)
-    {
-        $tokens = explode(':', $string);
-
-        $subKey = new Crypt_GPG_SubKey();
-
-        $subKey->setId($tokens[4]);
-        $subKey->setLength($tokens[2]);
-        $subKey->setAlgorithm($tokens[3]);
-        $subKey->setCreationDate(self::_parseDate($tokens[5]));
-        $subKey->setExpirationDate(self::_parseDate($tokens[6]));
-
-        if ($tokens[1] == 'r') {
-            $subKey->setRevoked(true);
-        }
-
-        $usage = 0;
-        $usage_map = array(
-            'a' => self::USAGE_AUTHENTICATION,
-            'c' => self::USAGE_CERTIFY,
-            'e' => self::USAGE_ENCRYPT,
-            's' => self::USAGE_SIGN,
-        );
-
-        foreach ($usage_map as $key => $flag) {
-            if (strpos($tokens[11], $key) !== false) {
-                $usage |= $flag;
-            }
-        }
-
-        $subKey->setUsage($usage);
-
-        return $subKey;
-    }
-
-    // }}}
-    // {{{ _parseDate()
-
-    /**
-     * Parses a date string as provided by GPG into a UNIX timestamp
-     *
-     * @param string $string the date string.
-     *
-     * @return integer the UNIX timestamp corresponding to the provided date
-     *                 string.
-     */
-    private static function _parseDate($string)
-    {
-        if ($string == '') {
-            $timestamp = 0;
-        } else {
-            // all times are in UTC according to GPG documentation
-            $timeZone = new DateTimeZone('UTC');
-
-            if (strpos($string, 'T') === false) {
-                // interpret as UNIX timestamp
-                $string = '@' . $string;
-            }
-
-            $date = new DateTime($string, $timeZone);
-
-            // convert to UNIX timestamp
-            $timestamp = intval($date->format('U'));
-        }
-
-        return $timestamp;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPG/UserId.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,378 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a data class representing a GPG user id
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-// {{{ class Crypt_GPG_UserId
-
-/**
- * A class for GPG user id information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method. User id objects are members of a {@link Crypt_GPG_Key} object.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- * @see       Crypt_GPG_Key::getUserIds()
- */
-class Crypt_GPG_UserId
-{
-    // {{{ class properties
-
-    /**
-     * The name field of this user id
-     *
-     * @var string
-     */
-    private $_name = '';
-
-    /**
-     * The comment field of this user id
-     *
-     * @var string
-     */
-    private $_comment = '';
-
-    /**
-     * The email field of this user id
-     *
-     * @var string
-     */
-    private $_email = '';
-
-    /**
-     * Whether or not this user id is revoked
-     *
-     * @var boolean
-     */
-    private $_isRevoked = false;
-
-    /**
-     * Whether or not this user id is valid
-     *
-     * @var boolean
-     */
-    private $_isValid = true;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new user id
-     *
-     * User ids can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  name</kbd>    - the name field of the user id.
-     * - <kbd>string  comment</kbd> - the comment field of the user id.
-     * - <kbd>string  email</kbd>   - the email field of the user id.
-     * - <kbd>boolean valid</kbd>   - whether or not the user id is valid.
-     * - <kbd>boolean revoked</kbd> - whether or not the user id is revoked.
-     *
-     * @param Crypt_GPG_UserId|string|array $userId optional. Either an
-     *        existing user id object, which is copied; a user id string, which
-     *        is parsed; or an array of initial values.
-     */
-    public function __construct($userId = null)
-    {
-        // parse from string
-        if (is_string($userId)) {
-            $userId = self::parse($userId);
-        }
-
-        // copy from object
-        if ($userId instanceof Crypt_GPG_UserId) {
-            $this->_name      = $userId->_name;
-            $this->_comment   = $userId->_comment;
-            $this->_email     = $userId->_email;
-            $this->_isRevoked = $userId->_isRevoked;
-            $this->_isValid   = $userId->_isValid;
-        }
-
-        // initialize from array
-        if (is_array($userId)) {
-            if (array_key_exists('name', $userId)) {
-                $this->setName($userId['name']);
-            }
-
-            if (array_key_exists('comment', $userId)) {
-                $this->setComment($userId['comment']);
-            }
-
-            if (array_key_exists('email', $userId)) {
-                $this->setEmail($userId['email']);
-            }
-
-            if (array_key_exists('revoked', $userId)) {
-                $this->setRevoked($userId['revoked']);
-            }
-
-            if (array_key_exists('valid', $userId)) {
-                $this->setValid($userId['valid']);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getName()
-
-    /**
-     * Gets the name field of this user id
-     *
-     * @return string the name field of this user id.
-     */
-    public function getName()
-    {
-        return $this->_name;
-    }
-
-    // }}}
-    // {{{ getComment()
-
-    /**
-     * Gets the comments field of this user id
-     *
-     * @return string the comments field of this user id.
-     */
-    public function getComment()
-    {
-        return $this->_comment;
-    }
-
-    // }}}
-    // {{{ getEmail()
-
-    /**
-     * Gets the email field of this user id
-     *
-     * @return string the email field of this user id.
-     */
-    public function getEmail()
-    {
-        return $this->_email;
-    }
-
-    // }}}
-    // {{{ isRevoked()
-
-    /**
-     * Gets whether or not this user id is revoked
-     *
-     * @return boolean true if this user id is revoked and false if it is not.
-     */
-    public function isRevoked()
-    {
-        return $this->_isRevoked;
-    }
-
-    // }}}
-    // {{{ isValid()
-
-    /**
-     * Gets whether or not this user id is valid
-     *
-     * @return boolean true if this user id is valid and false if it is not.
-     */
-    public function isValid()
-    {
-        return $this->_isValid;
-    }
-
-    // }}}
-    // {{{ __toString()
-
-    /**
-     * Gets a string representation of this user id
-     *
-     * The string is formatted as:
-     * <b><kbd>name (comment) <email-address></kbd></b>.
-     *
-     * @return string a string representation of this user id.
-     */
-    public function __toString()
-    {
-        $components = array();
-
-        if (mb_strlen($this->_name, '8bit') > 0) {
-            $components[] = $this->_name;
-        }
-
-        if (mb_strlen($this->_comment, '8bit') > 0) {
-            $components[] = '(' . $this->_comment . ')';
-        }
-
-        if (mb_strlen($this->_email, '8bit') > 0) {
-            $components[] = '<' . $this->_email. '>';
-        }
-
-        return implode(' ', $components);
-    }
-
-    // }}}
-    // {{{ setName()
-
-    /**
-     * Sets the name field of this user id
-     *
-     * @param string $name the name field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setName($name)
-    {
-        $this->_name = strval($name);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setComment()
-
-    /**
-     * Sets the comment field of this user id
-     *
-     * @param string $comment the comment field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setComment($comment)
-    {
-        $this->_comment = strval($comment);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setEmail()
-
-    /**
-     * Sets the email field of this user id
-     *
-     * @param string $email the email field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setEmail($email)
-    {
-        $this->_email = strval($email);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setRevoked()
-
-    /**
-     * Sets whether or not this user id is revoked
-     *
-     * @param boolean $isRevoked whether or not this user id is revoked.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setRevoked($isRevoked)
-    {
-        $this->_isRevoked = ($isRevoked) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setValid()
-
-    /**
-     * Sets whether or not this user id is valid
-     *
-     * @param boolean $isValid whether or not this user id is valid.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setValid($isValid)
-    {
-        $this->_isValid = ($isValid) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ parse()
-
-    /**
-     * Parses a user id object from a user id string
-     *
-     * A user id string is of the form:
-     * <b><kbd>name (comment) <email-address></kbd></b> with the <i>comment</i>
-     * and <i>email-address</i> fields being optional.
-     *
-     * @param string $string the user id string to parse.
-     *
-     * @return Crypt_GPG_UserId the user id object parsed from the string.
-     */
-    public static function parse($string)
-    {
-        $userId  = new Crypt_GPG_UserId();
-        $name    = '';
-        $email   = '';
-        $comment = '';
-
-        // get email address from end of string if it exists
-        $matches = array();
-        if (preg_match('/^(.*?)<([^>]+)>$/', $string, $matches) === 1) {
-            $string = trim($matches[1]);
-            $email  = $matches[2];
-        }
-
-        // get comment from end of string if it exists
-        $matches = array();
-        if (preg_match('/^(.+?) \(([^\)]+)\)$/', $string, $matches) === 1) {
-            $string  = $matches[1];
-            $comment = $matches[2];
-        }
-
-        // there can be an email without a name
-        if (!$email && preg_match('/^[\S]+@[\S]+$/', $string, $matches) === 1) {
-            $email = $string;
-        } else {
-            $name = $string;
-        }
-
-        $userId->setName($name);
-        $userId->setComment($comment);
-        $userId->setEmail($email);
-
-        return $userId;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
--- a/vendor/pear/crypt_gpg/Crypt/GPGAbstract.php	Wed Oct 08 09:03:29 2025 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,464 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This package provides an object oriented interface to GNU Privacy
- * Guard (GPG). It requires the GPG executable to be on the system.
- *
- * Though GPG can support symmetric-key cryptography, this package is intended
- * only to facilitate public-key cryptography.
- *
- * This file contains an abstract implementation of a user of the
- * {@link Crypt_GPG_Engine} class.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/>
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
- * @link      http://www.gnupg.org/
- */
-
-/**
- * GPG key class
- */
-require_once 'Crypt/GPG/Key.php';
-
-/**
- * GPG sub-key class
- */
-require_once 'Crypt/GPG/SubKey.php';
-
-/**
- * GPG user id class
- */
-require_once 'Crypt/GPG/UserId.php';
-
-/**
- * GPG process and I/O engine class
- */
-require_once 'Crypt/GPG/Engine.php';
-
-// {{{ class Crypt_GPGAbstract
-
-/**
- * Base class for implementing a user of {@link Crypt_GPG_Engine}
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2013 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-abstract class Crypt_GPGAbstract
-{
-    // {{{ class error constants
-
-    /**
-     * Error code returned when there is no error.
-     */
-    const ERROR_NONE = 0;
-
-    /**
-     * Error code returned when an unknown or unhandled error occurs.
-     */
-    const ERROR_UNKNOWN = 1;
-
-    /**
-     * Error code returned when a bad passphrase is used.
-     */
-    const ERROR_BAD_PASSPHRASE = 2;
-
-    /**
-     * Error code returned when a required passphrase is missing.
-     */
-    const ERROR_MISSING_PASSPHRASE = 3;
-
-    /**
-     * Error code returned when a key that is already in the keyring is
-     * imported.
-     */
-    const ERROR_DUPLICATE_KEY = 4;
-
-    /**
-     * Error code returned the required data is missing for an operation.
-     *
-     * This could be missing key data, missing encrypted data or missing
-     * signature data.
-     */
-    const ERROR_NO_DATA = 5;
-
-    /**
-     * Error code returned when an unsigned key is used.
-     */
-    const ERROR_UNSIGNED_KEY = 6;
-
-    /**
-     * Error code returned when a key that is not self-signed is used.
-     */
-    const ERROR_NOT_SELF_SIGNED = 7;
-
-    /**
-     * Error code returned when a public or private key that is not in the
-     * keyring is used.
-     */
-    const ERROR_KEY_NOT_FOUND = 8;
-
-    /**
-     * Error code returned when an attempt to delete public key having a
-     * private key is made.
-     */
-    const ERROR_DELETE_PRIVATE_KEY = 9;
-
-    /**
-     * Error code returned when one or more bad signatures are detected.
-     */
-    const ERROR_BAD_SIGNATURE = 10;
-
-    /**
-     * Error code returned when there is a problem reading GnuPG data files.
-     */
-    const ERROR_FILE_PERMISSIONS = 11;
-
-    /**
-     * Error code returned when a key could not be created.
-     */
-    const ERROR_KEY_NOT_CREATED = 12;
-
-    /**
-     * Error code returned when bad key parameters are used during key
-     * generation.
-     */
-    const ERROR_BAD_KEY_PARAMS = 13;
-
-    // }}}
-    // {{{ other class constants
-
-    /**
-     * URI at which package bugs may be reported.
-     */
-    const BUG_URI = 'http://pear.php.net/bugs/report.php?package=Crypt_GPG';
-
-    // }}}
-    // {{{ protected class properties
-
-    /**
-     * Engine used to control the GPG subprocess
-     *
-     * @var Crypt_GPG_Engine
-     *
-     * @see Crypt_GPGAbstract::setEngine()
-     */
-    protected $engine = null;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new GPG object
-     *
-     * Available options are:
-     *
-     * - <kbd>string  homedir</kbd>        - the directory where the GPG
-     *                                       keyring files are stored. If not
-     *                                       specified, Crypt_GPG uses the
-     *                                       default of <kbd>~/.gnupg</kbd>.
-     * - <kbd>string  publicKeyring</kbd>  - the file path of the public
-     *                                       keyring. Use this if the public
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/pubring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  privateKeyring</kbd> - the file path of the private
-     *                                       keyring. Use this if the private
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/secring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  trustDb</kbd>        - the file path of the web-of-trust
-     *                                       database. Use this if the trust
-     *                                       database is not in the homedir, or
-     *                                       if the database is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       trust database with this option
-     *                                       (/foo/bar/trustdb.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  binary</kbd>         - the location of the GPG binary. If
-     *                                       not specified, the driver attempts
-     *                                       to auto-detect the GPG binary
-     *                                       location using a list of known
-     *                                       default locations for the current
-     *                                       operating system. The option
-     *                                       <kbd>gpgBinary</kbd> is a
-     *                                       deprecated alias for this option.
-     * - <kbd>string  agent</kbd>          - the location of the GnuPG agent
-     *                                       binary. The gpg-agent is only
-     *                                       used for GnuPG 2.x. If not
-     *                                       specified, the engine attempts
-     *                                       to auto-detect the gpg-agent
-     *                                       binary location using a list of
-     *                                       know default locations for the
-     *                                       current operating system.
-     * - <kbd>string|false gpgconf</kbd>   - the location of the GnuPG conf
-     *                                       binary. The gpgconf is only
-     *                                       used for GnuPG >= 2.1. If not
-     *                                       specified, the engine attempts
-     *                                       to auto-detect the location using
-     *                                       a list of know default locations.
-     *                                       When set to FALSE `gpgconf --kill`
-     *                                       will not be executed via destructor.
-     * - <kbd>string digest-algo</kbd>     - Sets the message digest algorithm.
-     * - <kbd>string cipher-algo</kbd>     - Sets the symmetric cipher.
-     * - <kbd>boolean strict</kbd>         - In strict mode clock problems on
-     *                                       subkeys and signatures are not ignored
-     *                                       (--ignore-time-conflict
-     *                                       and --ignore-valid-from options)
-     * - <kbd>mixed debug</kbd>            - whether or not to use debug mode.
-     *                                       When debug mode is on, all
-     *                                       communication to and from the GPG
-     *                                       subprocess is logged. This can be
-     *                                       useful to diagnose errors when
-     *                                       using Crypt_GPG.
-     *
-     * @param array $options optional. An array of options used to create the
-     *                       GPG object. All options are optional and are
-     *                       represented as key-value pairs.
-     *
-     * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
-     *         and cannot be created. This can happen if <kbd>homedir</kbd> is
-     *         not specified, Crypt_GPG is run as the web user, and the web
-     *         user has no home directory. This exception is also thrown if any
-     *         of the options <kbd>publicKeyring</kbd>,
-     *         <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
-     *         specified but the files do not exist or are are not readable.
-     *         This can happen if the user running the Crypt_GPG process (for
-     *         example, the Apache user) does not have permission to read the
-     *         files.
-     *
-     * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
-     *         if no <kbd>binary</kbd> is provided and no suitable binary could
-     *         be found.
-     *
-     * @throws PEAR_Exception if the provided <kbd>agent</kbd> is invalid, or
-     *         if no <kbd>agent</kbd> is provided and no suitable gpg-agent
-     *         cound be found.
-     */
-    public function __construct(array $options = array())
-    {
-        $this->setEngine(new Crypt_GPG_Engine($options));
-    }
-
-    // }}}
-    // {{{ setEngine()
-
-    /**
-     * Sets the I/O engine to use for GnuPG operations
-     *
-     * Normally this method does not need to be used. It provides a means for
-     * dependency injection.
-     *
-     * @param Crypt_GPG_Engine $engine the engine to use.
-     *
-     * @return Crypt_GPGAbstract the current object, for fluent interface.
-     */
-    public function setEngine(Crypt_GPG_Engine $engine)
-    {
-        $this->engine = $engine;
-        return $this;
-    }
-
-    // }}}
-    // {{{ getVersion()
-
-    /**
-     * Returns version of the engine (GnuPG) used for operation.
-     *
-     * @return string GnuPG version.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function getVersion()
-    {
-        return $this->engine->getVersion();
-    }
-
-    // }}}
-    // {{{ _getKeys()
-
-    /**
-     * Gets the available keys in the keyring
-     *
-     * Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
-     * the first section of <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
-     * description of how the GPG command output is parsed.
-     *
-     * @param string $keyId optional. Only keys with that match the specified
-     *                      pattern are returned. The pattern may be part of
-     *                      a user id, a key id or a key fingerprint. If not
-     *                      specified, all keys are returned.
-     *
-     * @return array an array of {@link Crypt_GPG_Key} objects. If no keys
-     *               match the specified <kbd>$keyId</kbd> an empty array is
-     *               returned.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Key
-     */
-    protected function _getKeys($keyId = '')
-    {
-        // get private key fingerprints
-        if ($keyId == '') {
-            $operation = '--list-secret-keys';
-        } else {
-            $operation = '--utf8-strings --list-secret-keys ' . escapeshellarg($keyId);
-        }
-
-        // According to The file 'doc/DETAILS' in the GnuPG distribution, using
-        // double '--with-fingerprint' also prints the fingerprint for subkeys.
-        $arguments = array(
-            '--with-colons',
-            '--with-fingerprint',
-            '--with-fingerprint',
-            '--fixed-list-mode'
-        );
-
-        $output = '';
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $privateKeyFingerprints = array();
-
-        foreach (explode(PHP_EOL, $output) as $line) {
-            $lineExp = explode(':', $line);
-            if ($lineExp[0] == 'fpr') {
-                $privateKeyFingerprints[] = $lineExp[9];
-            }
-        }
-
-        // get public keys
-        if ($keyId == '') {
-            $operation = '--list-public-keys';
-        } else {
-            $operation = '--utf8-strings --list-public-keys ' . escapeshellarg($keyId);
-        }
-
-        $output = '';
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $keys   = array();
-        $key    = null; // current key
-        $subKey = null; // current sub-key
-
-        foreach (explode(PHP_EOL, $output) as $line) {
-            $lineExp = explode(':', $line);
-
-            if ($lineExp[0] == 'pub') {
-
-                // new primary key means last key should be added to the array
-                if ($key !== null) {
-                    $keys[] = $key;
-                }
-
-                $key = new Crypt_GPG_Key();
-
-                $subKey = Crypt_GPG_SubKey::parse($line);
-                $key->addSubKey($subKey);
-
-            } elseif ($lineExp[0] == 'sub') {
-
-                $subKey = Crypt_GPG_SubKey::parse($line);
-                $key->addSubKey($subKey);
-
-            } elseif ($lineExp[0] == 'fpr') {
-
-                $fingerprint = $lineExp[9];
-
-                // set current sub-key fingerprint
-                $subKey->setFingerprint($fingerprint);
-
-                // if private key exists, set has private to true
-                if (in_array($fingerprint, $privateKeyFingerprints)) {
-                    $subKey->setHasPrivate(true);
-                }
-
-            } elseif ($lineExp[0] == 'uid') {
-
-                $string = stripcslashes($lineExp[9]); // as per documentation
-                $userId = new Crypt_GPG_UserId($string);
-
-                if ($lineExp[1] == 'r') {
-                    $userId->setRevoked(true);
-                }
-
-                $key->addUserId($userId);
-
-            }
-        }
-
-        // add last key
-        if ($key !== null) {
-            $keys[] = $key;
-        }
-
-        return $keys;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>