tqp.c - scribo - Email-based phlog generator
HTML git clone git://git.z3bra.org/scribo.git
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tqp.c (2081B)
---
1 #include <ctype.h>
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <limits.h>
8
9 #include "qp.h"
10
11 #define QP_FOLD 76
12
13 static char *
14 qp_bin2hex(const int in, char *out)
15 {
16 char hex[] = "0123456789ABCDEF";
17
18 out[0] = hex[(unsigned char)in >> 4];
19 out[1] = hex[(unsigned char)in & 15];
20
21 return out;
22 }
23
24 static char
25 qp_hex2bin(const unsigned char *in)
26 {
27 int out;
28
29 if (*in == '=')
30 in++;
31
32 if ('A' <= in[0] && in[0] <= 'F') out = 16 * (in[0] - 'A' + 10);
33 if ('0' <= in[0] && in[0] <= '9') out = 16 * (in[0] - '0');
34
35 if ('A' <= in[1] && in[1] <= 'F') out += (in[1] - 'A' + 10);
36 if ('0' <= in[1] && in[1] <= '9') out += (in[1] - '0');
37
38 return out;
39 }
40
41 /*
42 * Encode the given message in qp, allocate memory to store the encoded
43 * message, and return the size allocated.
44 */
45 size_t
46 qp_encode(char **buf, const unsigned char *msg, size_t len)
47 {
48 size_t i, n;
49 char *p;
50
51 /* maximum size the encoded message can have */
52 *buf = malloc(len * 3);
53 if (!*buf)
54 return 0;
55
56 p = *buf;
57 memset(*buf, 0, len * 3);
58
59 for (i = 0; i < len; i++) {
60 if (isascii(msg[i]) && msg[i] != '=') {
61 *(p++) = msg[i];
62 n++;
63 } else if (msg[i] == '=') {
64 strcpy(p, "==");
65 p += 2;
66 n += 2;
67 } else {
68 if (n > 72) {
69 strcpy(p, "=\n");
70 p += 2;
71 n = 0;
72 }
73 qp_bin2hex(msg[i], p);
74 p += 3;
75 n += 3;
76 }
77 if (n > 74) {
78 *(p++) = '=';
79 *(p++) = '\n';
80 n = 0;
81 }
82 }
83
84 return strnlen(*buf, len * 3);;
85 }
86
87 /*
88 * Allocate size to decode a qp message, decode it in the buffer and
89 * return the allocated size.
90 */
91 size_t
92 qp_decode(char **buf, const unsigned char *msg, size_t len)
93 {
94 size_t i;
95 char *p;
96
97 /* maximum size the encoded message can have */
98 *buf = malloc(len);
99 if (!*buf)
100 return 0;
101
102 p = *buf;
103 memset(*buf, 0, len);
104
105 for (i = 0; i < len && msg[i]; i++) {
106 if (msg[i] == '=') {
107 switch (msg[i+1]) {
108 case '\r': i++; /* FALLTHROUGH */
109 case '\n': i++; break;
110 default:
111 *(p++) = qp_hex2bin(&msg[i]);
112 i += 2;
113 }
114 } else {
115 *(p++) = msg[i];
116 }
117 }
118
119 return strnlen(*buf, len);
120 }