/*
 * Copyright notice from original mutt:
 * Copyright (C) 1997-2000 Thomas Roessler <roessler@does-not-exist.org>
 *
 * This file is part of mutt-ng, see http://www.muttng.org/.
 * It's licensed under the GNU General Public License,
 * please see the file GPL in the top level source directory.
 */

/* Generally useful, pgp-related functions. */

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#include "mutt.h"
#include "lib.h"
#include "pgplib.h"

#include "lib/mem.h"

const char *pgp_pkalgbytype (unsigned char type)
{
  switch (type) {
  case 1:
    return "RSA";
  case 2:
    return "RSA";
  case 3:
    return "RSA";
  case 16:
    return "ElG";
  case 17:
    return "DSA";
  case 20:
    return "ElG";
  default:
    return "unk";
  }
}



/* unused */

#if 0

static const char *hashalgbytype (unsigned char type)
{
  switch (type) {
  case 1:
    return "MD5";
  case 2:
    return "SHA1";
  case 3:
    return "RIPE-MD/160";
  case 4:
    return "HAVAL";
  default:
    return "unknown";
  }
}

#endif

short pgp_canencrypt (unsigned char type)
{
  switch (type) {
  case 1:
  case 2:
  case 16:
  case 20:
    return 1;
  default:
    return 0;
  }
}

short pgp_cansign (unsigned char type)
{
  switch (type) {
  case 1:
  case 3:
  case 17:
  case 20:
    return 1;
  default:
    return 0;
  }
}

/* return values: 

 * 1 = sign only
 * 2 = encrypt only
 * 3 = both
 */

short pgp_get_abilities (unsigned char type)
{
  return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
}

void pgp_free_sig (pgp_sig_t ** sigp)
{
  pgp_sig_t *sp, *q;

  if (!sigp || !*sigp)
    return;

  for (sp = *sigp; sp; sp = q) {
    q = sp->next;
    mem_free (&sp);
  }

  *sigp = NULL;
}

void pgp_free_uid (pgp_uid_t ** upp)
{
  pgp_uid_t *up, *q;

  if (!upp || !*upp)
    return;
  for (up = *upp; up; up = q) {
    q = up->next;
    pgp_free_sig (&up->sigs);
    mem_free (&up->addr);
    mem_free (&up);
  }

  *upp = NULL;
}

pgp_uid_t *pgp_copy_uids (pgp_uid_t * up, pgp_key_t parent)
{
  pgp_uid_t *l = NULL;
  pgp_uid_t **lp = &l;

  for (; up; up = up->next) {
    *lp = mem_calloc (1, sizeof (pgp_uid_t));
    (*lp)->trust = up->trust;
    (*lp)->flags = up->flags;
    (*lp)->addr = str_dup (up->addr);
    (*lp)->parent = parent;
    lp = &(*lp)->next;
  }

  return l;
}

static void _pgp_free_key (pgp_key_t * kpp)
{
  pgp_key_t kp;

  if (!kpp || !*kpp)
    return;

  kp = *kpp;

  pgp_free_uid (&kp->address);
  mem_free (&kp->keyid);
  mem_free (kpp);
}

pgp_key_t pgp_remove_key (pgp_key_t * klist, pgp_key_t key)
{
  pgp_key_t *last;
  pgp_key_t p, q, r;

  if (!klist || !*klist || !key)
    return NULL;

  if (key->parent && key->parent != key)
    key = key->parent;

  last = klist;
  for (p = *klist; p && p != key; p = p->next)
    last = &p->next;

  if (!p)
    return NULL;

  for (q = p->next, r = p; q && q->parent == p; q = q->next)
    r = q;

  if (r)
    r->next = NULL;

  *last = q;
  return q;
}

void pgp_free_key (pgp_key_t * kpp)
{
  pgp_key_t p, q, r;

  if (!kpp || !*kpp)
    return;

  if ((*kpp)->parent && (*kpp)->parent != *kpp)
    *kpp = (*kpp)->parent;

  /* Order is important here:
   *
   * - First free all children.
   * - If we are an orphan (i.e., our parent was not in the key list),
   *   free our parent.
   * - free ourselves.
   */

  for (p = *kpp; p; p = q) {
    for (q = p->next; q && q->parent == p; q = r) {
      r = q->next;
      _pgp_free_key (&q);
    }
    if (p->parent)
      _pgp_free_key (&p->parent);

    _pgp_free_key (&p);
  }

  *kpp = NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1