#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h>
#include <errno.h>

#include "tango_cache_tools.h"

static const char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

#define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f])

#define B64_EOLN                0xF0
#define B64_CR                  0xF1
#define B64_EOF                 0xF2
#define B64_WS                  0xE0
#define B64_ERROR               0xFF
#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
#define B64_BASE64(a)           !B64_NOT_BASE64(a)

static const unsigned char data_ascii2bin[128] = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
    0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
    0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
    0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};

//切记不可以如此调用: conv_ascii2bin(x++); 因为会++两次
#define conv_ascii2bin(aa) (((aa) & 0x80)?(0xFF):data_ascii2bin[(aa)])

/*********************************************************************
函数名称：Base64_EncodeBlock
功能简介：对一完整BASE64编码块进行编码
输入参数：in：待编码的字符；
				inl：in的长度
输出参数：out：编码后存储的缓冲区；
返回值：编码后的长度
*********************************************************************/
int Base64_EncodeBlock(const unsigned char *in, int inl, unsigned char *out)
{
    int i, ret = 0;
    unsigned long l;

    for (i = inl; i > 0; i -= 3) {
        if (i >= 3) {
            l = (((unsigned long)in[0]) << 16L) |
                (((unsigned long)in[1]) << 8L) | in[2];
            *(out++) = conv_bin2ascii(l >> 18L);
            *(out++) = conv_bin2ascii(l >> 12L);
            *(out++) = conv_bin2ascii(l >> 6L);
            *(out++) = conv_bin2ascii(l);
        } else {
            l = ((unsigned long)in[0]) << 16L;
            if (i == 2)
                l |= ((unsigned long)in[1] << 8L);

            *(out++) = conv_bin2ascii(l >> 18L);
            *(out++) = conv_bin2ascii(l >> 12L);
            *(out++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
            *(out++) = '=';
        }
        ret += 4;
        in += 3;
    }

    *out = '\0';
    return (ret);
}

/*********************************************************************
函数名称：Base64_DecodeBlock
功能简介：对一完整BASE64编码块进行解析，自动忽略首尾非BASE64编码字符
输入参数：in：待解码的字符；
				inl：in的长度
输出参数：out：解码后存储的缓冲区；
				必须保证有足够的空间，一般达到@inl大小即可；
返回值：<0：失败；>=0：解码后的长度
*********************************************************************/
int Base64_DecodeBlock(const unsigned char *in, int inl, unsigned char *out, int outsize)
{
	int i, ret = 0;
	unsigned char a, b, c, d;
	unsigned long l;

	/* ignore not-base64-encoded charactor. */
	while ((conv_ascii2bin(*in) == B64_WS) && (inl > 0))
	{
		in++;
		inl--;
	}
	while ((inl > 3) && (B64_NOT_BASE64(conv_ascii2bin(in[inl - 1]))))
		inl--;

	if (inl % 4 != 0)
		return -1;

	if(outsize < (inl*3)/4)
		return -2;

	for (i = 0; i < inl; i += 4) 
	{
		a = conv_ascii2bin(*(in));
		b = conv_ascii2bin(*(in+1));
		c = conv_ascii2bin(*(in+2));
		d = conv_ascii2bin(*(in+3));
		if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
			return (-1);
		l = ((((unsigned long)a) << 18L) | (((unsigned long)b) << 12L) |
			(((unsigned long)c) << 6L) | (((unsigned long)d)));
		*(out++) = (unsigned char)(l >> 16L) & 0xff;
		*(out++) = (unsigned char)(l >> 8L) & 0xff;
		*(out++) = (unsigned char)(l) & 0xff;
		ret += 3;
		in+=4;
	}

	for(i = inl; i > 0; i -= 4)
	{
		if(*(in-3) == '=')
		{
			in -= 4;
			ret -= 3;
			continue;
		}

		while(*(--in) == '=')
			ret -= 1;

		break;
	}
	
    return ret;
}


//已知两个串长度相同的情况下，比较两个串是否相等
int strcmp_one_word_mesa_equal_len(const char *s1_lowercase, const char *s1_uppercase, const char *s2, size_t len)
{
	unsigned char *s1,*s12;

	if (s2[len-1]-'a'>=0)
	{
		s1 = (unsigned char *)s1_lowercase;
		s12= (unsigned char *)s1_uppercase;
	}
	else
	{
		s1 = (unsigned char *)s1_uppercase;
		s12= (unsigned char *)s1_lowercase;
	}
	
	do {
		if (*s1 == *s2 || *s12 == *s2)
		{
			++s1;
			++s12;
			++s2;
			continue;
		}
		return 0;
	} while (--len);
	
	return 1;
}

int mkdir_according_path(const char * path)
{
	char buffer[256];
	const char *ps=path, *pc;

	if(*ps == '/')
		ps += 1;
	
	while((pc = strchr(ps, '/')) != NULL)
	{
		while(*(pc+1) == '/')
			pc++;
			
		memcpy(buffer, path, pc - path);
		buffer[pc-path] = '\0';
		
		if(access(buffer, F_OK))
		{
			if(mkdir(buffer, 0777) && errno!=EEXIST)
			{
				return -1;
			}
		}

		ps = pc + 1;
	}
	if(access(path, F_OK))
	{
		if(mkdir(path, 0777))
		{
			return -1;
		}
	}
	return 0;
}

//将时间字符串转换为时间戳
time_t expires_hdr2timestamp(const char *expires_val, int len)
{
	struct tm tm;
	
	while(len > 0 && (*expires_val==' '||*expires_val=='\t'||*expires_val=='\r'||*expires_val=='\n'))
	{
		expires_val++;
		len--;
	}
	if(len == 0)
	{
		return 0;
	}

	memset(&tm, 0, sizeof(struct tm));
	if(strptime(expires_val, "%a, %d %b %Y %T", &tm) == NULL)
	{
		return 0;
	}

	return mktime(&tm);
}

//将本地时间戳转换为GMT时间字符串
size_t expires_timestamp2hdr_str(time_t seconds, char *buffer, size_t size)
{
	struct tm save;
	return strftime(buffer, size, "Expires: %a, %d %b %Y %T GMT", gmtime_r(&seconds, &save));
}

//将本地时间戳转换为GMT时间戳
time_t get_gmtime_timestamp(time_t seconds)
{
	struct tm *tm, save;
	
	tm = gmtime_r(&seconds, &save);
	return mktime(tm);
}

