1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 // David Freese, W1HKJ
4 //
5 // This file is part of fldigi
6 //
7 // fldigi is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // fldigi is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 // ----------------------------------------------------------------------------
20
21 //=====================================================================
22 //
23 // base64 encoding / decoding class
24 //
25 // To create a standalone base64 encode/coder:
26 // g++ -DTEST b64.cxx -o base64
27 //
28 // To use in a calling program:
29 //
30 // base64 b64; // default no CRLF's in output file
31 // base 64 b64(true); // insert CRLF's in output file
32 // pass c++ string into encoder / decoder
33 // return value is encoded / decoded string
34 // original string is left unchanged
35 //
36 // string instr, outstr;
37 // outstr = b64.encoder(instr);
38 // outstr = b64.decoder(instr);
39 //=====================================================================
40
41 #ifdef HAVE_CONFIG_H
42 # include <config.h>
43 #endif
44
45 #include "b64.h"
46
init()47 void base64::init()
48 {
49 iolen = 0;
50 iocp = 0;
51 ateof = false;
52 linelength = 0;
53
54 // create the etable for encoding
55 for (int i = 0; i < 9; i++) {
56 etable[i] = 'A' + i;
57 etable[i + 9] = 'J' + i;
58 etable[26 + i] = 'a' + i;
59 etable[26 + i + 9] = 'j' + i;
60 }
61 for (int i = 0; i < 8; i++) {
62 etable[i + 18] = 'S' + i;
63 etable[26 + i + 18] = 's' + i;
64 }
65 for (int i = 0; i < 10; i++)
66 etable[52 + i] = '0' + i;
67 etable[62] = '+';
68 etable[63] = '/';
69
70 // create the dtable for decoding
71 for (int i= 0; i < 255; i++)
72 dtable[i] = 0x80;
73 for (int i = 'A'; i <= 'I'; i++)
74 dtable[i] = 0 + (i - 'A');
75 for (int i = 'J'; i <= 'R'; i++)
76 dtable[i] = 9 + (i - 'J');
77 for (int i = 'S'; i <= 'Z'; i++)
78 dtable[i] = 18 + (i - 'S');
79 for (int i = 'a'; i <= 'i'; i++)
80 dtable[i] = 26 + (i - 'a');
81 for (int i = 'j'; i <= 'r'; i++)
82 dtable[i] = 35 + (i - 'j');
83 for (int i = 's'; i <= 'z'; i++)
84 dtable[i] = 44 + (i - 's');
85 for (int i = '0'; i <= '9'; i++)
86 dtable[i] = 52 + (i - '0');
87 dtable[(int)'+'] = 62;
88 dtable[(int)'/'] = 63;
89 dtable[(int)'='] = 0;
90 }
91
encode(std::string in)92 std::string base64::encode(std::string in)
93 {
94 int n;
95 byte igroup[3], ogroup[4];
96
97 output = "";
98 iocp = 0;
99 ateof = false;
100 if (crlf)
101 linelength = 0;
102 iolen = in.length();
103
104 while (!ateof) {
105 igroup[0] = igroup[1] = igroup[2] = 0;
106 for (n = 0; n < 3; n++) {
107 if (iocp == iolen) {
108 ateof = true;
109 break;
110 }
111 igroup[n] = (byte)in[iocp];
112 iocp++;
113 }
114 if (n > 0) {
115 ogroup[0] = etable[igroup[0] >> 2];
116 ogroup[1] = etable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
117 ogroup[2] = etable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
118 ogroup[3] = etable[igroup[2] & 0x3F];
119 if (n < 2) {
120 ogroup[2] = '=';
121 if (n < 1) {
122 ogroup[2] = '=';
123 }
124 }
125 for (int i = 0; i < 4; i++) {
126 if (crlf)
127 if (linelength >= LINELEN) {
128 // output += '\r';
129 output += '\n';
130 linelength = 0;
131 }
132 output += (byte)ogroup[i];
133 if (crlf)
134 linelength++;
135 }
136 }
137 }
138 if (crlf) {
139 // output += '\r';
140 output += '\n';
141 }
142
143 return output;
144 }
145
decode(std::string in)146 std::string base64::decode(std::string in)
147 {
148 int i;
149 output = "";
150 iocp = 0;
151 iolen = in.length();
152 byte c;
153
154 while (iocp < iolen) {
155 byte a[4], b[4], o[3];
156
157 for (i = 0; i < 4; i++) {
158 if (iocp == iolen) {
159 output = "b64 file length error.\n";
160 return output;
161 }
162 c = in[iocp++];
163 while (c <= ' ') {
164 if (iocp == iolen) {
165 return output;
166 }
167 c = in[iocp++];
168 }
169 if (dtable[c] & 0x80) {
170 output = "Illegal character in b64 file.\n";
171 return output;
172 }
173 a[i] = c;
174 b[i] = (byte)dtable[c];
175 }
176 o[0] = (b[0] << 2) | (b[1] >> 4);
177 o[1] = (b[1] << 4) | (b[2] >> 2);
178 o[2] = (b[2] << 6) | b[3];
179 output += o[0];
180 if (a[2] != '=') {
181 output += o[1];
182 if (a[3] != '=')
183 output += o[2];
184 }
185 }
186 return output;
187 }
188
189 #ifdef TEST
190 #include <iostream>
191 #include <fstream>
192
193
usage(void)194 void usage(void)
195 {
196 printf("b64 -- Encode/decode file as base64. Call:\n");
197 printf(" b64 e/d < infile > outfile\n");
198 }
199
main(int argc,char * argv[])200 int main(int argc,char*argv[])
201 {
202 char opt;
203 bool decoding = false;
204 char * cp;
205 byte c;
206
207 std::string inputstring;
208 std::string infilename;
209 std::string outputstring;
210 std::string outfilename;
211
212 base64 b64;
213
214 if (argc < 2) {
215 usage();
216 return(0);
217 }
218 opt = *(argv[1]);
219
220 if (opt == 'd' || opt == 'D') {
221 while (!std::cin.eof()) {
222 c = std::cin.get();
223 if (!std::cin.eof())
224 inputstring += c;
225 }
226 outputstring = b64.decode( inputstring );
227 size_t len = outputstring.length();
228 for (size_t n = 0; n < len; n++)
229 std::cout << (unsigned char)outputstring[n];
230 } else if (opt == 'e' || opt == 'E') {
231 while (!std::cin.eof()) {
232 c = std::cin.get();
233 if (!std::cin.eof())
234 inputstring += c;
235 }
236 outputstring = b64.encode( inputstring );
237 size_t len = outputstring.length();
238 for (size_t n = 0; n < len; n++)
239 std::cout << (unsigned char)outputstring[n];
240 } else
241 usage();
242
243 return 0;
244 }
245 #endif
246