#include<stdio.h>
#include<stdlib.h>
/*#include<unistd.h>*/
#include<string.h>
#include ".\zlib113\zlib.h"
/**********************************************
作者:Minuit
时间:2007年02月05日 星期日  20时42分33秒
文件名:base64.c
描述:C base64编码操作函数
**********************************************/
/*
A B C D E F G H I J  K  L  M  N  O  P  Q
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
R   S  T  U  V  W  X  Y  Z  a  b  c  d  e  f  g  h
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
z  0  1  2  3  4  5  6  7  8  9  +  / (pad) =
51 52 53 54 55 56 57 58 59 60 61 62 63
*/
static char base64_table[255];
char *decode(const char*,char **);
char *encode(const char*,char **);
const char hello[] = "hello, hello!";
/* "hello world" would be more standard, but the repeated "hello"
 * stresses the compression code better, sorry...
 */
#define CHECK_ERR(err, msg) { \
    if (err != Z_OK) { \
        fprintf(stderr, "%s error: %d\n", msg, err); \
        exit(1); \
    } \
}
const char dictionary[] = "hello";
uLong dictId; /* Adler32 value of the dictionary */

void test_inflate       OF((Byte *compr, uLong comprLen,
		            Byte *uncompr, uLong uncomprLen));
void test_large_inflate OF((Byte *compr, uLong comprLen,
		            Byte *uncompr, uLong uncomprLen));
void test_dict_inflate  OF((Byte *compr, uLong comprLen,
		            Byte *uncompr, uLong uncomprLen));
void base64_tableinit();


/* ===========================================================================
 * Test inflate() with small buffers
 */
void test_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = compr;
    d_stream.avail_in = 0;
    d_stream.next_out = uncompr;

    err = inflateInit(&d_stream);
    CHECK_ERR(err, "inflateInit");

    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
        err = inflate(&d_stream, Z_NO_FLUSH);
        if (err == Z_STREAM_END) break;
        CHECK_ERR(err, "inflate");
    }

    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");
    /*
    if (strcmp((char*)uncompr, hello)) {
        fprintf(stderr, "bad inflate\n");
	exit(1);
    } else {
        printf("inflate(): %s\n", (char *)uncompr);
    }
	*/
}


/* ===========================================================================
 * Test inflate() with large buffers
 */
void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = compr;
    d_stream.avail_in = (uInt)comprLen;

    err = inflateInit(&d_stream);
    CHECK_ERR(err, "inflateInit");

    for (;;) {
        d_stream.next_out = uncompr;            /* discard the output */
	d_stream.avail_out = (uInt)uncomprLen;
        err = inflate(&d_stream, Z_NO_FLUSH);
        if (err == Z_STREAM_END) break;
        CHECK_ERR(err, "large inflate");
    }

    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
	exit(1);
    } else {
        printf("large_inflate(): OK\n");
    }
}

/* ===========================================================================
 * Test inflate() with a preset dictionary
 */
void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = compr;
    d_stream.avail_in = (uInt)comprLen;

    err = inflateInit(&d_stream);
    CHECK_ERR(err, "inflateInit");

    d_stream.next_out = uncompr;
    d_stream.avail_out = (uInt)uncomprLen;

    for (;;) {
        err = inflate(&d_stream, Z_NO_FLUSH);
        if (err == Z_STREAM_END) break;
	if (err == Z_NEED_DICT) {
	    if (d_stream.adler != dictId) {
		fprintf(stderr, "unexpected dictionary");
		exit(1);
	    }
	    err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
				       sizeof(dictionary));
	}
        CHECK_ERR(err, "inflate with dict");
    }

    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    if (strcmp((char*)uncompr, hello)) {
        fprintf(stderr, "bad inflate with dict\n");
	exit(1);
    } else {
        printf("inflate with dictionary: %s\n", (char *)uncompr);
    }
}

void base64_tableinit()
{
   int i,j;
   /*bzero(base64_table,255);*/
        memset(base64_table,255,255);
        for(j=0,i='A';i<='Z';i++) /*填base64编码表*/
                base64_table[i]=j++;
        for(i='a';i<='z';i++)
                base64_table[i]=j++;
        for(i='0';i<='9';i++)
                base64_table[i]=j++;
        base64_table['+']=j++;
        base64_table['/']=j++;
        base64_table['=']=j;
}
char *decode(const char *cptr,char **rptr)
{
        char *res;
        int clen,len;
        static int init=0;
        if(cptr==NULL)
                return NULL;
        len=strlen(cptr);
        if(len%4)  /*编了码的字符绝对是4的倍数*/
                return NULL;
        if(!init)
          {
                init=1;
                base64_tableinit();
          }
        clen=len/4;
       /* if((res=malloc(len-clen))==NULL)
                return NULL;*/
		res=*rptr;
        for(*rptr=res;clen--;)
          {
                *res=base64_table[*cptr++]<<2&0xfc;         /*cptr后六位移动到最高位*/
                *res++|=base64_table[*cptr]>>4;               /*跟着下个字符低两位给res低两位*/
 				*res=base64_table[*cptr++]<<4&0xf0;               /*填充res高四位其它清0*/
                *res++|=base64_table[*cptr]>>2&0x0f;    /*字符前六位移到低六位取低四位*/
                *res=base64_table[*cptr++]<<6;
                if(*cptr!='=')                                                 /*=号忽略*/
                   *res++|=base64_table[*cptr++];
          }
        return *rptr;
}
char *encode(const char *cptr,char **rptr)
{
        char *res;
        int i,clen,len;
        len=strlen(cptr);
        clen=len/3;
        if(cptr==NULL||(res=malloc(clen+3*2+len))==NULL)
                  return NULL;
        for(*rptr=res;clen--;)
          {
                *res++=*cptr>>2&0x3f;          /*取ptr高6位放入res低6位*/
                *res=*cptr++<<4&0x30;          /*移动ptr最低2位到高6位然后清0其 它位*/
                *res++|=*cptr>>4;                  /*取ptr高4位给res低4位*/
                *res=(*cptr++&0x0f)<<2;        /*取ptr低4位移动到高6位*/
                *res++|=*cptr>>6;                  /*取ptr高2位给res低2位*/
                *res++=*cptr++&0x3f;
          }
        if(i=len%3)                                       /*处理多余字符只有两种情况多一个或者两个字符*/
          {
                if(i==1)                                    /*根据base64编码补=号*/
                  {
                        *res++=*cptr>>2&0x3f;
                        *res++=*cptr<<4&0x30;
                        *res++='=';
                        *res++='=';
                  }
                else
                  {
                        *res++=*cptr>>2&0x3f;
                        *res=*cptr++<<4&0x30;
                        *res++|=*cptr>>4;
                        *res++=(*cptr&0x0f)<<2;
                        *res++='=';
                  }
          }
        *res='=';                                               /*保证最后结位为=结束原因是因为base64里有为0的编码*/
        for(res=*rptr;*res!='=';res++)
       *res="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[*res];
        rptr[0][strlen(*rptr)-1]='\0';                 /*去掉最后一个=号*/
        return *rptr;
}
int main(argc, argv)
int argc;
char *argv[];
{
	FILE *fp;
	FILE *fo;
	char buf[256];
	char src[]=/*"8BgMHdmA3Qg9IbJmntlZoZQoHwcwg5nnm7+fMr2ywFxakaamb40d1Q==";*/ /*prvtlob.plb的编码内容*/
		"";
	char tra[]="3D6585B318DBE287F152AB634BB5A05F7D687B9B24C228678ADEA4261E03EB176F343E7A3FD2A96A"
		"0FE935561FB14D1078D975F6BC4104816106F9ADD6D5297E869E79E505BA84CC6E278EB05DA8F39F"
		"D0A271B858DD2C38994C480755E4538C46B62DA5AF322240DC50C3A1258B9C16605CCFFD0C981CD4"
		"376D3C3A30E86C3147F533DA43C8E35E1994ECE6A39514E09D64FA5915C52FCABB0BDFF297BF0A76"
		"B449445A1DF0009621807F1A82394FC1A7D70DD1D8FF139370EE5BEFBE09B97772E7B254B72AC773"
		"9066200E51EDF87C8F2EF412C62B83CDACCB3BC44EC069366202AE88FCAA4208A64557D39ABDE123"
		"8D924A1189746B91FBFEC901EA1BF7CE"; /*sys.idltranslate表内容存到字符数组"*/
	char *b64;
	char *dec;
	/*char **pdec=NULL;*/
	int i=0;
	int j=0;
	int flag=0;
	int len_src;
	int len_wrap;
	int pos=0;
	int size=0;
	Byte *compr, *uncompr;
	uLong comprLen = 250000*2.56*sizeof(int); /* don't overflow on MSDOS */
	uLong uncomprLen = comprLen;
	if(argc<3)
	{
		printf("Usage:base plb_filename sql_filename\n");
		exit(0);
	}
	b64=(char *) malloc(2560000);
	dec=(char *) malloc(2560000);
		uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
 	for (i=0;i<256;i++) /*将16进制恢复成字符*/
	{
		tra[i]=((tra[i*2]-'A'>=0?tra[i*2]-'A'+10:tra[i*2]-'0')&0xF)<<4|
			((tra[i*2+1]-'A'>=0?tra[i*2+1]-'A'+10:tra[i*2+1]-'0')&0xF);
			/*	 strncpy(dec,tra+i*2,2);dec[2]='\0';
		tra[i]=strtol(dec,NULL,16);*/
	}

	/*printf("%x,%x",tra[0x30],tra[0x83]);*/
	if(NULL==(fp=fopen(argv[1],"rt")))
		exit(1);
	if(NULL==(fo=fopen(argv[2],"wt")))
		exit(1);

	while(1) /* read many blocks */
	{
		if(feof(fp))
			break;

		/*fseek(fp,pos)*/
		flag=0;
		while(!feof(fp))
		{
			fgets(buf,255,fp);
			if(strcmp(buf,"abcd\n")==0)
			{
				flag=1;
			}
			else
			{
				if(flag==1)
				{
					flag=2;
					/*fscanf(fp,"%s",);*/
					printf("type code:\t%s",buf); /*type code:9 package,d body*/
				}
				else if(flag==2)
				{
					sscanf(buf,"%x %x\n",&len_src,&len_wrap);
					printf("len_src:\t%d\tlen_wrap:\t%d\n",len_src,len_wrap); /*store base64 code to dec*/
					printf("freadsize:%d\t",size=fread(dec,1,len_wrap,fp));
					if(size==len_wrap)
					{
						dec[len_wrap]='\0';
					}
					else
					{
						printf("fread err\n");
						exit(1);
					}
					/*printf("BASE64:\n%s",dec);*/
					pos=ftell(fp);
					flag=3;
					break;
				}
			}
		}
		if (flag==3) /*get BASE64 Block */
		{
		for(i=0,j=0;i<len_wrap;i++) /*trim \n*/
		{
			if(dec[i]!='\n')
				b64[j++]=dec[i];
		}

		b64[j]='\0';
		decode(b64,&dec);
		printf("read ok\n");
		compr	 = (Byte*)calloc((uInt)comprLen, 1);
	/*	printf("-->%lx,%lx,%lx,%lx\n",b64,dec,compr,uncompr);*/

		printf("b64 size:\t%d,%d\n",j,strlen(b64));

		for (i=20;i<j/4*3;i++)	/*translaate*/
		{
			compr[i-20]=tra[dec[i]&0xFF]&0xFF;
		}
		/* compr and uncompr are cleared to avoid reading uninitialized
		* data and to ensure that uncompr compresses well.
		*/
		if (compr == Z_NULL || uncompr == Z_NULL) {
			printf("out of memory\n");
			exit(1);
		}
/*		printf("### %c ###",compr[0]);*/
		test_inflate(compr, comprLen, uncompr, uncomprLen); /*从第21字节开始解压*/
		/*uncompr[21]='\0';*/
		uncompr[2560000-1]='\0';
		printf("unzip size:%d\n",strlen(uncompr));
		/*	printf("inflate:\t%s",uncompr);*/
		fprintf(fo,"CREATE OR REPLACE %s\n\n/\n\n",uncompr);
		uncompr[0]='\0';

		/*free(compr);*/
/*		printf("-->%lx,%lx,%lx,%lx\n",b64,dec,compr,uncompr);*/
	}
	}
		free(uncompr);
	free(b64);
	free(dec);
	fclose(fp);
	fclose(fo);
	return 1;
}

