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