Missing #include.
[sgt/utils] / base64 / base64.c
CommitLineData
9acadc2b 1#include <stdio.h>
2#include <errno.h>
3#include <string.h>
6b7a3adf 4#include <stdlib.h>
80e59395 5#include <ctype.h>
9acadc2b 6
7#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
8 ((c) >= 'a' && (c) <= 'z') || \
9 ((c) >= '0' && (c) <= '9') || \
10 (c) == '+' || (c) == '/' || (c) == '=' \
11 )
12
13int base64_decode_atom(char *atom, unsigned char *out) {
14 int vals[4];
15 int i, v, len;
16 unsigned word;
17 char c;
18
19 for (i = 0; i < 4; i++) {
20 c = atom[i];
21 if (c >= 'A' && c <= 'Z')
22 v = c - 'A';
23 else if (c >= 'a' && c <= 'z')
24 v = c - 'a' + 26;
25 else if (c >= '0' && c <= '9')
26 v = c - '0' + 52;
27 else if (c == '+')
28 v = 62;
29 else if (c == '/')
30 v = 63;
31 else if (c == '=')
32 v = -1;
33 else
34 return 0; /* invalid atom */
35 vals[i] = v;
36 }
37
38 if (vals[0] == -1 || vals[1] == -1)
39 return 0;
40 if (vals[2] == -1 && vals[3] != -1)
41 return 0;
42
43 if (vals[3] != -1)
44 len = 3;
45 else if (vals[2] != -1)
46 len = 2;
47 else
48 len = 1;
49
50 word = ((vals[0] << 18) |
51 (vals[1] << 12) |
52 ((vals[2] & 0x3F) << 6) |
53 (vals[3] & 0x3F));
54 out[0] = (word >> 16) & 0xFF;
55 if (len > 1)
56 out[1] = (word >> 8) & 0xFF;
57 if (len > 2)
58 out[2] = word & 0xFF;
59 return len;
60}
61
62void base64_encode_atom(unsigned char *data, int n, char *out) {
63 static const char base64_chars[] =
64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
65
66 unsigned word;
67
68 word = data[0] << 16;
69 if (n > 1)
70 word |= data[1] << 8;
71 if (n > 2)
72 word |= data[2];
73 out[0] = base64_chars[(word >> 18) & 0x3F];
74 out[1] = base64_chars[(word >> 12) & 0x3F];
75 if (n > 1)
76 out[2] = base64_chars[(word >> 6) & 0x3F];
77 else
78 out[2] = '=';
79 if (n > 2)
80 out[3] = base64_chars[word & 0x3F];
81 else
82 out[3] = '=';
83}
84
85const char usagemsg[] =
86 "usage: base64 [-d] [filename] decode from a file or from stdin\n"
87 " or: base64 -e [-cNNN] [filename] encode from a file or from stdin\n"
9acadc2b 88 "where: -d decode mode (default)\n"
89 " -e encode mode\n"
90 " -cNNN set number of chars per line for encoded output\n"
c52f9fb9 91 " also: base64 --version report version number\n"
92 " base64 --help display this help text\n"
93 " base64 --licence display the (MIT) licence text\n"
9acadc2b 94 ;
95
96void usage(void) {
97 fputs(usagemsg, stdout);
98}
99
da0f8522 100const char licencemsg[] =
101 "base64 is copyright 2001,2004 Simon Tatham.\n"
102 "\n"
103 "Permission is hereby granted, free of charge, to any person\n"
104 "obtaining a copy of this software and associated documentation files\n"
105 "(the \"Software\"), to deal in the Software without restriction,\n"
106 "including without limitation the rights to use, copy, modify, merge,\n"
107 "publish, distribute, sublicense, and/or sell copies of the Software,\n"
108 "and to permit persons to whom the Software is furnished to do so,\n"
109 "subject to the following conditions:\n"
110 "\n"
111 "The above copyright notice and this permission notice shall be\n"
112 "included in all copies or substantial portions of the Software.\n"
113 "\n"
114 "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n"
115 "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
116 "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n"
117 "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n"
118 "BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n"
119 "ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
120 "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
121 "SOFTWARE.\n"
122 ;
123
124void licence(void) {
125 fputs(licencemsg, stdout);
126}
127
9acadc2b 128void version(void) {
129#define SVN_REV "$Revision$"
130 char rev[sizeof(SVN_REV)];
131 char *p, *q;
132
133 strcpy(rev, SVN_REV);
134
135 for (p = rev; *p && *p != ':'; p++);
136 if (*p) {
137 p++;
138 while (*p && isspace(*p)) p++;
139 for (q = p; *q && *q != '$'; q++);
140 if (*q) *q = '\0';
141 printf("base64 revision %s\n", p);
142 } else {
143 printf("base64: unknown version\n");
144 }
145}
146
147int main(int ac, char **av) {
148 int encoding = 0;
149 int cpl = 64;
150 FILE *fp;
151 char *fname;
152 char *eptr;
153
154 fname = NULL;
155
156 while (--ac) {
157 char *v, *p = *++av;
158 if (*p == '-') {
159 while (*p) {
160 char c = *++p;
161 switch (c) {
162 case '-':
da0f8522 163 p++;
9acadc2b 164 if (!strcmp(p, "version")) {
165 version();
166 exit(0);
da0f8522 167 } else if (!strcmp(p, "help")) {
9acadc2b 168 usage();
169 exit(0);
da0f8522 170 } else if (!strcmp(p, "licence") ||
171 !strcmp(p, "license")) {
172 licence();
173 exit(0);
174 } else {
175 fprintf(stderr, "base64: unknown long option '--%s'\n",
176 p);
177 exit(1);
178 }
9acadc2b 179 break;
180 case 'v':
181 case 'V':
182 version();
183 exit(0);
184 break;
185 case 'h':
186 case 'H':
187 usage();
188 exit(0);
189 break;
190 case 'd':
191 encoding = 0;
192 break;
193 case 'e':
194 encoding = 1;
195 break;
196 case 'c':
197 /*
198 * Options requiring values.
199 */
200 v = p+1;
201 if (!*v && ac > 1) {
202 --ac;
203 v = *++av;
204 }
205 if (!*v) {
206 fprintf(stderr, "base64: option '-%c' expects"
207 " an argument\n", c);
208 exit(1);
209 }
210 switch (c) {
211 case 'c':
212 cpl = strtol(v, &eptr, 10);
213 if (eptr && *eptr) {
214 fprintf(stderr, "base64: option -c expects"
215 " a numeric argument\n");
216 exit(1);
217 }
218 if (cpl % 4) {
219 fprintf(stderr, "base64: chars per line should be"
220 " divisible by 4\n");
221 exit(1);
222 }
223 break;
224 }
225 p = "";
226 break;
227 }
228 }
229 } else {
230 if (!fname)
231 fname = p;
232 else {
233 fprintf(stderr, "base64: expected only one filename\n");
234 exit(0);
235 }
236 }
237 }
238
239 if (fname) {
240 fp = fopen(fname, encoding ? "rb" : "r");
241 if (!fp) {
242 fprintf(stderr, "base64: unable to open '%s': %s\n", fname,
243 strerror(errno));
244 exit(1);
245 }
246 } else
247 fp = stdin;
248
249 if (encoding) {
250 unsigned char in[3];
251 char out[4];
252 int column;
253 int n;
254
255 column = 0;
256 while (1) {
257 if (cpl && column >= cpl) {
258 putchar('\n');
259 column = 0;
260 }
261 n = fread(in, 1, 3, fp);
262 if (n == 0) break;
263 base64_encode_atom(in, n, out);
264 fwrite(out, 1, 4, stdout);
265 column += 4;
266 }
267
268 putchar('\n');
269 } else {
270 char in[4];
271 unsigned char out[3];
272 int c, i, n, eof;
273
274 eof = 0;
275 do {
276 for (i = 0; i < 4; i++) {
277 do {
278 c = fgetc(fp);
279 } while (c != EOF && !isbase64(c));
280 if (c == EOF) {
281 eof = 1;
282 break;
283 }
284 in[i] = c;
285 }
286 if (i > 0) {
287 if (i < 4) {
288 fprintf(stderr, "base64: warning: number of base64"
289 " characters was not a multiple of 4\n");
290 while (i < 4) in[i++] = '=';
291 }
292 n = base64_decode_atom(in, out);
293 fwrite(out, 1, n, stdout);
294 }
295 } while (!eof);
296 }
297
298 if (fname)
299 fclose(fp);
300
301 return 0;
302}