/* t-stream.c
 *        Copyright (C) 2002 Timo Schulz
 *
 * This file is part of OpenCDK.
 *
 * OpenCDK 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.
 *
 * OpenCDK 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 OpenCDK; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>

#include "opencdk.h"

/* we need this for _cdk_stream_get_opaque */
#include "../src/main.h"
#include "../src/filters.h"
#include "../src/stream.h"


int
stream_test_filters (int literal, int compress, int armor, int encrypt)
{
  char buf[128];
  cdk_stream_t s;
  cdk_dek_t dek;
  int rc, i;

  rc = cdk_stream_new ("test.asc", &s);
  if (rc)
    {
      printf ("cdk_stream_new: `%s'\n", cdk_strerror (rc));
      return -1;
    }
  
  if (armor)
    cdk_stream_set_armor_flag (s, CDK_ARMOR_MESSAGE);
  if (encrypt)
    {
      rc = cdk_dek_new (&dek);
      if (rc)
        {
          cdk_stream_close (s);
          return rc;
        }
      cdk_dek_set_cipher( dek, CDK_CIPHER_TWOFISH );
      cdk_stream_set_cipher_flag (s, dek, 0);
    }
  if (compress)
    cdk_stream_set_compress_flag (s, CDK_COMPRESS_ZLIB, 5);
  if (literal)
    cdk_stream_set_literal_flag (s, 0, "test.asc");

  cdk_stream_set_cache (s, 1);
  /* write a marker packet we won't filter! */
  buf[0] = (0x80 | (10<<2));
  buf[1] = 3;
  buf[2] = 0x50;
  buf[3] = 0x47;
  buf[4] = 0x50;
  cdk_stream_write (s, buf, 5);
  cdk_stream_set_cache (s, 0);

  for (i = 0; i < 512; i++)
    {
      switch (i % 4)
        {
        case 0: strcpy (buf, "Hello World!\n"); break;
        case 1: strcpy (buf, "You won't believe it.\n"); break;
        case 2: strcpy (buf, "Haha, chicks will laugh about it?\n"); break;
        case 3: strcpy (buf, "1..2..3 the police is coming.\n"); break;
        }
      cdk_stream_write (s, buf, strlen (buf));
    }

  rc = cdk_stream_close (s);
  if (rc)
    printf ("cdk_stream_close: `%s'\n", cdk_strerror (rc));
  cdk_free (dek);
  return rc;
}


static char *
read_ascii_data (const char *file, int *r_nbytes)
{
  struct stat statbuf;
  FILE *fp;
  char *p;

  fp = fopen (file, "r");
  if (!fp)
    return NULL;
  if (fstat (fileno (fp), &statbuf))
    {
      fclose (fp);
      return NULL;
    }
  *r_nbytes = statbuf.st_size;
  p = cdk_calloc (1, *r_nbytes + 1);
  if (!p)
    {
      fclose (fp);
      return NULL;
    }
  *r_nbytes = fread (p, 1, *r_nbytes, fp);
  p[*r_nbytes] = '\0';
  fclose (fp);

  return p;
}

  

int
stream_test_filters_tmp_ascii (void)
{
  cdk_stream_t s;
  char *pk;
  size_t nbytes;
  int c, rc;

  pk = read_ascii_data ("ts.asc", &nbytes);
  if (!pk)
    {
      printf ("could not read armored key: %s\n", strerror (errno));
      return -1;
    }  
  
  s = cdk_stream_tmp_from_mem (pk, nbytes);
  if (!s)
    {
      printf ("stream_tmp: `%s'\n", cdk_strerror (CDK_Out_Of_Core));
      return -1;
    }

  #if 0
  c = cdk_stream_get_length (s);
  printf ("length of stream `%d'\n", c);
  #endif

  cdk_stream_set_armor_flag (s, 0);
  
  while ((c = cdk_stream_getc (s)) != -1)
    printf ("%c", c);

  rc = cdk_stream_close (s);
  if (rc)
    printf ("stream_close: `%s'\n", cdk_strerror (rc));
  cdk_free (pk);
  return 0;
}


int
stream_test_filters_tmp_both (void)
{
  cdk_stream_t s;
  char *p;
  size_t nbytes;
  int rc, c;

  p = read_ascii_data ("dat.lit", &nbytes);
  if (!p)
    {
      printf ("could not read armored data: `%s'\n", strerror (errno));
      return -1;
    }

  s = cdk_stream_tmp_from_mem (p, nbytes);
  if (!s)
    {
      printf ("stream_tmp: `%s'\n", cdk_strerror (CDK_Out_Of_Core));
      return -1;
    }

  cdk_stream_set_literal_flag (s, 0, NULL);
  cdk_stream_set_armor_flag (s, 0);

  while ((c = cdk_stream_getc (s)) != -1)
    printf ("%c", c);

  rc = cdk_stream_close (s);
  if (rc)
    printf ("stream_close: `%s'\n", cdk_strerror (rc));
  return 0;
}


int
stream_encrypt (char *file)
{
  int rc;
  cdk_ctx_t hd;

  cdk_handle_new (&hd);
  rc = cdk_file_encrypt (hd, NULL, file, "out.gpg");
  if (rc)
    printf ("encrypt file %s: `%s'\n", file, cdk_strerror (rc));
  cdk_handle_free (hd);
  return rc;
}


int
stream_encrypt_pk (char *user, char *file)
{
  int rc;
  cdk_ctx_t hd;
  cdk_strlist_t recp = NULL;
  cdk_keydb_hd_t db;
  
  cdk_handle_new (&hd);
  cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, "ts.gpg", 6);
  cdk_strlist_add (&recp, user);

  cdk_handle_set_keydb (hd, db);
  rc = cdk_file_encrypt (hd, recp, file, "out.gpg");
  if (rc)
    printf ("encrypt_file %s: `%s'\n", file, cdk_strerror (rc));
  cdk_handle_free (hd);
  cdk_strlist_free (recp);
  return rc;
}


int
stream_trustdb (char *db)
{
  cdk_stream_t s;
  cdk_pkt_userid_t u;
  int rc, valid;

  rc = cdk_stream_open (db, &s);
  if (rc)
    {
      printf ("stream_open: `%s'\n", cdk_strerror (rc));
      return -1;
    }
  u = cdk_calloc (1, sizeof *u + 128);
  strcpy (u->name, "Timo Schulz <ts@winpt.org>");
  u->len = strlen (u->name);
  rc = cdk_trustdb_get_validity (s, u, &valid);
  if (!rc)
      printf ("Validity of `%s': %d\n", u->name, valid);

  cdk_stream_close (s);
  cdk_free (u);
  
  return 0;
}


const char *
get_sig_status (int id)
{
  const char *s = "unknown error";
  switch (id)
    {
    case CDK_SIGSTAT_NONE: s = "no signature"; break;
    case CDK_SIGSTAT_GOOD: s = "good signature"; break;
    case CDK_SIGSTAT_BAD : s = "bad signature"; break;
    case CDK_SIGSTAT_NOKEY: s = "no key for checking the signature"; break;
    }
  return s;
}


const char *
get_sig_time (unsigned long timestamp)
{
  static char buf[128];
  struct tm * tmbuf;
  
  tmbuf = localtime ((const time_t *)&timestamp);
  sprintf (buf, "%04d-%02d-%02d",
           tmbuf->tm_year+1900, tmbuf->tm_mon+1, tmbuf->tm_mday);
  return buf;
}


const char *
get_sig_algo (int pubkey_algo)
{
  switch (pubkey_algo)
    {
    case CDK_PK_RSA_E:
    case CDK_PK_RSA_S:
    case CDK_PK_RSA  : return "RSA";
    case CDK_PK_ELG  :
    case CDK_PK_ELG_E: return "ELG";
    case CDK_PK_DSA  : return "DSA";
    default           : return "???";
    }
  return NULL;
}


int
stream_decrypt (char *file, int with_pass)
{
  int rc, sigstat, created, pkalgo;
  const unsigned long * keyid;
  cdk_ctx_t hd;
  cdk_keydb_hd_t db, p_db;

  if (!with_pass)
    cdk_keydb_new (&db, CDK_DBTYPE_SK_KEYRING, "sec.gpg", 7);
  else
    cdk_keydb_new (&db, CDK_DBTYPE_SK_KEYRING, "sec-with-pwd.gpg", 16);
  cdk_keydb_new(&p_db, CDK_DBTYPE_PK_KEYRING, "pub.gpg", 7);
  cdk_handle_new (&hd);
  cdk_handle_set_keydb (hd, db);
  cdk_handle_set_keydb (hd, p_db);
  rc = cdk_file_decrypt (hd, file, "out.gpg");
  if (rc)
    printf ("decrypt file %s: `%s'\n", file, cdk_strerror (rc));
  sigstat = cdk_sig_get_ulong_attr (hd, 0, CDK_ATTR_STATUS);
  if (sigstat)
    {
      keyid = cdk_sig_get_data_attr (hd, 0, CDK_ATTR_KEYID);
      created = cdk_sig_get_ulong_attr (hd, 0, CDK_ATTR_CREATED);
      pkalgo = cdk_sig_get_ulong_attr (hd, 0, CDK_ATTR_ALGO_PK);
      printf ("(%s) keyid %08lX%08lX algo %s created %s\n",
              get_sig_status (sigstat), keyid[0], keyid[1],
              get_sig_algo (pkalgo), get_sig_time (created));
    }
  cdk_handle_free (hd);
  return rc;
}


int
stream_hash (char * file, char * algo)
{
  md_filter_t * mfx;
  cdk_stream_t s;
  int rc;

  rc = cdk_stream_open (file, &s);
  if (rc)
    {
      printf ("stream_open %s: `%s'\n", file, cdk_strerror (rc));
      return -1;
    }
  rc = cdk_stream_set_hash_flag (s, atol (algo));
  cdk_stream_read (s, NULL, 0);
  mfx = _cdk_stream_get_opaque (s, fHASH);
  printf ("hash %s...\n", file);
  if (mfx && mfx->md)
    {
      unsigned char *md = cdk_md_read (mfx->md, 0);
      size_t dlen = cdk_md_get_algo_dlen (mfx->digest_algo), i;
      for (i = 0; i < dlen; i++)
        printf ("%02X ", md[i]);
      printf ("\n");
      cdk_md_close (mfx->md);
    }
  cdk_stream_close (s);
  return 0;
}

int
stream_test_armor (char *file)
{
  cdk_stream_t s;
  int rc;
    
  rc = cdk_stream_open (file, &s);
  if (rc)
    {
      printf ("stream_open %s: `%s'\n", file, cdk_strerror (rc));
      return -1;
    }
  printf ("use_armor_filter=%d\n", cdk_armor_filter_use (s));
  cdk_stream_close (s);
  return 0;
}


int
stream_test_keyblock (char *file)
{
  cdk_stream_t s;
  cdk_kbnode_t knode;
  int rc;

  rc = cdk_stream_open (file, &s);
  if (rc)
    {
      printf ("stream_open %s: `%s'\n", file, cdk_strerror (rc));
      return -1;
    }
  if (cdk_armor_filter_use (s))
    cdk_stream_set_armor_flag (s, 0);;
  rc = cdk_keydb_get_keyblock (s, &knode);
  printf ("rc=%d knode=%p\n", rc, knode);

  cdk_stream_close (s);
  cdk_kbnode_release (knode);
  return 0;
}


static int
stream_verify (char *file)
{
  cdk_ctx_t hd;
  cdk_keydb_hd_t db;
  int rc;
  
  cdk_handle_new (&hd);
  cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, "pub.gpg", 7);
  cdk_handle_set_keydb (hd, db);
  rc = cdk_file_verify (hd, file, "clear.txt");
  if (rc)
    printf ("verify_file %s: `%s'\n", file, cdk_strerror (rc));
  cdk_handle_free (hd);
  return 0;
}


static int
stream_clearsign (char *file)
{
  cdk_ctx_t hd;
  cdk_strlist_t locusr = NULL;
  cdk_keydb_hd_t db;
  int rc ;
  
  cdk_handle_new (&hd);
  cdk_keydb_new (&db, CDK_DBTYPE_SK_KEYRING, "sec.gpg", 7);
  cdk_strlist_add (&locusr, "twoaday@daredevil");
      //rc = cdk_file_clearsign (hd, locusr, file, "out.asc");
  if (rc)
    printf ("clearsign_file %s: `%s'\n", file, cdk_strerror (rc));
  cdk_handle_free (hd);
  cdk_strlist_free (locusr);
  return 0;
}


int
stream_test_textmode (void)
{
  cdk_stream_t s;
  int rc;

  rc = cdk_stream_new ("literal.txm", &s);
  if (rc)
    {
      printf ("stream_new: `%s'\n", cdk_strerror (rc));
      return -1;
    }
  cdk_stream_set_text_flag (s, NULL);
  cdk_stream_write (s, "hallo\n", 6);
  rc = cdk_stream_close (s);
  if (rc)
    printf ("stream_close `%s'\n", cdk_strerror (rc));
  return 0;
}


int
test_stream_kbnode (const char * file)
{
  cdk_kbnode_t node = NULL, n, ctx = NULL;
  cdk_stream_t inp;
  unsigned char buf[8192];
  int rc, nread;

  rc = cdk_stream_open (file, &inp);
  if (rc)
    {
      fprintf (stderr, "stream open `%s': %s\n", file, cdk_strerror (rc));
      return -1;
    }

  nread = cdk_stream_read (inp, buf, sizeof buf-1);
  cdk_stream_close (inp);

  rc = cdk_kbnode_read_from_mem (&node, buf, nread);
  if (rc)
    fprintf (stderr, "read_from_mem: %s\n", cdk_strerror (rc));

  while ((n = cdk_kbnode_walk (node, &ctx, 0)))
    {
      CDK_PACKET * pkt = cdk_kbnode_get_packet (n);
      fprintf (stderr, "pkttype=%d\n", pkt->pkttype);
    }

  cdk_kbnode_write_to_mem (node, buf, &nread);
  cdk_kbnode_release (node);

  /*fwrite (buf, 1, nread, stdout);*/
  return 0;
}


#if TEST
int classify_data (const byte * buf, size_t len);
     
void
test_classify_function (void)
{
  int i;
  const char * s;
  const char * kid [] =
  {
    "0xBF3DF9B4",
    "BF3DF9B4",
    "bf3df9b4",
    "ED4681C9BF3DF9B4",
    "0xED4681C9BF3DF9B4",
    "timo",
    "ts@winpt.org",
    NULL
  };
  for (i = 0, s = kid[i]; kid[i]; i++)
    printf ("classify_data `%s' = %d\n", kid[i],
            classify_data (kid[i], strlen (kid[i])));
  
} 
#endif


#if 0
int
main (int argc, char **argv)
{
  cdk_set_log_level (CDK_LOG_DEBUG);
  return test_stream_kbnode (argc>1? argv[1] : "foo");
  /*stream_test_filters (1, 1, 1, 1);*/
  /*stream_test_filters_tmp_ascii ();*/
  /*stream_test_filters_tmp_both ();*/
  /*stream_trustdb ("trustdb.gpg");*/
  #if 0
  if (argc > 1)
    stream_clearsign (argv[1]);
  #endif
  if (argc > 1)
    stream_verify (argv[1]);
  #if 0
  if (argc > 1)
    stream_decrypt (argv[1], argc==3);
  if (argc > 1)
    stream_encrypt (argv[1]);
  if (argc == 2)
    stream_encrypt_pk ("ts@winpt.org", argv[1]);
  if (argc == 3)
    stream_hash (argv[1], argv[2]);
#endif
  
  return 0;
}
#endif


int
test_sign (int argc, char ** argv)
{
    cdk_ctx_t hd;
    cdk_keydb_hd_t db;
    cdk_strlist_t locusr = NULL;
    char * s = "/home/twoaday/cvs/gnupg.org/opencdk/tests/sec-with-pwd.gpg";
    const char * test = "Hello World!";
    unsigned char * out = NULL;
    size_t olen = 0;
    int rc;
    
    rc = cdk_keydb_new (&db, CDK_DBTYPE_SK_KEYRING, s, strlen (s));
    assert (!rc);
    rc = cdk_handle_new (&hd);
    assert (!rc);
    cdk_handle_set_keydb (hd, db);
    cdk_handle_set_armor( hd, 1 );
    cdk_strlist_add (&locusr, "opencdk");
    rc = cdk_data_transform (hd, CDK_CRYPTYPE_SIGN, locusr, NULL,
                             test, strlen (test), &out, &olen,
                             CDK_SIGMODE_NORMAL);
    printf ("rc=%d(_%s) out=%p olen=%d\n", rc, cdk_strerror (rc), out, olen);
    if (!rc)
        printf ("%s\n", out);
    
    cdk_strlist_free (locusr);
    cdk_handle_free (hd);
    cdk_keydb_free (db);
    cdk_free (out);
    return 0;
}


int
test_encrypt (int argc, char ** argv)
{
    cdk_ctx_t hd;
    cdk_keydb_hd_t db;
    cdk_strlist_t remusr = NULL;
    char * s = "/home/twoaday/.gnupg/pubring.gpg";
    const char *test = "Hello World!";
    unsigned char * out = NULL;
    size_t olen = 0;
    int rc, cmd = CDK_CRYPTYPE_ENCRYPT;

    rc = cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, s, strlen (s));
    assert (!rc);
    rc = cdk_handle_new (&hd);
    assert (!rc);
    cdk_handle_set_keydb (hd, db);
    cdk_handle_set_armor( hd, 1 );

    cdk_strlist_add (&remusr, "opencdk");
    rc = cdk_data_transform (hd, cmd, NULL, remusr,
                             test, strlen (test), &out, &olen, 0);
    printf ("rc=%d out=%p outlen=%d\n", rc, out, olen);
    if (!rc)
        printf ("%s\n", out);

    cdk_keydb_free (db);
    cdk_strlist_free (remusr);
    cdk_free (out);
    cdk_handle_free (hd);

    return 0;
}


int
test_verify (int argc, char ** argv)
{
    cdk_ctx_t hd;
    cdk_keydb_hd_t db;
    int rc;
    char * s = "/home/twoaday/.gnupg/pubring.cdk";
    const char * st =
        "-----BEGIN PGP MESSAGE-----\n"
        "Version: OpenPrivacy 0.4.2-cvs\n"
        "\n"
        "xA0DAAIRvVcs3MzAfDUByxpiCF9DT05TT0xFPiWDbEhlbGxvIFdvcmxkIcJGBAAR\n"
        "AgAGBQI+JYNsAAoJEL1XLNzMwHw1YHYAn2e58AeNp1aXc76toHRHpoFkb6ChAJ49\n"
        "ey3CPJI/sDoy9NPoa3/vBAiYzA==\n"
        "=jB61\n"
        "-----END PGP MESSAGE-----\n";
    unsigned char * out = NULL;
    size_t olen = 0;

    cdk_set_log_level (CDK_LOG_DEBUG);
    rc = cdk_handle_new (&hd);
    assert (!rc);
    rc = cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, s, strlen (s));
    assert (!rc);
    cdk_handle_set_keydb (hd, db);

    rc = cdk_data_transform (hd, CDK_CRYPTYPE_VERIFY, NULL, NULL,
                             st, strlen (st), &out, &olen, 1);
    printf ("rc=%d out=%p outlen=%d\n", rc, out, olen );
    if( !rc )
        printf ("%s\n", out );

    cdk_free (out);
    cdk_handle_free (hd);
    cdk_keydb_free (db);
    return 0;
}


int
test_import (int argc, char ** argv)
{
    cdk_ctx_t hd;
    cdk_keydb_hd_t db;
    int rc;
    char * s = "/home/twoaday/.gnupg/pubring.cdk";
    const char * pk =
        "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
        "\n"
        "mQDNAzvQJ6kAAAEGANHEToZzlrFEkGmEjIeP9FkQkr5YHi2Epk/YTmObZQZxOetf\n"
        "rCl/V/aJaD4zGV3JaU/cfpipDmghihdEHWggw59BYnrvQY20BBMy79x8d/ptnyST\n"
        "huPGk8nSJ1DtefiDyT+v4L50Mu+0o+axC19+SxmZGWTrNeSJ4kiEICB10OU/jxYa\n"
        "e4B6YURQszsggPDT17w3E2gg3cJfhsdrs5sQuBFeYc2qrawt7xtC1YnEggpmHfRs\n"
        "T3jSyYivl2kzMzyliQAFEbQeSm9obiBRLiBTbWl0aCA8am9obkBzbWl0aC5vcmc+\n"
        "iQDVAwUQO9Anqa+XaTMzPKWJAQHiPQYAuV8Nhda5jYnUaz8MBNesJaUCCZKTzqfv\n"
        "OXtk1klb1t5MrEagMxkomsKIXhpZcF4zYerZ/NwNm+bgU/ELM5I1/kNN7HrKd5yT\n"
        "xWwVTLtOIP06hrlemQtlC+mQfadC9OHN2bHaR3bsUSjiUlkPbD4MApLqm4/WjAJT\n"
        "B/5nb4pdDKdG2DB0WFtrO/eXXe1nWtIZHljQmbAOIkT8WxHRz2MfZKsGUEgukfD7\n"
        "jODCarLM3fYba6NeBQkz4n9rPPphc7yD\n"
        "=PtOU\n"
        "-----END PGP PUBLIC KEY BLOCK-----\n";
    unsigned char * out;
    size_t olen = 0;
    
    rc = cdk_handle_new (&hd);
    assert (!rc);
    rc = cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, s, strlen (s));
    assert (!rc);
    cdk_handle_set_keydb (hd, db);

    rc = cdk_data_transform (hd, CDK_CRYPTYPE_IMPORT, NULL, NULL,
                             pk, strlen (pk), &out, &olen, 0);
    if (!rc)
        printf ("%s", out);
    cdk_handle_free (hd);
    cdk_keydb_free (db);
    cdk_free (out);
    return 0;
}
        
        
int
test_decrypt (int argc, char ** argv)
{
    cdk_ctx_t hd;
    cdk_keydb_hd_t db;
    int rc;
    char * s = "/home/twoaday/cvs/gnupg.org/opencdk/tests/sec-with-pwd.gpg";
    const char * ct =
        "-----BEGIN PGP MESSAGE-----\n"
        "Version: OpenPrivacy 0.4.2-cvs\n"
        "\n"
        "wcBOA/ywzzpSYeBnEAP/W2fLuyjEdXoFxIUq6mgxgbH/t9/2PPEHpk+ZX+X79R7I\n"
        "SHHua/yky6o/4nwYwvXFcnudHjXkN7NqA0qe/qXImN+YnCf9zJFNt31YrI5KGvEz\n"
        "pG0U89U0+vWtOJmCWPGi8FiR/xF6nMX598dhnV/D0Bqo9EM+0VY209pSSgULf9YD\n"
        "/0NQGPQaQy8Ls8JYOWd2NRFBfyNO9vTvayyOjEf7XNPc+XUSx6VEACCefc1mBqn+\n"
        "XW4ZthoAHBNeEBjdWiNvFUsMtiwNI6o3MvO8wJABcuRDT3cqx4vtSBqQpDipXeAX\n"
        "xxS/mlTvPu9UOURbwtRnh/lG8AshydM3EWHGro+ODT6v0kkBSbmIpS0bvcZx2lz0\n"
        "t6kJNfo1ZnPzEu1T7nkWs5AQWfQjDnX0AEDaeqi39qYQilaE4sPobJ1HiRVwVrVo\n"
        "YFDSMaPRxHzaqtwV\n"
        "=geuH\n"
        "-----END PGP MESSAGE-----\n";
    unsigned char * out = NULL;
    size_t olen = 0;

    rc = cdk_handle_new (&hd);
    assert (!rc);
    rc = cdk_keydb_new (&db, CDK_DBTYPE_SK_KEYRING, s, strlen (s));
    assert (!rc);
    cdk_handle_set_keydb (hd, db);

    rc = cdk_data_transform (hd, CDK_CRYPTYPE_DECRYPT, NULL, NULL,
                             ct, strlen (ct), &out, &olen, 0);
    printf ("rc=%d out=%p outlen=%d\n", rc, out, olen);
    if (!rc)
        printf ("%s\n", out);
    
    cdk_handle_free (hd);
    cdk_keydb_free (db);
    cdk_free (out);
    return 0;
}


int
test_keydb_routines (void)
{
    cdk_keydb_hd_t db;
    cdk_kbnode_t node;
    int rc;

    rc = cdk_keydb_new (&db, CDK_DBTYPE_PK_KEYRING, "pubring.gpg", 11);
    if (!rc)
        rc = cdk_keydb_search_start (db, CDK_DBSEARCH_NEXT, NULL);
        /*rc = cdk_keydb_search_start (db, CDK_DBSEARCH_AUTO,
          "0xBF3DF9B4");*/
    printf ("rc=%d\n", rc);
    while (!rc) {
        rc = cdk_keydb_search (db, &node);
        if (!rc) {
            printf ("%s\n",
                    cdk_kbnode_get_attr (node, CDK_PKT_USER_ID, CDK_ATTR_NAME)
                    );
            cdk_kbnode_release (node);
        }
    }
    if (rc)
        printf ("keydb error `%s'\n", cdk_strerror (rc));
    cdk_keydb_free (db);
    return rc;
}


int
main (int argc, char ** argv)
{
    /*test_encrypt (argc, argv);*/
    /*test_decrypt (argc, argv);*/
    /*test_sign (argc, argv);*/
    /*test_verify (argc, argv);*/
    /*test_import (argc, argv);*/
    test_keydb_routines ();
    return 0;
}


