mess822x 1.23
mess822x
Loading...
Searching...
No Matches
mess822_qp.c
Go to the documentation of this file.
1#include "mess822.h"
2#include "str.h"
3
4static const char qptab[] =
5{
6// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
7 0, 0, 0, 0, 0, 0, 0, 0, 0,'\t','\n', 0, 0, 0, 0, 0,
8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0 , 0, 0, 0, 0, 0,
9 ' ' ,'!','"','#','$','%','&','\'','(',')' ,'*' ,'+', ',','-','.','/',
10 '0' ,'1','2','3','4','5','6','7' ,'8','9' ,':' ,';', '<', 0,'>','?',
11 '@' ,'A','B','C','D','E','F','G' ,'H','I' ,'J' ,'K', 'L','M','N','O',
12 'P' ,'Q','R','S','T','U','V','W' ,'X','Y' ,'Z' ,'[','\\',']','^','_',
13 '`' ,'a','b','c','d','e','f','g' ,'h','i' ,'j' ,'k', 'l','m','n','o',
14 'p' ,'q','r','s','t','u','v','w' ,'x','y' ,'z' ,'{', '|','}','~', 0,
15};
16
17static const char hextab[] = "0123456789abcdef";
18static const char qpok[] = "0123456789abcdef "; // FIXME: Invalid last char required
19static const char QPok[] = "0123456789ABCDEF "; // FIXME: Invalid last char required
20
21int hex2dec(char hex[2])
22{
23 unsigned char c, dec = 0;
24
25 for (int i = 0; i < 2; i++) {
26 c = hex[i];
27 dec <<= 4;
28 if (c >= '0' && c <= '9') dec += c - '0';
29 else if (c >= 'A' && c <= 'F') dec += c - 55; // 'A' - 10
30 else if (c >= 'a' && c <= 'f') dec += c - 87; // 'a' - 10
31 else return -1;
32 }
33 return dec;
34}
35
36static int decode_qp(const char *s)
37{
38 if (*s == '=') {
39 if (*s == '\n') s + 1;
40 return hex2dec(s + 1);
41 } else
42 return -1;
43}
44
45/* If the character is <= ' ', > '~', or '=', we want to
46 * print it out in =XY format, unless it's a \n, where
47 * we dump a RFC822 \r\n, or unless it's a tab or space,
48 * where we display it as is, except if it's at end of
49 * line we need to dump a soft linebreak to keep from
50 * having a bare whitespace at the end of the line
51 * (RFC1541 5.1, rule 3). If the line ever gets over
52 * 70 characters long, we need to drop a soft linebreak
53 * and start a new line (RFC1541 5.1, rule 5). If none
54 * of the above is true, dump the ascii value of the
55 * character and continue on our way.
56 *
57 * Return number of byte encoded
58*/
59
60int mess822_qpencode(stralloc *out,stralloc *in)
61{
62 int r = 0; // number of written chars
63 unsigned char ch;
64 char xch[2];
65
66 if (in->len == 0) {
67 if (!stralloc_copys(out,"")) return -1;
68 return 0;
69 }
70 if (!stralloc_copys(out,"")) return -1;
71
72 for (int i = 0; i < in->len - 1; i++) {
73 ch = in->s[i];
74 if ((ch & 0x80) || (ch == '.') || (qptab[ch] == 0)) {
75 if (!stralloc_append(out,"=")) return -1;
76 r++;
77 xch[0] = hextab[(ch >> 4) & 0x0f];
78 xch[1] = hextab[(ch & 0x0f)];
79 if (!stralloc_catb(out,xch,2)) return -1;
80 r += 2;
81 } else {
82 if (!stralloc_append(out,in->s + i)) return -1;
83 r++;
84 }
85 if (r % 76 == 0) if (!stralloc_catb(out,"=\n",2)) return -1;
86 r += 2;
87 }
88
89 return r;
90}
91
92/* Decode a quoted-printable string:
93 1. Convert 2 byte chars introduced by '='.
94 2. Respect \r\n and \r.
95 3. Translate '_' as WSP if RFC 2047.
96 4. Treat standard chars unchanged.
97 The incoming byte sequence does not need to be \0 terminated.
98 The outgoing stralloc is \0 terminated.
99
100 Return number of bytes decoded, -1 if out of memory
101*/
102
103int mess822_qpdecode(stralloc *out,const char *in,int len,int flag)
104{
105 int r = 0;
106 char ch;
107
108 if (len == 0) {
109 if (!stralloc_copys(out,"")) return -1;
110 return 1;
111 }
112 if (!stralloc_readyplus(out,len)) return -1;
113
114 while (len) {
115 if (*in == '\0') return r; // done
116 if (flag == 2047 && *in == '_') { // RFC 2047 ยง 4.2(2)
117 if (!stralloc_append(out," ")) return -1;
118 r++, in++; len--; continue;
119 }
120 if (*in == '=') { // QP double byte char
121 if (*(in + 1) == '\n') { in += 2; len -= 2; continue; }
122 if ((str_chr(QPok,*(in + 1)) < 16 && str_chr(QPok,*(in + 2)) < 16) ||
123 (str_chr(qpok,*(in + 1)) < 16 && str_chr(qpok,*(in + 2)) < 16)) {
124 ch = hex2dec(in + 1);
125 if (!stralloc_append(out,&ch)) return -1;
126 r++; in += 3; len -= 3;
127 } else { r += 2; in += 2; len -= 2; continue; } // ignore any none-valid char
128 }
129 else { // standard char
130 if (!stralloc_append(out,in)) return -1;
131 r++; in++; len--;
132 }
133 }
134 if (!stralloc_0(out)) return -1;
135
136 return r;
137}
stralloc out
Definition: b64decode.c:12
void c(char *, char *, char *, int, int, int)
Definition: install.c:46
int flag
Definition: 822field.c:16
int mess822_qpdecode(stralloc *out, const char *in, int len, int flag)
Definition: mess822_qp.c:103
int mess822_qpencode(stralloc *out, stralloc *in)
Definition: mess822_qp.c:60
int hex2dec(char hex[2])
Definition: mess822_qp.c:21