#include <string.h>
#include <stdio.h>
#include <glib.h>
#include <gobject/gobject.h>

#include "gxsnmp_hash.h"
#include "gxsnmp_digest.h"
#include "gxsnmp_md2.h"
#include "gxsnmp_md4.h"
#include "gxsnmp_md5.h"
#include "gxsnmp_sha.h"
#include "gxsnmp_ripemd128.h"
#include "gxsnmp_ripemd160.h"

int
main(int argc, char *argv[])
{
  int i, cnt;
  guint j, num;
  guchar *ptr;
  guchar key[20];
  GxsnmpHash *hash;
  GType  type;
  GType *tarray;

  guchar engineid[32]; /* Max 32 bytes as per RFC */

  g_type_init(G_TYPE_DEBUG_NONE);

  if (argc != 3) 
    {
       printf("Usage: %s password engineid\n", argv[0]);
       return 1;
    }

  cnt = 0;
  ptr = argv[2];
  while(*ptr)
    {
      if (cnt > 64)
        {
          printf("engineid too long\n");
          return 1;
        }
      switch(*ptr)
        {
          case ' ':
            ptr++;
            break;
          case '0'...'9':
            if (cnt % 2)
              {
                engineid[cnt/2] |= (*ptr & 0x0f);
              }
            else
              {
                engineid[cnt/2] = (*ptr & 0x0f) << 8;
              }
            ptr++;
            cnt++;
            break;
          case 'a'...'f':
          case 'A'...'F':
            if (cnt % 2)
              {
                engineid[cnt/2] |= ((*ptr & 0x0f) +9);
              }
            else
              {
                engineid[cnt/2] = ((*ptr & 0x0f) +9) << 8;
              }
            ptr++;
            cnt++;
            break;
          default:
            printf("Parse error in engineid at %c\n", *ptr);
            return 1;
        }
    }
  if (cnt % 2)
    {
      printf("Uneven number of characters in engineid\n");
      return 1;
    }

  printf("EngineID:          ");
  for (i=0;i<cnt/2;i++) printf("%02x ", engineid[i]);
  printf("\n");

  /* Register classes */

  type = gxsnmp_md2_get_type();
  type = gxsnmp_md4_get_type();
  type = gxsnmp_md5_get_type();
  type = gxsnmp_sha_get_type();
  type = gxsnmp_ripemd128_get_type();
  type = gxsnmp_ripemd160_get_type();

  /* Get HASH type */
  type = gxsnmp_digest_get_type();

  tarray = g_type_children(type, &num);

  for (j=0;j<num;j++)
    {
      hash = g_object_new (tarray[j], NULL);
      gxsnmp_hash_pw2key(hash, argv[1], strlen(argv[1]), key);
      printf("%s key non-local: ", hash->hashname);
      for (i=0;i<hash->hashlen;i++) printf("%02x ", key[i]);
      printf("\n");
      gxsnmp_hash_reset(hash);
      gxsnmp_hash_localize(hash, key, engineid, cnt/2);
      printf("%s key localized: ", hash->hashname);
      for (i=0;i<hash->hashlen;i++) printf("%02x ", key[i]);
      printf("\n");
      g_object_unref(G_OBJECT(hash));
    }
  return 0;
}

