]> mj.ucw.cz Git - libucw.git/blob - lib/base64.c
configuration reader:
[libucw.git] / lib / base64.c
1 /*
2  *      UCW Library -- Base 64 Encoding & Decoding
3  *
4  *      (c) 2002, Robert Spalek <robert@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #undef LOCAL_DEBUG
11
12 #include "lib/lib.h"
13 #include "lib/base64.h"
14
15 #include <string.h>
16
17 static byte base64_table[] =
18         { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
19           'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
20           'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
21           'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
22           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
23         };
24 static byte base64_pad = '=';
25
26 uns
27 base64_encode(byte *dest, byte *src, uns len)
28 {
29         byte *current = src;
30         uns i = 0;
31
32         while (len > 2) { /* keep going until we have less than 24 bits */
33                 dest[i++] = base64_table[current[0] >> 2];
34                 dest[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
35                 dest[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
36                 dest[i++] = base64_table[current[2] & 0x3f];
37
38                 current += 3;
39                 len -= 3; /* we just handle 3 octets of data */
40         }
41
42         /* now deal with the tail end of things */
43         if (len != 0) {
44                 dest[i++] = base64_table[current[0] >> 2];
45                 if (len > 1) {
46                         dest[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
47                         dest[i++] = base64_table[(current[1] & 0x0f) << 2];
48                         dest[i++] = base64_pad;
49                 }
50                 else {
51                         dest[i++] = base64_table[(current[0] & 0x03) << 4];
52                         dest[i++] = base64_pad;
53                         dest[i++] = base64_pad;
54                 }
55         }
56         return i;
57 }
58
59 /* as above, but backwards. :) */
60 uns
61 base64_decode(byte *dest, byte *src, uns len)
62 {
63         byte *current = src;
64         uns ch;
65         uns i = 0, j = 0;
66         static byte reverse_table[256];
67         static uns table_built = 0;
68
69         if (table_built == 0) {
70                 byte *chp;
71                 table_built = 1;
72                 for(ch = 0; ch < 256; ch++) {
73                         chp = strchr(base64_table, ch);
74                         if(chp) {
75                                 reverse_table[ch] = chp - base64_table;
76                         } else {
77                                 reverse_table[ch] = 0xff;
78                         }
79                 }
80         }
81
82         /* run through the whole string, converting as we go */
83         ch = 0;
84         while (len > 0) {
85                 len--;
86                 ch = *current++;
87                 if (ch == base64_pad) break;
88
89                 /* When Base64 gets POSTed, all pluses are interpreted as spaces.
90                    This line changes them back.  It's not exactly the Base64 spec,
91                    but it is completely compatible with it (the spec says that
92                    spaces are invalid).  This will also save many people considerable
93                    headache.  - Turadg Aleahmad <turadg@wise.berkeley.edu>
94                  */
95
96                 if (ch == ' ') ch = '+';
97
98                 ch = reverse_table[ch];
99                 if (ch == 0xff) continue;
100
101                 switch(i % 4) {
102                 case 0:
103                         dest[j] = ch << 2;
104                         break;
105                 case 1:
106                         dest[j++] |= ch >> 4;
107                         dest[j] = (ch & 0x0f) << 4;
108                         break;
109                 case 2:
110                         dest[j++] |= ch >>2;
111                         dest[j] = (ch & 0x03) << 6;
112                         break;
113                 case 3:
114                         dest[j++] |= ch;
115                         break;
116                 }
117                 i++;
118         }
119         return j;
120 }