#include "xysdk_common.h"
#include "xysdk_md5.h"
#include "xysdk_hmac_sha1.h"

#define XY_CLOUD_SECRET_LEN 				32

static void xysdk_md5(unsigned char *input, unsigned int len, unsigned char *output)
{
    XY_MD5_CTX md5;
    
    xy_MD5Init(&md5);
	xy_MD5Update(&md5,input, len);
	xy_MD5Final(&md5, output);
}

static void xysdk_hex_str(unsigned char *inchar, unsigned int len, unsigned char *outtxt)
{
	unsigned char hbit,lbit;
	unsigned int i;
	
	for(i = 0; i < len; i++)
	{
		hbit = (*(inchar+i)&0xf0)>>4;
		lbit = *(inchar+i)&0x0f;
		if (hbit>9) 
		outtxt[2*i]='a'+hbit-10;
		else
			outtxt[2*i]='0'+hbit;
		if (lbit>9) 
		outtxt[2*i+1]='a'+lbit-10;
		else    
			outtxt[2*i+1]='0'+lbit;
	}
	outtxt[2*i] = 0;
}


static unsigned char *base64_encode(unsigned char *str)  
{  
    int len;  
    int str_len;  
    unsigned char *res;  
    int i,j;  

    const char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  
    str_len=strlen((const char *)str);  
    if(str_len % 3 == 0)  
        len=str_len/3*4;  
    else  
        len=(str_len/3+1)*4;  
  
    res=(unsigned char *)xy_common_malloc(sizeof(unsigned char)*len+1);  
    res[len]='\0';  
  

    for(i=0,j=0;i<len-2;j+=3,i+=4)  
    {  
        res[i]=base64_table[str[j]>>2]; 
        res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; 
        res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; 
        res[i+3]=base64_table[str[j+2]&0x3f];
    }  
  
    switch(str_len % 3)  
    {  
        case 1:  
            res[i-2]='=';  
            res[i-1]='=';  
            break;  
        case 2:  
            res[i-1]='=';  
            break;  
    }  
  
    return res;  
}  

/**
 * @brief 获取签名
 *
 * 使用给定的 app_secret 和字符串 str，计算签名并存储到 data_sig 中。
 *
 * @param app_secret 应用密钥
 * @param str 字符串
 * @param data_sig 存储签名的字符数组
 *
 * @return 成功返回 0，失败返回 -1
 */
int xy_api_get_sig(char *app_secret, char *str, char *data_sig)
{
	int ret =-1;
	unsigned char *base64_out = NULL;
	char *sig = NULL;
	char md5_out[16] = {0};

	if(!app_secret || !str || !data_sig)
	{
		goto err_exit;
	}
	
	sig = (char *)xy_common_malloc(128);
	if(!sig)
	{
		goto err_exit;
	}

	base64_out = base64_encode((unsigned char*)str);
	if(!base64_out)
	{
		goto err_exit;

	}
	ret = xy_hmac_sha1((unsigned char*)app_secret, XY_CLOUD_SECRET_LEN, base64_out, strlen((char *)base64_out), (unsigned char*)sig);
	if(ret<0)
	{
		goto err_exit;
	}

	memset(md5_out,0,sizeof(md5_out));
	xysdk_md5((unsigned char*)sig, 20,(unsigned char*)md5_out); 
	
	xysdk_hex_str((unsigned char *)md5_out, 16, (unsigned char*)data_sig);
	XY_LOG_I("data_sig=%s\n",data_sig);
	ret = 0;
err_exit:
	xy_common_free((void**)&sig);
	xy_common_free((void**)&base64_out);
	
	return ret;
}