return *cur? 0:-1;
}
+static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp)
+{
+ /* there's no side-effect free way to view key data in GPGME,
+ * so we import the key into a temporary keyring */
+ char tmpdir[_POSIX_PATH_MAX];
+ char tmpfile[_POSIX_PATH_MAX];
+ gpgme_ctx_t tmpctx;
+ gpgme_error_t err;
+ gpgme_engine_info_t engineinfo;
+ gpgme_key_t key;
+ gpgme_user_id_t uid;
+ gpgme_subkey_t subkey;
+ const char* shortid;
+ int len;
+ char date[STRING];
+ int more;
+ int rc = -1;
+
+ snprintf (tmpdir, sizeof(tmpdir), "%s/mutt-gpgme-XXXXXX", Tempdir);
+ if (!mkdtemp (tmpdir))
+ {
+ dprint (1, (debugfile, "Error creating temporary GPGME home\n"));
+ return rc;
+ }
+
+ if ((err = gpgme_new (&tmpctx)) != GPG_ERR_NO_ERROR)
+ {
+ dprint (1, (debugfile, "Error creating GPGME context\n"));
+ goto err_tmpdir;
+ }
+
+ engineinfo = gpgme_ctx_get_engine_info (tmpctx);
+ while (engineinfo && engineinfo->protocol != GPGME_PROTOCOL_OpenPGP)
+ engineinfo = engineinfo->next;
+ if (!engineinfo)
+ {
+ dprint (1, (debugfile, "Error finding GPGME PGP engine\n"));
+ goto err_ctx;
+ }
+
+ err = gpgme_ctx_set_engine_info (tmpctx, GPGME_PROTOCOL_OpenPGP,
+ engineinfo->file_name, tmpdir);
+ if (err != GPG_ERR_NO_ERROR)
+ {
+ dprint (1, (debugfile, "Error setting GPGME context home\n"));
+ goto err_ctx;
+ }
+
+ if ((err = gpgme_op_import (tmpctx, keydata)) != GPG_ERR_NO_ERROR)
+ {
+ dprint (1, (debugfile, "Error importing key\n"));
+ goto err_ctx;
+ }
+
+ mutt_mktemp (tmpfile);
+ *fp = safe_fopen (tmpfile, "w+");
+ if (!*fp)
+ {
+ mutt_perror (tmpfile);
+ goto err_ctx;
+ }
+ unlink (tmpfile);
+
+ err = gpgme_op_keylist_start (tmpctx, NULL, 0);
+ while (!err)
+ {
+ if ((err = gpgme_op_keylist_next (tmpctx, &key)))
+ break;
+ uid = key->uids;
+ subkey = key->subkeys;
+ more = 0;
+ while (subkey)
+ {
+ shortid = subkey->keyid;
+ len = mutt_strlen (subkey->keyid);
+ if (len > 8)
+ shortid += len - 8;
+ strftime (date, sizeof (date), "%Y-%m-%d", localtime (&subkey->timestamp));
+
+ if (!more)
+ fprintf (*fp, "%s %5.5s %d/%8s %s %s\n", more ? "sub" : "pub",
+ gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length,
+ shortid, date, uid->uid);
+ else
+ fprintf (*fp, "%s %5.5s %d/%8s %s\n", more ? "sub" : "pub",
+ gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length,
+ shortid, date);
+ subkey = subkey->next;
+ more = 1;
+ }
+ gpgme_key_release (key);
+ }
+ if (gpg_err_code (err) != GPG_ERR_EOF)
+ {
+ dprint (1, (debugfile, "Error listing keys\n"));
+ goto err_fp;
+ }
+
+ rc = 0;
+
+err_fp:
+ if (rc)
+ {
+ fclose (*fp);
+ *fp = NULL;
+ }
+err_ctx:
+ gpgme_release (tmpctx);
+err_tmpdir:
+ mutt_rmtree (tmpdir);
+
+ return rc;
+}
/*
* Implementation of `pgp_check_traditional'.
/* Copy PGP material to an data container */
armored_data = file_to_data_object (s->fpin, m->offset, m->length);
/* Invoke PGP if needed */
- if (!clearsign || (s->flags & M_VERIFY))
+ if (pgp_keyblock)
+ {
+ pgp_gpgme_extract_keys (armored_data, &pgpout);
+ }
+ else if (!clearsign || (s->flags & M_VERIFY))
{
unsigned int sig_stat = 0;
gpgme_data_t plaintext;
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
+#include <dirent.h>
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
return 0;
}
+/* remove a directory and everything under it */
+int mutt_rmtree (const char* path)
+{
+ DIR* dirp;
+ struct dirent* de;
+ char cur[_POSIX_PATH_MAX];
+ int rc = 0;
+
+ if (!(dirp = opendir (path)))
+ {
+ dprint (1, (debugfile, "mutt_rmtree: error opening directory %s\n", path));
+ return -1;
+ }
+ while ((de = readdir (dirp)))
+ {
+ if (!strcmp (".", de->d_name) || !strcmp ("..", de->d_name))
+ continue;
+
+ snprintf (cur, sizeof (cur), "%s/%s", path, de->d_name);
+ /* XXX make nonrecursive version */
+ if (de->d_type == DT_DIR)
+ rc |= mutt_rmtree (cur);
+ else
+ rc |= unlink (cur);
+ }
+ closedir (dirp);
+
+ rc |= rmdir (path);
+
+ return rc;
+}
+
int mutt_put_file_in_place (const char *path, const char *safe_file, const char *safe_dir)
{
int rv;