4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
25 static char tob64(char x)
33 return x == 62 ? '+' : '/';
36 char *base64encw(const char *buffer, int length, int width)
41 if (width == 0 || width % 4) {
42 ERROR("bad width in base64enc");
45 result = malloc(2 + 4 * ((length + 2) / 3) + (length / width));
47 ERROR("malloc failed in base64enc");
53 if (out % (width + 1) == width)
55 result[out] = tob64((buffer[in] >> 2) & '\x3f');
56 result[out+1] = tob64(((buffer[in] << 4) & '\x30') | ((buffer[in+1] >> 4) & '\x0f'));
57 result[out+2] = tob64(((buffer[in+1] << 2) & '\x3c') | ((buffer[in+2] >> 6) & '\x03'));
58 result[out+3] = tob64(buffer[in+2] & '\x3f');
64 if (out % (width + 1) == width)
66 result[out] = tob64((buffer[in] >> 2) & '\x3f');
68 result[out+1] = tob64((buffer[in] << 4) & '\x30');
71 result[out+1] = tob64(((buffer[in] << 4) & '\x30') | ((buffer[in+1] >> 4) & '\x0f'));
72 result[out+2] = tob64((buffer[in+1] << 2) & '\x3c');
81 char *base64enc(const char *buffer, int length)
83 return base64encw(buffer, length, 76);
86 static char fromb64(char x)
88 if ('A' <= x && x <= 'Z')
90 if ('a' <= x && x <= 'z')
92 if ('0' <= x && x <= '9')
103 int base64dec(const char *buffer, char **output)
107 unsigned char x0, x1, x2, x3;
109 len = strlen(buffer);
110 result = malloc(3 * ((3 + len) / 4));
111 if (result == NULL) {
112 ERROR("malloc failed in base64dec");
116 while (buffer[in] == '\r' || buffer[in] == '\n')
120 ERROR("unexpected input size in base64dec");
124 x0 = (unsigned char)fromb64(buffer[in]);
125 x1 = (unsigned char)fromb64(buffer[in+1]);
126 x2 = (unsigned char)fromb64(buffer[in+2]);
127 x3 = (unsigned char)fromb64(buffer[in+3]);
129 if (x0 == 'E' || x1 == 'E' || x2 == 'E' || x3 == 'E') {
130 ERROR("unexpected input character in base64dec");
134 if (x0 == '@' || x1 == '@' || (x2 == '@' && x3 != '@')) {
135 ERROR("unexpected termination character in base64dec");
139 result[out] = (char)((x0 << 2) | (x1 >> 4));
140 result[out+1] = (char)((x1 << 4) | ((x2 >> 2) & 15));
141 result[out+2] = (char)((x2 << 6) | (x3 & 63));
142 while (buffer[in] == '\r' || buffer[in] == '\n')
146 else if (!buffer[in])
147 out += 1 + (x2 != '@');
149 ERROR("unexpected continuation in base64dec");
158 int base64eq(const char *buf1, const char *buf2)
161 while(*buf1 == '\n' || *buf1 == '\r')
163 while(*buf2 == '\n' || *buf2 == '\r')
178 int main(int ac, char **av)
185 fd = open(*av, O_RDONLY);
186 if (fd < 0) continue;
187 l0 = read(fd, buffer, sizeof buffer);
188 if (l0 <= 0) continue;
190 p1 = base64enc(buffer, l0);
193 l2 = base64dec(p1, &p2);
194 if (l2 <= 0) continue;
195 printf("[[[%.*s]]]\n",l2,p2);
196 if (l0 != l2) printf("length mismatch\n");
197 else if (memcmp(buffer, p2, l0)) printf("content mismatch\n");