Added -messageid switch to send(1) and post(8). This allows selection
[mmh] / sbr / base64.c
1 /*
2  * base64.c -- routines for converting to base64
3  *
4  * This code is Copyright (c) 2012, by the authors of nmh.  See the
5  * COPYRIGHT file in the root directory of the nmh distribution for
6  * complete copyright information.
7  */
8
9 #include <h/mh.h>
10 #include <h/mime.h>
11
12 static char nib2b64[0x40+1] =
13         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
14
15 int
16 writeBase64aux (FILE *in, FILE *out)
17 {
18     unsigned int cc, n;
19     char inbuf[3];
20
21     n = BPERLIN;
22     while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
23         unsigned long bits;
24         char *bp;
25         char outbuf[4];
26
27         if (cc < sizeof(inbuf)) {
28             inbuf[2] = 0;
29             if (cc < sizeof(inbuf) - 1)
30                 inbuf[1] = 0;
31         }
32         bits = (inbuf[0] & 0xff) << 16;
33         bits |= (inbuf[1] & 0xff) << 8;
34         bits |= inbuf[2] & 0xff;
35
36         for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6)
37             *--bp = nib2b64[bits & 0x3f];
38         if (cc < sizeof(inbuf)) {
39             outbuf[3] = '=';
40             if (cc < sizeof inbuf - 1)
41                 outbuf[2] = '=';
42         }
43
44         fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out);
45
46         if (cc < sizeof(inbuf)) {
47             putc ('\n', out);
48             return OK;
49         }
50
51         if (--n <= 0) {
52             n = BPERLIN;
53             putc ('\n', out);
54         }
55     }
56     if (n != BPERLIN)
57         putc ('\n', out);
58
59     return OK;
60 }
61
62
63 /* Caller is responsible for ensuring that the out array is long
64    enough.  Given length is that of in, out should be have at
65    least this capacity:
66      4 * [length/3]  +  length/57  +  2
67    But double the length will certainly be sufficient. */
68 int
69 writeBase64 (unsigned char *in, size_t length, unsigned char *out)
70 {
71     unsigned int n = BPERLIN;
72
73     while (1) {
74         unsigned long bits;
75         unsigned char *bp;
76         unsigned int cc;
77         for (cc = 0, bp = in; length > 0 && cc < 3; ++cc, ++bp, --length)
78           /* empty */ ;
79
80         if (cc == 0) {
81             break;
82         } else {
83             bits = (in[0] & 0xff) << 16;
84             if (cc > 1) {
85                 bits |= (in[1] & 0xff) << 8;
86                 if (cc > 2) {
87                     bits |= in[2] & 0xff;
88                 }
89             }
90         }
91
92         for (bp = out + 4; bp > out; bits >>= 6)
93             *--bp = nib2b64[bits & 0x3f];
94         if (cc < 3) {
95             out[3] = '=';
96             if (cc < 2)
97                 out[2] = '=';
98             out += 4;
99             n = 0;
100             break;
101         }
102
103         in += 3;
104         out += 4;
105         if (--n <= 0) {
106             n = BPERLIN;
107             *out++ = '\n';
108         }
109     }
110     if (n != BPERLIN)
111         *out++ = '\n';
112
113     *out = '\0';
114
115     return OK;
116 }