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.
24 static char tob64(char x)
32 return x == 62 ? '+' : '/';
35 char *base64encw(const char *buffer, int length, int width)
40 if (width == 0 || width % 4) {
41 syslog(LOG_ERR, "bad width in base64enc");
44 result = malloc(2 + 4 * ((length + 2) / 3) + (length / width));
46 syslog(LOG_ERR, "malloc failed in base64enc");
52 if (out % (width + 1) == width)
54 result[out] = tob64((buffer[in] >> 2) & '\x3f');
55 result[out+1] = tob64(((buffer[in] << 4) & '\x30') | ((buffer[in+1] >> 4) & '\x0f'));
56 result[out+2] = tob64(((buffer[in+1] << 2) & '\x3c') | ((buffer[in+2] >> 6) & '\x03'));
57 result[out+3] = tob64(buffer[in+2] & '\x3f');
63 if (out % (width + 1) == width)
65 result[out] = tob64((buffer[in] >> 2) & '\x3f');
67 result[out+1] = tob64((buffer[in] << 4) & '\x30');
70 result[out+1] = tob64(((buffer[in] << 4) & '\x30') | ((buffer[in+1] >> 4) & '\x0f'));
71 result[out+2] = tob64((buffer[in+1] << 2) & '\x3c');
80 char *base64enc(const char *buffer, int length)
82 return base64encw(buffer, length, 76);
85 static char fromb64(char x)
87 if ('A' <= x && x <= 'Z')
89 if ('a' <= x && x <= 'z')
91 if ('0' <= x && x <= '9')
102 int base64dec(const char *buffer, char **output)
106 unsigned char x0, x1, x2, x3;
108 len = strlen(buffer);
109 result = malloc(3 * ((3 + len) / 4));
110 if (result == NULL) {
111 syslog(LOG_ERR, "malloc failed in base64dec");
115 while (buffer[in] == '\r' || buffer[in] == '\n')
119 syslog(LOG_ERR, "unexpected input size in base64dec");
123 x0 = (unsigned char)fromb64(buffer[in]);
124 x1 = (unsigned char)fromb64(buffer[in+1]);
125 x2 = (unsigned char)fromb64(buffer[in+2]);
126 x3 = (unsigned char)fromb64(buffer[in+3]);
128 if (x0 == 'E' || x1 == 'E' || x2 == 'E' || x3 == 'E') {
129 syslog(LOG_ERR, "unexpected input character in base64dec");
133 if (x0 == '@' || x1 == '@' || (x2 == '@' && x3 != '@')) {
134 syslog(LOG_ERR, "unexpected termination character in base64dec");
138 result[out] = (char)((x0 << 2) | (x1 >> 4));
139 result[out+1] = (char)((x1 << 4) | ((x2 >> 2) & 15));
140 result[out+2] = (char)((x2 << 6) | (x3 & 63));
141 while (buffer[in] == '\r' || buffer[in] == '\n')
145 else if (!buffer[in])
146 out += 1 + (x2 != '@');
148 syslog(LOG_ERR, "unexpected continuation in base64dec");
157 int base64eq(const char *buf1, const char *buf2)
160 while(*buf1 == '\n' || *buf1 == '\r')
162 while(*buf2 == '\n' || *buf2 == '\r')
177 int main(int ac, char **av)
184 fd = open(*av, O_RDONLY);
185 if (fd < 0) continue;
186 l0 = read(fd, buffer, sizeof buffer);
187 if (l0 <= 0) continue;
189 p1 = base64enc(buffer, l0);
192 l2 = base64dec(p1, &p2);
193 if (l2 <= 0) continue;
194 printf("[[[%.*s]]]\n",l2,p2);
195 if (l0 != l2) printf("length mismatch\n");
196 else if (memcmp(buffer, p2, l0)) printf("content mismatch\n");