Fossil SCM

fossil-scm / tools / decode-email.c
Blame History Raw 164 lines
1
/*
2
** This program reads a raw email file and attempts to decode it into
3
** a more human-readable format. The following decodings are done:
4
**
5
** (1) Header values are prefixed by "| " at the left margin.
6
**
7
** (2) Content-Transfer-Encoding is recognized and the content is
8
** decoded for display.
9
*/
10
#define _GNU_SOURCE
11
#include <stdio.h>
12
#include <string.h>
13
#include <ctype.h>
14
15
#define BINARY 0
16
#define BASE64 1
17
#define QUOTED 2
18
19
static int decode_hex(char c){
20
if( c>='0' && c<='9' ) return c - '0';
21
if( c>='A' && c<='F' ) return c - 'A' + 10;
22
if( c>='a' && c<='f' ) return c - 'a' + 10;
23
return -1;
24
}
25
26
static void convert_file(const char *zFilename, FILE *in){
27
int inHdr = 1;
28
int n;
29
int nBoundary;
30
int decodeType = 0;
31
int textMimetype = 1;
32
char *zB;
33
char zBoundary[200];
34
char zLine[5000];
35
char zOut[5000];
36
while( fgets(zLine, sizeof(zLine), in) ){
37
if( !inHdr
38
&& zLine[0]=='-'
39
&& zLine[1]=='-'
40
&& strncmp(zLine+2,zBoundary,nBoundary)==0
41
){
42
printf("|----------------- end of body section ---------|\n");
43
inHdr = 1;
44
}
45
if( !inHdr ){
46
if( textMimetype && decodeType==BASE64 ){
47
int ii, jj, c, x, y;
48
int bits = 0;
49
for(ii=jj=0; (c = zLine[ii])!=0; ii++){
50
if( c>='A' && c<='Z' ){
51
x = c - 'A';
52
}else if( c>='a' && c<='z' ){
53
x = c - 'a' + 26;
54
}else if( c>='0' && c<='9' ){
55
x = c - '0' + 52;
56
}else if( c=='+' ){
57
x = 62;
58
}else if( c=='/' ){
59
x = 63;
60
}else if( c=='=' ){
61
x = 0;
62
}else{
63
continue;
64
}
65
if( bits==0 ){
66
y = x;
67
bits = 6;
68
}else if( bits==6 ){
69
zOut[jj++] = ((y<<2) & 0xfc) | ((x>>4) & 0x03);
70
y = x & 0xf;
71
bits = 4;
72
}else if( bits==4 ){
73
zOut[jj++] = ((y<<4) & 0xf0) | ((x>>2) & 0x0f);
74
y = x & 0x3;
75
bits = 2;
76
}else if( bits==2 ){
77
zOut[jj++] = ((y<<6) & 0xc0) | (x & 0x3f);
78
bits = 0;
79
}
80
}
81
zOut[jj] = 0;
82
printf("%s", zOut);
83
}else if( textMimetype && decodeType==QUOTED ){
84
int ii, jj, c;
85
for(ii=jj=0; (c = zLine[ii])!=0; ii++){
86
if( c=='=' ){
87
int x1 = decode_hex(zLine[ii+1]);
88
int x2 = decode_hex(zLine[ii+2]);
89
if( x1>=0 && x2>=0 ){
90
zOut[jj++] = (x1<<4) | x2;
91
ii += 2;
92
}else if( zLine[ii+1]=='\r' && zLine[ii+2]=='\n' ){
93
ii += 2;
94
}
95
}else{
96
zOut[jj++] = c;
97
}
98
}
99
zOut[jj] = 0;
100
printf("%s", zOut);
101
}else{
102
printf("%s", zLine);
103
}
104
continue;
105
}
106
n = (int)strlen(zLine);
107
while( n>0 && isspace(zLine[n-1]) ){ n--; }
108
zLine[n] = 0;
109
if( n==0 ){
110
inHdr = 0;
111
printf("|----------------- end of header ---------------|\n");
112
continue;
113
}
114
printf("| %s\n", zLine);
115
if( strncasecmp(zLine,"Content-Type:", 13)==0 ){
116
textMimetype = strstr(zLine, "text/")!=0;
117
printf("|** %s content type **|\n",
118
textMimetype ? "Text" : "Non-text");
119
}
120
if( strncasecmp(zLine,"Content-Transfer-Encoding:", 26)==0 ){
121
if( strcasestr(zLine, "base64") ){
122
decodeType = BASE64;
123
}else if( strcasestr(zLine, "quoted-printable") ){
124
decodeType = QUOTED;
125
}else{
126
decodeType = BINARY;
127
}
128
printf("|** Content encoding %s **|\n",
129
decodeType==BASE64 ? "BASE64" :
130
decodeType==QUOTED ? "QUOTED" : "BINARY");
131
}
132
zB = strstr(zLine, "boundary=\"");
133
if( zB ){
134
int kk;
135
zB += 10;
136
for(kk=0; zB[kk] && zB[kk]!='"' && kk<sizeof(zBoundary)-1; kk++){
137
zBoundary[kk] = zB[kk];
138
}
139
zBoundary[kk] = 0;
140
nBoundary = kk;
141
printf("|** boundary [%s] **|\n", zBoundary);
142
}
143
}
144
}
145
146
int main(int argc, char **argv){
147
if( argc==1 ){
148
convert_file("<stdin>", stdin);
149
return 0;
150
}else{
151
int i;
152
for(i=1; i<argc; i++){
153
FILE *in = fopen(argv[i], "rb");
154
if( in==0 ){
155
fprintf(stderr, "cannot open \"%s\"", argv[i]);
156
}else{
157
convert_file(argv[i], in);
158
fclose(in);
159
}
160
}
161
}
162
return 0;
163
}
164

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button