chiark / gitweb /
Start on 'settings' window. Currently disabled as it's not very
[disorder] / lib / base64.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2005, 2007 Richard Kettlewell
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20 /** @file lib/base64.c
21  * @brief Support for MIME base64
22  */
23
24 #include <config.h>
25 #include "types.h"
26
27 #include <string.h>
28
29 #include <stdio.h>
30
31 #include "mem.h"
32 #include "base64.h"
33 #include "vector.h"
34
35 static const char mime_base64_table[] =
36   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
37
38 /** @brief Convert MIME base64
39  * @param s base64 data
40  * @param nsp Where to store length of converted data
41  * @return Decoded data
42  *
43  * See <a href="http://tools.ietf.org/html/rfc2045#section-6.8">RFC
44  * 2045 s6.8</a>.
45  */
46 char *mime_base64(const char *s, size_t *nsp) {
47   return generic_base64(s, nsp, mime_base64_table);
48 }
49
50 /** @brief Convert base64
51  * @param s base64 data
52  * @param nsp Where to store length of converted data
53  * @param table Table of characters to use
54  * @return Decoded data
55  *
56  * @p table should consist of 65 characters.  The first 64 will be used to
57  * represents the 64 digits and the 65th will be used as padding at the end
58  * (i.e. the role of '=' in RFC2045 base64).
59  */
60 char *generic_base64(const char *s, size_t *nsp, const char *table) {
61   struct dynstr d;
62   const char *t;
63   int b[4], n, c;
64
65   dynstr_init(&d);
66   n = 0;
67   while((c = (unsigned char)*s++)) {
68     if(c == table[64]) {
69       if(n >= 2) {
70         dynstr_append(&d, (b[0] << 2) + (b[1] >> 4));
71         if(n == 3)
72           dynstr_append(&d, (b[1] << 4) + (b[2] >> 2));
73       }
74       break;
75     } else if((t = strchr(table, c))) {
76       b[n++] = t - table;
77       if(n == 4) {
78         dynstr_append(&d, (b[0] << 2) + (b[1] >> 4));
79         dynstr_append(&d, (b[1] << 4) + (b[2] >> 2));
80         dynstr_append(&d, (b[2] << 6) + b[3]);
81         n = 0;
82       }
83     }
84   }
85   if(nsp)
86     *nsp = d.nvec;
87   dynstr_terminate(&d);
88   return d.vec;
89 }
90
91 /** @brief Convert a binary string to MIME base64
92  * @param s Bytes to convert
93  * @param ns Number of bytes to convert
94  * @return Encoded data
95  *
96  * This function does not attempt to split up lines.
97  *
98  * See <a href="http://tools.ietf.org/html/rfc2045#section-6.8">RFC
99  * 2045 s6.8</a>.
100  */
101 char *mime_to_base64(const uint8_t *s, size_t ns) {
102   return generic_to_base64(s, ns, mime_base64_table);
103 }
104
105 /** @brief Convert a binary string to base64
106  * @param s Bytes to convert
107  * @param ns Number of bytes to convert
108  * @param table Table of characters to use
109  * @return Encoded data
110  *
111  * This function does not attempt to split up lines.
112  *
113  * @p table should consist of 65 characters.  The first 64 will be used to
114  * represents the 64 digits and the 65th will be used as padding at the end
115  * (i.e. the role of '=' in RFC2045 base64).
116  */
117 char *generic_to_base64(const uint8_t *s, size_t ns, const char *table) {
118   struct dynstr d[1];
119
120   dynstr_init(d);
121   while(ns >= 3) {
122     /* Input bytes with output bits: AAAAAABB BBBBCCCC CCDDDDDD */
123     /* Output bytes with input bits: 000000 001111 111122 222222 */
124     dynstr_append(d, table[s[0] >> 2]);
125     dynstr_append(d, table[((s[0] & 3) << 4)
126                                        + (s[1] >> 4)]);
127     dynstr_append(d, table[((s[1] & 15) << 2)
128                                        + (s[2] >> 6)]);
129     dynstr_append(d, table[s[2] & 63]);
130     ns -= 3;
131     s += 3;
132   }
133   if(ns > 0) {
134     dynstr_append(d, table[s[0] >> 2]);
135     switch(ns) {
136     case 1:
137       dynstr_append(d, table[(s[0] & 3) << 4]);
138       dynstr_append(d, table[64]);
139       dynstr_append(d, table[64]);
140       break;
141     case 2:
142       dynstr_append(d, table[((s[0] & 3) << 4)
143                                          + (s[1] >> 4)]);
144       dynstr_append(d, table[(s[1] & 15) << 2]);
145       dynstr_append(d, table[64]);
146       break;
147     }
148   }
149   dynstr_terminate(d);
150   return d->vec;
151 }
152
153 /*
154 Local Variables:
155 c-basic-offset:2
156 comment-column:40
157 fill-column:79
158 End:
159 */