把资料用base64进行转码
把文件用base64进行转码
一直很好奇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 10M unsigned 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 table for(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 byte for(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 比较原来的图片和经过编码解码后的图片有没有区别
黑白烂苹果,很喜欢的一张图片