source: BAORadio/libindi/v1/base64.c@ 670

Last change on this file since 670 was 490, checked in by campagne, 15 years ago

import libindi (JEC)

File size: 7.1 KB
Line 
1#if 0
2 INDI
3 Copyright (C) 2003 Elwood C. Downey
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Adapted from code written by Eric S. Raymond <esr@snark.thyrsus.com>
20#endif
21
22/* Pair of functions to convert to/from base64.
23 * Also can be used to build a standalone utility and a loopback test.
24 * see http://www.faqs.org/rfcs/rfc3548.html
25 */
26
27/** \file base64.c
28 \brief Pair of functions to convert to/from base64.
29
30*/
31
32#include <ctype.h>
33#include "base64.h"
34
35static const char base64digits[] =
36 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
37
38#define BAD (-1)
39static const char base64val[] = {
40 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
41 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
42 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
43 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
44 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
45 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD,
46 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
47 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD
48};
49#define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
50
51/* convert inlen raw bytes at in to base64 string (NUL-terminated) at out.
52 * out size should be at least 4*inlen/3 + 4.
53 * return length of out (sans trailing NUL).
54 */
55int
56to64frombits(unsigned char *out, const unsigned char *in, int inlen)
57{
58 unsigned char *out0 = out;
59
60 for (; inlen >= 3; inlen -= 3)
61 {
62 *out++ = base64digits[in[0] >> 2];
63 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
64 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
65 *out++ = base64digits[in[2] & 0x3f];
66 in += 3;
67 }
68 if (inlen > 0)
69 {
70 unsigned char fragment;
71
72 *out++ = base64digits[in[0] >> 2];
73 fragment = (in[0] << 4) & 0x30;
74 if (inlen > 1)
75 fragment |= in[1] >> 4;
76 *out++ = base64digits[fragment];
77 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
78 *out++ = '=';
79 }
80 *out = '\0';
81
82 return (out-out0);
83}
84
85/* convert base64 at in to raw bytes out, returning count or <0 on error.
86 * base64 may contain any embedded whitespace.
87 * out should be at least 3/4 the length of in.
88 */
89int
90from64tobits(char *out, const char *in)
91{
92 int len = 0;
93 register unsigned char digit1, digit2, digit3, digit4;
94
95 do {
96 do {digit1 = *in++;} while (isspace(digit1));
97 if (DECODE64(digit1) == BAD)
98 return(-1);
99 do {digit2 = *in++;} while (isspace(digit2));
100 if (DECODE64(digit2) == BAD)
101 return(-2);
102 do {digit3 = *in++;} while (isspace(digit3));
103 if (digit3 != '=' && DECODE64(digit3) == BAD)
104 return(-3);
105 do {digit4 = *in++;} while (isspace(digit4));
106 if (digit4 != '=' && DECODE64(digit4) == BAD)
107 return(-4);
108 *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
109 ++len;
110 if (digit3 != '=')
111 {
112 *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
113 ++len;
114 if (digit4 != '=')
115 {
116 *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
117 ++len;
118 }
119 }
120 while (isspace(*in))
121 in++;
122 } while (*in && digit4 != '=');
123
124 return (len);
125}
126
127#ifdef BASE64_PROGRAM
128/* standalone program that converts to/from base64.
129 * cc -o base64 -DBASE64_PROGRAM base64.c
130 */
131
132#include <stdio.h>
133#include <stdlib.h>
134#include <string.h>
135
136static void
137usage (char *me)
138{
139 fprintf (stderr, "Purpose: convert stdin to/from base64 on stdout\n");
140 fprintf (stderr, "Usage: %s {-t,-f}\n", me);
141 exit (1);
142}
143
144int
145main (int ac, char *av[])
146{
147 int to64 = 1;
148
149 /* decide whether to or from base64 */
150 if (ac == 2 && strcmp (av[1], "-f") == 0)
151 to64 = 0;
152 else if (ac != 1 && (ac != 2 || strcmp (av[1], "-t")))
153 usage (av[0]);
154
155 if (to64) {
156 unsigned char *rawin, *b64;
157 int i, n, nrawin, nb64;
158
159 /* read raw on stdin until EOF */
160 rawin = malloc(4096);
161 nrawin = 0;
162 while ((n = fread (rawin+nrawin, 1, 4096, stdin)) > 0)
163 rawin = realloc (rawin, (nrawin+=n)+4096);
164
165 /* convert to base64 */
166 b64 = malloc (4*nrawin/3+4);
167 nb64 = to64frombits(b64, rawin, nrawin);
168
169 /* pretty print */
170 for (i = 0; i < nb64; i += 72)
171 printf ("%.*s\n", 72, b64+i);
172 } else {
173 unsigned char *raw, *b64;
174 int n, nraw, nb64;
175
176 /* read base64 on stdin until EOF */
177 b64 = malloc(4096);
178 nb64 = 0;
179 while ((n = fread (b64+nb64, 1, 4096, stdin)) > 0)
180 b64 = realloc (b64, (nb64+=n)+4096);
181 b64[nb64] = '\0';
182
183 /* convert to raw */
184 raw = malloc (3*nb64/4);
185 nraw = from64tobits(raw, b64);
186 if (nraw < 0) {
187 fprintf (stderr, "base64 conversion error: %d\n", nraw);
188 return (1);
189 }
190
191 /* write */
192 fwrite (raw, 1, nraw, stdout);
193 }
194
195 return (0);
196}
197
198#endif
199
200#ifdef LOOPBACK_TEST
201/* standalone test that reads binary on stdin, converts to base64 and back,
202 * then compares. exit 0 if compares the same else 1
203 */
204
205#include <stdio.h>
206#include <stdlib.h>
207#include <string.h>
208
209int
210main (int ac, char *av[])
211{
212 unsigned char *rawin, *b64, *rawback;
213 int n, nrawin, nrawback, nb64;
214
215 /* read raw on stdin until EOF */
216 rawin = malloc(4096);
217 nrawin = 0;
218 while ((n = fread (rawin+nrawin, 1, 4096, stdin)) > 0)
219 rawin = realloc (rawin, (nrawin+=n)+4096);
220
221 /* convert to base64 */
222 b64 = malloc (4*nrawin*3 + 4);
223 nb64 = to64frombits(b64, rawin, nrawin);
224
225 /* convert back to raw */
226 rawback = malloc (3*nb64/4);
227 nrawback = from64tobits(rawback, b64);
228 if (nrawback < 0) {
229 fprintf (stderr, "base64 error: %d\n", nrawback);
230 return(1);
231 }
232 if (nrawback != nrawin) {
233 fprintf (stderr, "base64 back length %d != %d\n", nrawback, nrawin);
234 return(1);
235 }
236
237 /* compare */
238 if (memcmp (rawback, rawin, nrawin)) {
239 fprintf (stderr, "compare error\n");
240 return (1);
241 }
242
243 /* success */
244 return (0);
245}
246#endif
247/* For RCS Only -- Do Not Edit */
248static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile$ $Date: 2006-09-30 14:19:41 +0300 (Sat, 30 Sep 2006) $ $Revision: 590506 $ $Name: $"};
Note: See TracBrowser for help on using the repository browser.