- 论坛徽章:
- 0
|
该程序主要完成电子邮件中邮件附件的编码与解码工作。其中对BASE64编码原理的理解还是比较完善的。如果以后有人用到这些东西,可以参考。
#include<stdio.h>
#include<stdlib.h>
#include"string"
//***********************************************************
unsigned short Chr2Base( char c );
int B64Decode( FILE *fpoutfile, FILE *fpinfile,int n );
int counter(FILE *in_file);
void convertmain(char adrin[20]/*要处理的本地临时文件地址*/);
//***********************************************************
int checkct(char fin[100],int n);
int checkfi(char fin[100],int n);
int strcount(char fstr[100]);
void filecopy(FILE *fp,char adr[20]);
int linecount(FILE *fpinfile);
void checkmain(FILE *fpinfile,char adr[20],int line);
//***********************************************************
void main()
{
printf("此程序是对基于foxmail客户端的文本格式邮件导出的.eml文件进行分析、提取和解码:\n");
FILE *fpinfile;
int n;
char adr[20];
printf("输入要处理的文件:\n");
scanf("%s",adr);
fpinfile=fopen(adr,"r");
if(fpinfile==NULL)
{
printf("can't open the file,please check your URL\n");
return;
}
n=linecount(fpinfile);
fpinfile=fopen(adr,"r");
// printf("%d\n",n);
checkmain(fpinfile,adr,n);
}
//—————————————————————————————————————————
//**********************************************************************************
//—————————————————————————————————————————
int linecount(FILE *fpinfile)//计算要处理文件的行数,以便后边处理
{
int count=0;
int ch;
while(1)
{
ch=fgetc(fpinfile);
if(ch==EOF)
break;
++count;
}
return int(count/50);
fclose(fpinfile);
}
void checkmain(FILE *fpinfile,char adr[20],int line)
{
char fstr[100]; //行缓冲数组
int n; //行缓冲数组中有效字符长度
int m=0; //用来标记 Content-Type的出现次数
char adrtemp[20]; //存储临时文件地址
for(int i=0;i<line/*入口参数*/;i++)
{
fgets(fstr,100,fpinfile);
n=strcount(fstr);
// checkct(fstr, n);//找content-type
if( checkct(fstr, n)==1)//第一个content-type将不参与处理
{
m=m+1;
}
else
checkfi(fstr,n);//找filename
//*** printf("coming !!!!!\n");
//对吗?原本想只对第二个以后的content-type进行处理
if((m>1)&&(fstr[0]=='\n'))//第一个content-type将不参与处理
{
//*** printf("coming !!!!!\n");
//将正文部分保存到本地磁盘中
printf("文件的第 %d部分格式如上,现要将其保存为.txt文件到本地磁盘,文件名请用原始扩展名:\n",m-1);
scanf("%s",adrtemp);
//文件拷到目标地址
//*** printf("coming !!!!!\n");
filecopy(fpinfile,adrtemp);
//调用译码程序
printf("o k !!!!!\n");
convertmain(adrtemp/*要处理的本地临时文件地址*/);
//*** printf("coming !!!!!\n");//问题是convert没有执行?
}
}
fclose(fpinfile);
}
//文件拷贝函数
void filecopy(FILE *fp/*要处理文件指针*/,char adr[20]/*目标地址*/)
{
//创建一个临时文本文件
FILE *tempfp;
char ch[100];
tempfp=fopen(adr,"w");
if(tempfp==NULL)
{
printf("临时文件未能创建!!!\n");
return;
}
//当遇到一行只有一个回车符或者遇到分界符的时候,停止copy
while(ch[0]!='\n')
{
fgets(ch,100,fp);
if((ch[0]!='-')&&(ch[0]!='\n'))//回车和无效字符都不能写进要编译的文本
fputs(ch,tempfp);//当连着拷进两个回车符时,译码程序不能识别,
else //将最后一个回车作为文件结束,这样文件将比实际多出两个字符
{
ch[0]=NULL;
break;
}
}
fclose(tempfp);
}
//数组有效字符计数
int strcount(char fstr[100])
{
int i=0;
while(fstr!='\0')
{
i++;
}
return i+1;
}
//Content-Type字符串查找
int checkct(char fin[100],int n)
{
char ctype[20]="Content-Type";
int i;
int j;
int m;
int k=0;//返回标志
for(i=0;i<n;i++)
{
j=i;
m=0;
//先找Content-Type项
while(fin[j]==ctype[m])
{
j++;
m++;
if(ctype[m]=='\0')
{
printf("%s",fin);
k=1;
break;
}
}
}
return k;
}
//filename查找
int checkfi(char fin[100],int n)
{
char fname[20]="filename";
int i;
int j;
int m;
int k=0;//返回条件变量
for(i=0;i<n;i++)
{
j=i;
m=0;
while(fin[j]==fname[m])
{
j++;
m++;
if(fname[m]=='\0')
{
printf("%s",fin);
k=1;
break;
}
}
}
return k;
}
//—————————————————————————————————————————
//**********************************************************************************
//—————————————————————————————————————————
void convertmain(char adrin[20]/*要处理的本地临时文件地址*/)
{
FILE *fpinfile;
char adrout[20];
int character;
fpinfile=fopen(adrin,"r");
if(fpinfile==0)
{
printf("can't open the file,please check your URL.");
return;
}
printf("参照上面的输出,输入原始文件的文件格式\n");
printf("二进制文件选:1\n");
printf("ASCII文件选: 0\n");
scanf("%d",&character);
FILE *fpoutfile;
printf("输入原始文件保存地址,名称及文件保存格式:\n");
scanf("%s",adrout);
if(character==1)
fpoutfile=fopen(adrout,"wb");//创建一个二进制文件
else
fpoutfile=fopen(adrout,"w"); //创建一个文本文件
if(fpoutfile==0)
{
printf("can't create the file,please check your URL.");
return;
}
int innumf,outnumf; //base64文件大小
innumf=counter(fpinfile);
fclose(fpinfile); //必须注意在进行一次计数后文件的指针已经指向文件末尾
fpinfile=fopen(adrin,"r"); //对文件以读格式重新打开很重要
if(fpinfile==0)
{
printf("can't open the file again,please check your URL.");
return;
}
printf("编码后文件长度:%d\n",innumf);
outnumf=B64Decode( fpoutfile, fpinfile,innumf ) ;//处理后文件大小
printf("原始文件字节数%d\n",outnumf);
fclose(fpinfile);
fclose(fpoutfile);
}
//文件大小计算函数
int counter(FILE *in_file)
{
int count=0;
int ch;
while(1)
{
ch=fgetc(in_file);
if(ch==EOF)
break;
++count;
}
return(count);
}
//源文件字符到64进制数转换函数
/*base64的64个基数分别是:A、B、C……Z、a、b、c……z、0、1、2……9、+、/。
一般在标准编码文件中一般不会出现无效字符*/
unsigned short Chr2Base( char c )
{
if ( c >= 'A' && c <= 'Z' )
return (unsigned short)( c - 'A' ); /*0--25*/
else if ( c >= 'a' && c <= 'z' )
return (unsigned short)( c - 'a' + 26 ); /*26--51*/
else if ( c >= '0' && c <= '9' )
return (unsigned short)( c - '0' + 52 ); /*52--61*/
else if ( c == '+' )
return 62; //62
else if ( c == '/' )
return 63; //63
else
return 64; // 无效字符
}
//base64文件到原始文件译码函数
int B64Decode( FILE *fpoutfile, FILE *fpinfile,int n ) //n为要处理文件大小
{
int i,j=0;
unsigned char t;
char tt;
int ch;
unsigned short c;
unsigned char resl;
for ( i = 0; i < n; i++ )
{
ch=fgetc(fpinfile);
if ((char)ch=='=')//base64在将原始文件编码时是每三个字符一处理输入不够三字府时用“=”补足
break; //所以“=”出现的个数不超过2个,并且“=”不参与编码,当然也就不能译码了
if ((char)ch=='\n')
ch=fgetc(fpinfile);//遇到回车则再读一次,这是对一行读完后遇到回车符的处理
do {
if (ch!=EOF)
{
tt=(char)ch;
// printf("%c",tt);
c = Chr2Base((char)ch);//调用Chr2Base读字符,并转成0--63的其中之一
//既然Chr2Base()是将字符一个一个处理的,这样我就可以用fgetc()将源文件中的字符读出,将返回值变为字符形式。
}
else
c = 65; // 字符串结束
} while (c==64); // 跳过无效字符,如回车等
//64进制数并没有参与运算,而是用于判断
// printf("out");
if ( c==65)
break;
switch ( i % 4 ) /*4个字符为一组处理*/
{
case 0 :
t = c << 2; //主意:在进行移位操作时,c的原始值是系统保留的
break;
case 1:
resl = (unsigned char)(t | ( c >> 4 )); //译码后的第一个字符;
fputc(resl,fpoutfile);
// printf("%d:%d\n", j, resl);
j=j+1;
//能不能在循环的同时就将他写入目标文件?写的时候是直接使用二进制吗?
t = ( c << 4 );
break;
case 2:
resl = (unsigned char)(( t | ( c >> 2 ) )&255); //译码后的第二个字符
fputc(resl,fpoutfile);
// printf("%d:%d\n", j, resl);
j=j+1;
t = ( c << 6 );
break;
case 3 :
resl = (unsigned char)(( t | c )&255); //译码后的第三个字符
fputc(resl,fpoutfile);
// printf("%d:%d\n", j, resl);
j=j+1;
break;
}
}
return(j);
} |
|