source: BAORadio/libindi/v1.0.1/base64.c @ 629

Last change on this file since 629 was 490, checked in by campagne, 14 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.