WvStreams
wvbase64.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Functions for encoding and decoding strings in MIME's Base64 notation.
6 *
7 * Base 64 is pretty easy. The input is processed in groups of three bytes.
8 * These 24 bits are split into 4 groups of 6 bits. Each group of six bits
9 * is represented by one character in the base64 alphabet, in the encoded
10 * output. The alphabet is as follows:
11 * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
12 * Where 'A' through '/' represent 000000 through 011111, the 64 different
13 * combinations. The '=' (100000) is padding and has no value when decoded.
14 */
15#include "wvbase64.h"
16
17// maps codes to the Base64 alphabet
18static char alphabet[67] =
19 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
20
21// finds codes in the Base64 alphabet
22static int lookup(char ch)
23{
24 if (ch >= 'A' && ch <= 'Z')
25 return ch - 'A';
26 if (ch >= 'a' && ch <= 'z')
27 return ch - 'a' + 26;
28 if (ch >= '0' && ch <= '9')
29 return ch - '0' + 52;
30 if (ch == '+')
31 return 62;
32 if (ch == '/')
33 return 63;
34 if (ch == '=')
35 return 64; // padding
36 if (ch == '\n' || ch == ' ' || ch == '\r' || ch == '\t' ||
37 ch == '\f' || ch == '\v')
38 return 65; // whitespace
39 return -1;
40}
41
42
43/***** WvBase64Encoder *****/
44
49
50
52{
53 state = ATBIT0;
54 bits = 0;
55 return true;
56}
57
58
59bool WvBase64Encoder::_encode(WvBuf &in, WvBuf &out, bool flush)
60{
61 // base 64 encode the entire buffer
62 while (in.used() != 0)
63 {
64 unsigned char next = in.getch();
65 bits = (bits << 8) | next;
66 switch (state)
67 {
68 case ATBIT0:
69 out.putch(alphabet[bits >> 2]);
70 bits &= 0x03;
71 state = ATBIT2;
72 break;
73 case ATBIT2:
74 out.putch(alphabet[bits >> 4]);
75 bits &= 0x0f;
76 state = ATBIT4;
77 break;
78 case ATBIT4:
79 out.putch(alphabet[bits >> 6]);
80 out.putch(alphabet[bits & 0x3f]);
81 bits = 0;
82 state = ATBIT0;
83 break;
84 }
85 }
86 // do not consider the data flushed if we need padding
87 if (flush && state != ATBIT0)
88 return false;
89 return true;
90}
91
92
94{
95 // pad text if needed
96 switch (state)
97 {
98 case ATBIT2:
99 out.putch(alphabet[bits << 4]);
100 out.putch('=');
101 out.putch('=');
102 break;
103 case ATBIT4:
104 out.putch(alphabet[bits << 2]);
105 out.putch('=');
106 break;
107 case ATBIT0:
108 break;
109 }
110 return true;
111}
112
113
114
115/***** WvBase64Decoder *****/
116
121
122
124{
125 state = ATBIT0;
126 bits = 0;
127 return true;
128}
129
130
131bool WvBase64Decoder::_encode(WvBuf &in, WvBuf &out, bool flush)
132{
133 // base 64 decode the entire buffer
134 while (in.used() != 0)
135 {
136 unsigned char next = in.getch();
137 int symbol = lookup(next);
138 switch (symbol)
139 {
140 case -1: // invalid character
141 seterror("invalid character #%s in base64 input", next);
142 return false;
143
144 case 64: // padding
145 // strip out any remaining padding
146 // we are lenient in that we do not track how much padding we skip
147 setfinished();
148 state = PAD;
149 break;
150
151 case 65: // whitespace
152 break;
153
154 default: // other symbol
155 bits = (bits << 6) | symbol;
156 switch (state)
157 {
158 case ATBIT0:
159 state = ATBIT2;
160 break;
161 case ATBIT2:
162 out.putch(bits >> 4);
163 bits &= 0x0f;
164 state = ATBIT4;
165 break;
166 case ATBIT4:
167 out.putch(bits >> 2);
168 bits &= 0x03;
169 state = ATBIT6;
170 break;
171 case ATBIT6:
172 out.putch(bits);
173 bits = 0;
174 state = ATBIT0;
175 break;
176
177 case PAD:
178 seterror("invalid character #%s "
179 "after base64 padding", next);
180 return false;
181 }
182 break;
183 }
184 }
185 // if flushing and we did not get sufficient padding, then fail
186 if (flush && (state == ATBIT2 || state == ATBIT4 || state == ATBIT6))
187 return false; // insufficient padding to flush!
188 return true;
189}
WvBase64Decoder()
Creates a base 64 decoder.
Definition wvbase64.cc:117
virtual bool _encode(WvBuf &in, WvBuf &out, bool flush)
Template method implementation of encode().
Definition wvbase64.cc:131
virtual bool _reset()
Template method implementation of reset().
Definition wvbase64.cc:123
virtual bool _encode(WvBuf &in, WvBuf &out, bool flush)
Template method implementation of encode().
Definition wvbase64.cc:59
virtual bool _reset()
Template method implementation of reset().
Definition wvbase64.cc:51
WvBase64Encoder()
Creates a base 64 encoder.
Definition wvbase64.cc:45
virtual bool _finish(WvBuf &out)
Template method implementation of finish().
Definition wvbase64.cc:93
void seterror(WvStringParm message)
Sets an error condition, then setnotok().
Definition wvencoder.h:375
bool flush(WvBuf &inbuf, WvBuf &outbuf, bool finish=false)
Flushes the encoder and optionally finishes it.
Definition wvencoder.h:163
void setfinished()
Sets 'finished' to true explicitly.
Definition wvencoder.h:383
int lookup(const char *str, const char *const *table, bool case_sensitive=false)
Finds a string in an array and returns its index.
Definition strutils.cc:850