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