Fossil SCM

Add the decode-email.c utility program source code.

drh 2018-06-23 15:49 trunk
Commit 17b4d3e49a3797f1434ec3261a61fda70ebc6448bdbd031156430971756be99e
1 file changed +163
--- a/tools/decode-email.c
+++ b/tools/decode-email.c
@@ -0,0 +1,163 @@
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
+}
--- a/tools/decode-email.c
+++ b/tools/decode-email.c
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/tools/decode-email.c
+++ b/tools/decode-email.c
@@ -0,0 +1,163 @@
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 }

Keyboard Shortcuts

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