把文件用base64进行转码

来源:互联网 发布:linux 移动整个文件夹 编辑:程序博客网 时间:2024/05/22 12:21

一直很好奇base64的实现,ubuntu也自带了base64工具,这篇帖子是对base64的很好解释,http://www.linandxin.com/archives/876 ,特别要注意的是:base64有自己的转码表,并不是跟ascii码表一样的,

今天自己写了一个base64转码的程序,包括编码和解码程序,整个过程让我觉得自己的C语言功底非常的弱,free的时候竟然出现 double free的错误,后来查了一下,原来是因为溢出,超出了malloc的大小

/*****************************************************************> File Name: t.c> Author: Lobo Chim> Mail: zhanlongbo@gmail.com > Created Time: 2013年01月25日 星期五 18时07分39秒 ****************************************************************/#include <stdio.h>#include <memory.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#define MAX_SIZE (10 * 1024 * 1024)   //max size 10Munsigned char *table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";void my_err(const char *s,int line){fprintf(stderr,"line:%d ",line);perror(s);exit(1);}/* * translate 4B to 3B * p is start index in f,q is start index in t */void f2t(unsigned char *f,unsigned char *t,int p,int q){int i;for(i=q;i<3+q;i++)t[i]=0x00;t[q]=f[p]<<2;t[q]|=(f[p+1]& 0x30)>>4;t[q+1]=f[p+1]<<4;t[q+1]|=(f[p+2] & 0x3c)>>2;t[q+2]=f[p+2]<<6;t[q+2]|=f[p+3] & 0x3f;}/* * translate 3B to 4B * p is start index in t,q is in f */void t2f(unsigned char *t,unsigned char * const f,int p,int q){int i;for(i=q;i<4+q;i++)f[i]=0x00;f[q]=(t[p]>>2) & 0x3f;f[q+1]=(t[p]<<4) & 0x30;f[q+1]|=(t[p+1]>>4) & 0x0f;f[q+2]=(t[p+1]<<2) & 0x3c;f[q+2]|=(t[p+2]>>6) & 0x03;f[q+3]=t[p+2] & 0x3f;}/* * change base64 string to byte * return:number of byte */int decode(unsigned char *s,unsigned char *b){int len=strlen(s);int i,j;int other=0;  //except a-zA-Z+/=//change string to key in tablefor(i=0;i<len;i++){if(s[i]=='=')s[i]=(unsigned char)0;else{for(j=0;j<64;j++)if(s[i]==table[j]) break;if(j==64){ other++;continue;}s[i-other]=(unsigned char)j;}}//change the key to bytefor(i=0,j=0;i<len-other;i+=4,j+=3)f2t(s,b,i,j);return j;}/* *byte to base64 *return :number of string base64,include new line '\n' */int encode(unsigned char *b,unsigned char *s,int n){int m=n/3;if(n%3)m++;// may overflow,it is very dangerous!!!unsigned char *p=(unsigned char *)malloc(m*4);memset(p,0,m*4);int i,j;for(i=0,j=0;i<m*3;i+=3,j+=4)t2f(b,p,i,j);// not enough, =if(n%3==1){p[m*3-1]=(unsigned char)0x40;p[m*3-2]=(unsigned char)0x40;}else if(n%3==2){p[m*3-1]=(unsigned char)0x40;}//printf("m:%d\n",m*4);for(i=0,j=0;j<m*4;i++,j++){if(j && j%76==0)   //new line{s[i++]='\n';}s[i]=table[p[j]];}//printf("m*4:%d\n",m*4);s[i++]='\n';//printf("i:%d\n",i);//printf("free\n");//if(p)free(p);p=NULL;//printf("free ok\n");return i;}int main(int argc,unsigned char *argv[]){int flag;if(argc!=4){perror("argc is not 3\n");exit(1);}if(strcmp(argv[1],"-e")==0)flag=1;else if(strcmp(argv[1],"-d")==0)flag=2;else{my_err("usage: ./a.out [optione] file1 file2",__LINE__);}int rf=open(argv[2],O_RDONLY);int wf=open(argv[3],O_RDWR|O_CREAT,0644);if(rf<0 || wf<0){my_err("open fail",__LINE__);}int SIZE=lseek(rf,0,SEEK_END);if(SIZE>MAX_SIZE){my_err("file size is too big",__LINE__);}lseek(rf,0,SEEK_SET);//printf("SIZE:%d\n",SIZE);int PER=1024;unsigned char buf[PER];unsigned char *s=(unsigned char *)malloc(SIZE * 2);unsigned char *b=(unsigned char *)malloc(SIZE * 2);int n,p,i;if(s==NULL || b==NULL){my_err("malloc fail",__LINE__);}switch(flag){case 1:p=0;while((n=read(rf,buf,PER))>0){memcpy(s+p,buf,n); p+=n; }//printf("%d\n",p);p=encode(s,b,p);for(i=0;i<p;i++)write(wf,b+i,1);break;case 2:p=0;while((n=read(rf,buf,PER))>0){memcpy(s+p,buf,n);p+=n; }s[p]='\0';p=decode(s,b);for(i=0;i<p;i+=3){write(wf,b+i,3);}break;}free(s);s=NULL;free(b);b=NULL;close(rf);close(wf);return 0;}

longbo@ubuntu:~/lab$ ./a.out -e d.jpg c.txt        编码
longbo@ubuntu:~/lab$ ./a.out -d c.txt c            解码 
longbo@ubuntu:~/lab$ diff d.jpg c                  比较原来的图片和经过编码解码后的图片有没有区别
黑白烂苹果,很喜欢的一张图片


                

	
				
		
原创粉丝点击