/* Copyright 2013 Akira Ohta (akohta001@gmail.com)
    This file is part of ntch.

    The ntch 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 3 of the License, or
    (at your option) any later version.

    The ntch 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 ntch.  If not, see <http://www.gnu.org/licenses/>.
    
*/
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>

#include "utils/nt_std_t.h"
#include "utils/base64.h"

//Encode Base64
BOOL nt_base64encode(const char* source, char* buf, size_t buf_len) 
{
	BIO *bio, *b64;
	FILE* fp;
	int len;
	BOOL result;

	bio = NULL;
	result = FALSE;

	fp = fmemopen(buf, buf_len, "w");
	if(!fp)
		return FALSE;

	b64 = BIO_new(BIO_f_base64());
	if(!b64)
		goto ERROR_TRAP;
	bio = BIO_new_fp(fp, BIO_NOCLOSE);
	if(!bio)
		goto ERROR_TRAP;
	bio = BIO_push(b64, bio);
	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
	len = BIO_write(bio, source, strlen(source));
	if(len <= 0)
		goto ERROR_TRAP;
	(void)BIO_flush(bio);
	result = TRUE;
ERROR_TRAP:
	if(bio)
		BIO_free_all(bio);
	fclose(fp);

	return result;
}
// Calculates decoded string length
int nt_base64_calc_decoded_length(const char *source)
{
	int len, pad;
	assert(source);
	pad = 0;
	len = strlen(source);
	if(len % 4)
		return -1;
	if(len == 0)
		return 0;
	if(source[len-1] == '='){
		pad++;
		if(len > 1 && source[len-2] == '=')
			pad++;
	}
	return len / 4 * 3 - pad;
	
}

//Decode Base64
BOOL nt_base64decode(char* b64str, char* buf) 
{
	BIO *bio, *b64;
	FILE *fp;
	int len;
	BOOL result;

	assert(b64str && buf);

	result = FALSE;
	bio = NULL;

	fp = fmemopen(b64str, strlen(b64str), "r");
	if(!fp)
		return FALSE;

	b64 = BIO_new(BIO_f_base64());
	if(!b64)
		goto ERROR_TRAP;
	bio = BIO_new_fp(fp, BIO_NOCLOSE);
	if(!bio)
		goto ERROR_TRAP;
	bio = BIO_push(b64, bio);
	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); 
	len = BIO_read(bio, buf, strlen(b64str));
	if(len <= 0)
		goto ERROR_TRAP;
	buf[len] = '\0';
	result = TRUE;
ERROR_TRAP:
	if(bio)
		BIO_free_all(bio);
	fclose(fp);

	return result; 
}


