/*
 * User Defined Function for MySQL
 * Whirlpool (512 bit) and Tiger (192 bits)
 *
 * Using a modified version of Crypto++
 * (type declaration for byte moved into namespace)
 *
 * Author: Kristian Fiskerstrand
 * Website: http://www.kfwebs.net
 * Project: http://www.kfwebs.net/mysql/ohash
 *
 * Date: 2005-07-31
 * Copyright (C) 2005 Kristian Fiskerstrand
 *
 * CREATE FUNCTION whirlpool RETURNS STRING SONAME 'mysql_ohash.so';
 * CREATE FUNCTION tiger RETURNS STRING SONAME 'mysql_ohash.so';
*/

#include <stdio.h>
#include <string.h>

#include <my_global.h>
#include <my_sys.h>

#include <mysql.h>
#include <m_ctype.h>
#include <m_string.h>

#include <iostream>
#include <string>
#include <sys/time.h>

#include <cryptopp/whrlpool.h>
#include <cryptopp/tiger.h>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h>
#include <cryptopp/base64.h>

using namespace std;
using namespace CryptoPP;

static pthread_mutex_t LOCK_hostname;

extern "C" {
my_bool whirlpool_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
char *whirlpool(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
my_bool tiger_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
char *tiger(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
}

int lower_case ( int c )
{
         return tolower ( c );
}


string doWP(string input)
{
 string output;
 Whirlpool wp;
 StringSource s(input.c_str(),true, new HashFilter(wp,new HexEncoder(new StringSink(output))));
 return output;
}

string doTiger(string input)
{
 string output;
 Tiger tg;
 StringSource s(input.c_str(),true, new HashFilter(tg,new HexEncoder(new StringSink(output))));
 return output;
}

my_bool whirlpool_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
  if (args->arg_count != 1)
  {
    strmov(message,"This function takes 1 argument");
    return 1;
  }

  return 0;
}

char *whirlpool(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
 const char *word=args->args[0];

 if (!word)					// Null argument
 {
  *is_null=1;
  *error=1;
  return 0;
 } 
 string a,b;
 b = word;
 a = doWP(b);
 transform (a.begin(),a.end(), a.begin(), lower_case);
 *length=a.length();
 memcpy(result,a.c_str(),*length);
 return result;
}

my_bool tiger_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
  if (args->arg_count != 1)
  {
    strmov(message,"This function takes 1 argument");
    return 1;
  }

  return 0;
}

char *tiger(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
 const char *word=args->args[0];

 if (!word)					// Null argument
 {
  *is_null=1;
  *error=1;
  return 0;
 } 
 string a,b;
 b = word;
 a = doTiger(b);
 transform (a.begin(),a.end(), a.begin(), lower_case);
 *length=a.length();
 memcpy(result,a.c_str(),*length);
 return result;
}

