/*
* Copyright (C) 1996-7,2007 Michael R. Elkins <me@mutt.org>
* Copyright (c) 1998-2003 Thomas Roessler <roessler@does-not-exist.org>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later
* version.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "mutt.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "mime.h"
#include "pgp.h"
#include "pager.h"
#include "sort.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <locale.h>
#ifdef CRYPT_BACKEND_CLASSIC_PGP
struct pgp_cache
{
char *what;
char *dflt;
struct pgp_cache *next;
};
static struct pgp_cache *id_defaults = NULL;
static char trust_flags[] = "?- +";
static char *pgp_key_abilities (int flags)
{
static char buff[3];
if (!(flags & KEYFLAG_CANENCRYPT))
buff[0] = '-';
else if (flags & KEYFLAG_PREFER_SIGNING)
buff[0] = '.';
else
buff[0] = 'e';
if (!(flags & KEYFLAG_CANSIGN))
buff[1] = '-';
else if (flags & KEYFLAG_PREFER_ENCRYPTION)
buff[1] = '.';
else
buff[1] = 's';
buff[2] = '\0';
return buff;
}
static char pgp_flags (int flags)
{
if (flags & KEYFLAG_REVOKED)
return 'R';
else if (flags & KEYFLAG_EXPIRED)
return 'X';
else if (flags & KEYFLAG_DISABLED)
return 'd';
else if (flags & KEYFLAG_CRITICAL)
return 'c';
else
return ' ';
}
static pgp_key_t pgp_principal_key (pgp_key_t key)
{
if (key->flags & KEYFLAG_SUBKEY && key->parent)
return key->parent;
else
return key;
}
/*
* Format an entry on the PGP key selection menu.
*
* %n number
* %k key id %K key id of the principal key
* %u user id
* %a algorithm %A algorithm of the princ. key
* %l length %L length of the princ. key
* %f flags %F flags of the princ. key
* %c capabilities %C capabilities of the princ. key
* %t trust/validity of the key-uid association
* %[...] date of key using strftime(3)
*/
typedef struct pgp_entry
{
size_t num;
pgp_uid_t *uid;
} pgp_entry_t;
static const char *pgp_entry_fmt (char *dest,
size_t destlen,
size_t col,
char op,
const char *src,
const char *prefix,
const char *ifstring,
const char *elsestring,
unsigned long data,
format_flag flags)
{
char fmt[16];
pgp_entry_t *entry;
pgp_uid_t *uid;
pgp_key_t key, pkey;
int kflags = 0;
int optional = (flags & M_FORMAT_OPTIONAL);
entry = (pgp_entry_t *) data;
uid = entry->uid;
key = uid->parent;
pkey = pgp_principal_key (key);
if (isupper ((unsigned char) op))
key = pkey;
kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS)
| uid->flags;
switch (ascii_tolower (op))
{
case '[':
{
const char *cp;
char buf2[SHORT_STRING], *p;
int do_locales;
struct tm *tm;
size_t len;
p = dest;
cp = src;
if (*cp == '!')
{
do_locales = 0;
cp++;
}
else
do_locales = 1;
len = destlen - 1;
while (len > 0 && *cp != ']')