Happy new year
[yaz-moved-to-github.git] / src / base64.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2012 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file base64.c
7  * \brief Base64 encode/decode utilities
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <string.h>
14 #include <yaz/base64.h>
15
16 void yaz_base64encode(const char *in, char *out)
17 {
18     static char encoding[] =
19         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
20     unsigned char buf[3];
21     long n;
22
23     while (*in != 0)
24     {
25         const char *pad = 0;
26         buf[0] = in[0];
27         buf[1] = in[1];
28         if (in[1] == 0)
29         {
30             buf[2] = 0;
31             pad = "==";
32         }
33         else
34         {
35             buf[2] = in[2];
36             if (in[2] == 0)
37                 pad = "=";
38         }
39
40         /* Treat three eight-bit numbers as on 24-bit number */
41         n = (buf[0] << 16) + (buf[1] << 8) + buf[2];
42
43         /* Write the six-bit chunks out as four encoded characters */
44         *out++ = encoding[(n >> 18) & 63];
45         *out++ = encoding[(n >> 12) & 63];
46         if (in[1] != 0)
47             *out++ = encoding[(n >> 6) & 63];
48         if (in[1] != 0 && in[2] != 0)
49             *out++ = encoding[n & 63];
50
51         if (pad != 0) {
52             while (*pad != 0)
53                 *out++ = *pad++;
54             break;
55         }
56         in += 3;
57     }
58     *out++ = 0;
59 }
60
61 int yaz_base64decode(const char *in, char *out)
62 {
63     const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
64         "abcdefghijklmnopqrstuvwxyz0123456789+/";
65     int len = strlen(in);
66
67     while (len >= 4)
68     {
69         char i0, i1, i2, i3;
70         char *p;
71
72         if (!(p = strchr(map, in[0])))
73             return -1;
74         i0 = p - map;
75         len--;
76         if (!(p = strchr(map, in[1])))
77             return -1;
78         i1 = p - map;
79         len--;
80         *(out++) = i0 << 2 | i1 >> 4;
81         if (in[2] == '=')
82             break;
83         if (!(p = strchr(map, in[2])))
84             return -1;
85         i2 = p - map;
86         len--;
87         *(out++) = i1 << 4 | i2 >> 2;
88         if (in[3] == '=')
89             break;
90         if (!(p = strchr(map, in[3])))
91             return -1;
92         i3 = p - map;
93         len--;
94         *(out++) = i2 << 6 | i3;
95
96         in += 4;
97     }
98
99     *out = '\0';
100     return 0;
101 }
102
103 /*
104  * Local variables:
105  * c-basic-offset: 4
106  * c-file-style: "Stroustrup"
107  * indent-tabs-mode: nil
108  * End:
109  * vim: shiftwidth=4 tabstop=8 expandtab
110  */
111