mp3_afh: Move mode_text[] into header_mode().
[paraslash.git] / base64.c
1 /*
2  * The code in this file was taken from openssh-5.2p1, Copyright (c) 1996 by
3  * Internet Software Consortium.  Portions Copyright (c) 1995 by International
4  * Business Machines, Inc.
5  */
6
7 /** \file base64.c Uudecode and base64decode implementation. */
8
9 #include <regex.h>
10
11 #include "para.h"
12 #include "error.h"
13 #include "base64.h"
14 #include "string.h"
15
16 static const unsigned char base64_tab[256] = {
17         255, 255, 255, 255, 255, 255, 255, 255, /* 00-07 */
18         255, 255, 255, 255, 255, 255, 255, 255, /* 08-0f */
19         255, 255, 255, 255, 255, 255, 255, 255, /* 10-17 */
20         255, 255, 255, 255, 255, 255, 255, 255, /* 18-1f */
21         255, 255, 255, 255, 255, 255, 255, 255, /* 20-2f */
22         255, 255, 255,  62, 255, 255, 255,  63, /* 28-2f */
23         52 ,  53,  54,  55,  56,  57,  58,  59, /* 30-37 */
24         60 ,  61, 255, 255, 255, 255, 255, 255, /* 38-3f */
25         255,   0,   1,   2,   3,   4,   5,   6, /* 40-47 */
26         7  ,   8,   9,  10,  11,  12,  13,  14, /* 48-4f */
27         15 ,  16,  17,  18,  19,  20,  21,  22, /* 50-57 */
28         23 ,  24,  25, 255, 255, 255, 255, 255, /* 58-5f */
29         255,  26,  27,  28,  29,  30,  31,  32, /* 60-6f */
30         33 ,  34,  35,  36,  37,  38,  39,  40, /* 68-6f */
31         41 ,  42,  43,  44,  45,  46,  47,  48, /* 70-77 */
32         49 ,  50,  51, 255, 255, 255, 255, 255, /* 78-7f */
33         255, 255, 255, 255, 255, 255, 255, 255, /* 80-87 */
34         255, 255, 255, 255, 255, 255, 255, 255, /* 88-8f */
35         255, 255, 255, 255, 255, 255, 255, 255, /* 90-97 */
36         255, 255, 255, 255, 255, 255, 255, 255, /* 98-9f */
37         255, 255, 255, 255, 255, 255, 255, 255, /* a0-a7 */
38         255, 255, 255, 255, 255, 255, 255, 255, /* a8-af */
39         255, 255, 255, 255, 255, 255, 255, 255, /* b0-b7 */
40         255, 255, 255, 255, 255, 255, 255, 255, /* b8-bf */
41         255, 255, 255, 255, 255, 255, 255, 255, /* c0-c7 */
42         255, 255, 255, 255, 255, 255, 255, 255, /* c8-cf */
43         255, 255, 255, 255, 255, 255, 255, 255, /* d0-d7 */
44         255, 255, 255, 255, 255, 255, 255, 255, /* d8-df */
45         255, 255, 255, 255, 255, 255, 255, 255, /* e0-e7 */
46         255, 255, 255, 255, 255, 255, 255, 255, /* e8-ef */
47         255, 255, 255, 255, 255, 255, 255, 255, /* f0-f7 */
48         255, 255, 255, 255, 255, 255, 255, 255, /* f8-ff */
49 };
50
51 /** Maximal possible size of the decoded data. */
52 #define BASE64_MAX_DECODED_SIZE(_encoded_size) ((_encoded_size) / 4 * 3)
53
54 #define PAD64 '='
55 /**
56  * base64-decode a buffer.
57  *
58  * \param src The buffer to decode.
59  * \param encoded_size The special value -1 means: look for terminating zero byte.
60  * \param result Points to dynamically allocated target buffer on success.
61  * \param decoded_size Number of bytes written to \a result.
62  *
63  * Skips all whitespace anywhere. Converts characters, four at a time, starting
64  * at (or after) src from base - 64 numbers into three 8 bit bytes in the
65  * target area.
66  *
67  * It is OK to pass a \p NULL pointer as \a decoded_size. The result is
68  * terminated with a zero byte.
69  *
70  * \return Standard. The contents of result \a and \a decoded_size are
71  * undefined on failure.
72  */
73 int base64_decode(char const *src, size_t encoded_size, char **result,
74                 size_t *decoded_size)
75 {
76         size_t i, j, state; /* source/target indices */
77         const char *end = src + encoded_size, *p;
78         unsigned char *target, uch;
79
80         if (encoded_size == (size_t)-1)
81                 encoded_size = strlen(src);
82         target = para_malloc(BASE64_MAX_DECODED_SIZE(encoded_size) + 1);
83
84         for (
85                 i = 0, j = 0, state = 0;
86                 i < encoded_size && (uch = src[i]) != '\0';
87                 i++
88         ) {
89                 if (para_isspace(uch)) /* Skip whitespace anywhere. */
90                         continue;
91                 if (uch == PAD64)
92                         break;
93                 if (base64_tab[uch] == 255) /* A non-base64 character. */
94                         goto fail;
95                 uch = base64_tab[uch];
96                 switch (state) {
97                 case 0:
98                         target[j] = uch << 2;
99                         break;
100                 case 1:
101                         target[j] |= uch >> 4;
102                         j++;
103                         target[j] = (uch & 0x0f) << 4;
104                         break;
105                 case 2:
106                         target[j] |= uch >> 2;
107                         j++;
108                         target[j] = (uch & 0x03) << 6;
109                         break;
110                 case 3:
111                         target[j] |= uch;
112                         j++;
113                         break;
114                 }
115                 state = (state + 1) % 4;
116         }
117         p = (i < encoded_size)? src + i : NULL;
118         /*
119          * We are done decoding Base-64 chars.  Let's see if we ended
120          * on a byte boundary, and/or with erroneous trailing characters.
121          */
122         if (p && *p == PAD64) { /* We got a pad char. Skip it, get next. */
123                 p++;
124                 switch (state) {
125                 case 0: /* Invalid = in first position */
126                 case 1: /* Invalid = in second position */
127                         goto fail;
128
129                 case 2: /* Valid, means one byte of info */
130                         /* Skip any number of spaces. */
131                         for (; p < end && *p != '\0'; p++)
132                                 if (!para_isspace(*p))
133                                         break;
134                         /* Make sure there is another trailing = sign. */
135                         if (*p != PAD64)
136                                 goto fail;
137                         /* Fall through to "single trailing =" case. */
138                         p++;
139
140                 case 3: /* Valid, means two bytes of info */
141                         /*
142                          * We know this char is an =.  Is there anything but
143                          * whitespace after it?
144                          */
145                         for (; p < end && *p != '\0'; p++)
146                                 if (!para_isspace(*p))
147                                         goto fail;
148                         /*
149                          * Now make sure for cases 2 and 3 that the "extra"
150                          * bits that slopped past the last full byte were
151                          * zeros.  If we don't check them, they become a
152                          * subliminal channel.
153                          */
154                         if (target[j] != 0)
155                                 goto fail;
156                 }
157         } else {
158                 /*
159                  * We ended by seeing the end of the string.  Make sure we
160                  * have no partial bytes lying around.
161                  */
162                 if (state != 0)
163                         goto fail;
164         }
165         /* success */
166         target[j] = '\0'; /* just to be sure */
167         if (decoded_size)
168                 *decoded_size = j;
169         *result = (char *)target;
170         return 1;
171 fail:
172         free(target);
173         return -E_BASE64;
174 }
175
176 /**
177  * Decode a buffer using the uuencode Base64 algorithm.
178  *
179  * \param src The buffer to decode.
180  * \param encoded_size Number of input bytes in the source buffer.
181  * \param result Contains the decoded data on success.
182  * \param decoded_size Number of output bytes on success.
183  *
184  * This is just a simple wrapper for \ref base64_decode() which strips
185  * whitespace.
186  *
187  * \return The return value of the underlying call to \ref base64_decode().
188  *
189  * \sa uuencode(1), uudecode(1).
190  */
191 int uudecode(char const *src, size_t encoded_size, char **result,
192                 size_t *decoded_size)
193 {
194         const char *end = src + encoded_size, *p;
195
196         /* skip whitespace and data */
197         for (p = src; p < end && (*p == ' ' || *p == '\t'); p++)
198                 ;
199         for (; p < end && *p != '\0' && *p != ' ' && *p != '\t'; p++)
200                 ;
201         /* and remove trailing whitespace because base64_decode needs this */
202         return base64_decode(src, p - src, result, decoded_size);
203 }