///
module imap.auth;
import imap.sil : SILdoc;
import std.string;
import std.stdio;
import deimos.openssl.ssl;
import deimos.openssl.hmac;
import deimos.openssl.evp;
import imap.defines;


@SILdoc("challenge-response authentication mechanism MD5")
string authCramMD5(string user, string pass,string challenge)
{
	import std.conv : to;
	import std.algorithm : map;
	import std.array : array;
	import std.string : join;
	import std.format : format;
	size_t n;
	uint i;
	ubyte[] resp, ret;
	ubyte[EVP_MAX_MD_SIZE] md;
	uint mdlen;
	HMAC_CTX hmac;

	n = challenge.length * 3 / 4 + 1;
	resp.length=n;
	EVP_DecodeBlock(resp.ptr, cast(const(ubyte)*)challenge.toStringz, challenge.length.to!int);

	HMAC_Init(&hmac, cast(const(void)*) pass.toStringz, pass.length.to!int, EVP_md5());
	HMAC_Update(&hmac, cast(const(ubyte)*)resp.ptr, resp.length.to!int);
	HMAC_Final(&hmac, md.ptr, &mdlen);
	
	auto mdhex = md[0..mdlen]
					.map!(c => format!"%02X"(c)).array.join("");
	auto buf = format!"%s %s"(user,mdhex);
	n = (buf.length + 3)*4 / 3 + 1;
	ret.length=n;
	EVP_EncodeBlock(ret.ptr, cast(ubyte*) buf.ptr, buf.length.to!int);
	return cast(string)(ret.idup);
}