fix typo in pt.po headers
[debian/iodine.git] / src / base32.c
1 /*
2  * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
3  * 2006-2009 Bjorn Andersson <flex@kryo.se>
4  * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "encoding.h"
24 #include "base32.h"
25
26 #define BLKSIZE_RAW 5
27 #define BLKSIZE_ENC 8
28
29 static const char cb32[] =
30         "abcdefghijklmnopqrstuvwxyz012345";
31 static const char cb32_ucase[] =
32         "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
33 static unsigned char rev32[256];
34 static int reverse_init = 0;
35
36 static int base32_encode(char *, size_t *, const void *, size_t);
37 static int base32_decode(void *, size_t *, const char *, size_t);
38 static int base32_handles_dots();
39 static int base32_blksize_raw();
40 static int base32_blksize_enc();
41
42 static struct encoder base32_encoder =
43 {
44         "Base32",
45         base32_encode,
46         base32_decode,
47         base32_handles_dots,
48         base32_handles_dots,
49         base32_blksize_raw,
50         base32_blksize_enc
51 };
52
53 struct encoder
54 *get_base32_encoder()
55 {
56         return &base32_encoder;
57 }
58
59 static int
60 base32_handles_dots()
61 {
62         return 0;
63 }
64
65 static int
66 base32_blksize_raw()
67 {
68         return BLKSIZE_RAW;
69 }
70
71 static int
72 base32_blksize_enc()
73 {
74         return BLKSIZE_ENC;
75 }
76
77 inline static void
78 base32_reverse_init()
79 {
80         int i;
81         unsigned char c;
82
83         if (!reverse_init) {
84                 memset (rev32, 0, 256);
85                 for (i = 0; i < 32; i++) {
86                         c = cb32[i];
87                         rev32[(int) c] = i;
88                         c = cb32_ucase[i];
89                         rev32[(int) c] = i;
90                 }
91                 reverse_init = 1;
92         }
93 }
94
95 int
96 b32_5to8(int in)
97 {
98         return cb32[in & 31];
99 }
100
101 int
102 b32_8to5(int in)
103 {
104         base32_reverse_init();
105         return rev32[in];
106 }
107
108 static int
109 base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
110 /*
111  * Fills *buf with max. *buflen characters, encoding size bytes of *data.
112  *
113  * NOTE: *buf space should be at least 1 byte _more_ than *buflen
114  * to hold the trailing '\0'.
115  *
116  * return value    : #bytes filled in buf   (excluding \0)
117  * sets *buflen to : #bytes encoded from data
118  */
119 {
120         unsigned char *udata = (unsigned char *) data;
121         int iout = 0;   /* to-be-filled output char */
122         int iin = 0;    /* one more than last input byte that can be
123                            successfully decoded */
124
125         /* Note: Don't bother to optimize manually. GCC optimizes
126            better(!) when using simplistic array indexing. */
127
128         while (1) {
129                 if (iout >= *buflen || iin >= size)
130                         break;
131                 buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)];
132                 iout++;
133
134                 if (iout >= *buflen || iin >= size) {
135                         iout--;         /* previous char is useless */
136                         break;
137                 }
138                 buf[iout] = cb32[((udata[iin] & 0x07) << 2) |
139                                   ((iin + 1 < size) ?
140                                    ((udata[iin + 1] & 0xc0) >> 6) : 0)];
141                 iin++;                  /* 0 complete, iin=1 */
142                 iout++;
143
144                 if (iout >= *buflen || iin >= size)
145                         break;
146                 buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)];
147                 iout++;
148
149                 if (iout >= *buflen || iin >= size) {
150                         iout--;         /* previous char is useless */
151                         break;
152                 }
153                 buf[iout] = cb32[((udata[iin] & 0x01) << 4) |
154                                   ((iin + 1 < size) ?
155                                    ((udata[iin + 1] & 0xf0) >> 4) : 0)];
156                 iin++;                  /* 1 complete, iin=2 */
157                 iout++;
158
159                 if (iout >= *buflen || iin >= size)
160                         break;
161                 buf[iout] = cb32[((udata[iin] & 0x0f) << 1) |
162                                   ((iin + 1 < size) ?
163                                    ((udata[iin + 1] & 0x80) >> 7) : 0)];
164                 iin++;                  /* 2 complete, iin=3 */
165                 iout++;
166
167                 if (iout >= *buflen || iin >= size)
168                         break;
169                 buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)];
170                 iout++;
171
172                 if (iout >= *buflen || iin >= size) {
173                         iout--;         /* previous char is useless */
174                         break;
175                 }
176                 buf[iout] = cb32[((udata[iin] & 0x03) << 3) |
177                                   ((iin + 1 < size) ?
178                                    ((udata[iin + 1] & 0xe0) >> 5) : 0)];
179                 iin++;                  /* 3 complete, iin=4 */
180                 iout++;
181
182                 if (iout >= *buflen || iin >= size)
183                         break;
184                 buf[iout] = cb32[((udata[iin] & 0x1f))];
185                 iin++;                  /* 4 complete, iin=5 */
186                 iout++;
187         }
188
189         buf[iout] = '\0';
190
191         /* store number of bytes from data that was used */
192         *buflen = iin;
193
194         return iout;
195 }
196
197 #define REV32(x) rev32[(int) (x)]
198
199 static int
200 base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
201 /*
202  * Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
203  * Decoding stops early when *str contains \0.
204  * Illegal encoded chars are assumed to decode to zero.
205  *
206  * NOTE: *buf space should be at least 1 byte _more_ than *buflen
207  * to hold a trailing '\0' that is added (though *buf will usually
208  * contain full-binary data).
209  *
210  * return value    : #bytes filled in buf   (excluding \0)
211  */
212 {
213         unsigned char *ubuf = (unsigned char *) buf;
214         int iout = 0;   /* to-be-filled output byte */
215         int iin = 0;    /* next input char to use in decoding */
216
217         base32_reverse_init ();
218
219         /* Note: Don't bother to optimize manually. GCC optimizes
220            better(!) when using simplistic array indexing. */
221
222         while (1) {
223                 if (iout >= *buflen || iin + 1 >= slen ||
224                     str[iin] == '\0' || str[iin + 1] == '\0')
225                         break;
226                 ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
227                              ((REV32(str[iin + 1]) & 0x1c) >> 2);
228                 iin++;                  /* 0 used up, iin=1 */
229                 iout++;
230
231                 if (iout >= *buflen || iin + 2 >= slen ||
232                     str[iin] == '\0' || str[iin + 1] == '\0' ||
233                     str[iin + 2] == '\0')
234                         break;
235                 ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
236                              ((REV32(str[iin + 1]) & 0x1f) << 1) |
237                              ((REV32(str[iin + 2]) & 0x10) >> 4);
238                 iin += 2;               /* 1,2 used up, iin=3 */
239                 iout++;
240
241                 if (iout >= *buflen || iin + 1 >= slen ||
242                     str[iin] == '\0' || str[iin + 1] == '\0')
243                         break;
244                 ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) |
245                              ((REV32(str[iin + 1]) & 0x1e) >> 1);
246                 iin++;                  /* 3 used up, iin=4 */
247                 iout++;
248
249                 if (iout >= *buflen || iin + 2 >= slen ||
250                     str[iin] == '\0' || str[iin + 1] == '\0' ||
251                     str[iin + 2] == '\0')
252                         break;
253                 ubuf[iout] = ((REV32(str[iin]) & 0x01) << 7) |
254                              ((REV32(str[iin + 1]) & 0x1f) << 2) |
255                              ((REV32(str[iin + 2]) & 0x18) >> 3);
256                 iin += 2;               /* 4,5 used up, iin=6 */
257                 iout++;
258
259                 if (iout >= *buflen || iin + 1 >= slen ||
260                     str[iin] == '\0' || str[iin + 1] == '\0')
261                         break;
262                 ubuf[iout] = ((REV32(str[iin]) & 0x07) << 5) |
263                              ((REV32(str[iin + 1]) & 0x1f));
264                 iin += 2;               /* 6,7 used up, iin=8 */
265                 iout++;
266         }
267
268         ubuf[iout] = '\0';
269
270         return iout;
271 }