2 * This file is part of the OpenPTS project.
4 * The Initial Developer of the Original Code is International
5 * Business Machines Corporation. Portions created by IBM
6 * Corporation are Copyright (C) 2010 International Business
7 * Machines Corporation. All Rights Reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the Common Public License as published by
11 * IBM Corporation; either version 1 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * Common Public License for more details.
19 * You should have received a copy of the Common Public License
20 * along with this program; if not, a copy can be viewed at
21 * http://www.opensource.org/licenses/cpl1.0.php.
26 * \brief Base64 Encode/Decode
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-12-31 SM
31 * http://en.wikipedia.org/wiki/Base64
33 * 2011-08-17 SM - encodebase64 & decodeBase64 - alloc output buffer
34 * 2011-08-21 SM - remove _removeCR() and malloc
35 * 2011-08-21 SM - check bad string in BASE64 msg.
48 * string(or binary data) => base64 string + 1
49 * Output is actual string size + 1 (for \0)
51 int _sizeofBase64Encode(int len) {
53 if (len < 0) return 0;
54 if (len == 0) return 1;
56 return (len + 2 - ((len + 2) % 3)) * 4 / 3 + 1;
59 int getDecodedBase64Size(unsigned char *in, int inLen) {
73 outCount = inCount * 3;
76 if ( in[inCount+1] == '=' ) {
78 } else if ( in[inCount+2] == '=' ) {
80 } else if ( in[inCount+3] == '=' ) {
90 * calc original data size from base64 string size
92 * This is rough estimation.
93 * Output is actual string size (+1 or +2) + 1 (for \0)
96 int _sizeofBase64Decode(int len) {
98 if (len < 0) return 0;
99 if (len == 0) return 1;
101 return (len / 4 * 3) + 1;
106 * Encode BYTE[] to Base64 string
111 int _encodeBase64(char *out, unsigned char * in, int len) {
116 static unsigned char transTable[64] = {
118 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
120 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
122 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
124 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
125 /* 30h - 39h, 2Bh, 2Fh */
126 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
131 ERROR("null input\n");
147 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
148 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
149 (in[ptr1+1]&0xF0) >> 4) ];
150 out[ptr2+2] = transTable[ ((in[ptr1+1]&0x0F) <<2 |
151 (in[ptr1+2]&0xC0) >> 6) ];
152 out[ptr2+3] = transTable[ (in[ptr1+2]&0x3F) ];
156 } else if ( len == 2 ) {
157 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
158 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
159 (in[ptr1+1]&0xF0) >> 4) ];
160 out[ptr2+2] = transTable[ (in[ptr1+1]&0x0F) <<2 ];
164 } else if ( len == 1 ) {
165 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
166 out[ptr2+1] = transTable[ (in[ptr1 ]&0x03) <<4 ];
176 /* add \0 at the end of buffer */
182 * Encode BYTE[] to Base64 string
184 * @param *in buffer of input data
185 * @param inlen length
186 * @raram *outlen size of output
187 * @return *out Base64 string, malloc new buffer
189 char *encodeBase64(unsigned char * in, int inlen, int *outlen) {
195 ERROR("null input\n");
199 *outlen = _sizeofBase64Encode(inlen);
200 out = (char *) xmalloc_assert(*outlen);
206 memset(out, 0, *outlen);
208 len2 = _encodeBase64(out, in, inlen);
209 if (len2 > *outlen) {
210 ERROR("fatal error");
221 * trans (do not check the bad input)
223 unsigned char _b64trans(unsigned char in) {
224 if (in == '+') return 62;
225 if (in == '/') return 63;
226 if (in >= 'a') return (in-'a' + 26);
227 if (in >= 'A') return (in-'A');
228 if (in >= '0') return (in-'0' + 52);
233 * string length without space at the end
235 * 2011-11-30 Munetoh - fixed to skip the char in the middle of string
237 int _strippedlength(char * in, int len) {
243 ERROR("null input\n");
254 } else if (in[i] == ' ') {
267 * Decode Base64 string to BYTE[]
269 * caller must provide the buffer
271 * return size of BYTE[] array
273 int _decodeBase64(unsigned char *out, char * in, int len) {
284 ERROR("decodeBase64core - out is NULL\n");
289 ERROR("decodeBase64core - in is NULL\n");
292 /* in[0] => out[0]=\0 */
298 len2 = _strippedlength(in, len);
303 /* check remain buffer size >= 4 */
305 ERROR("bad base64 data size");
308 /* remove CR and Space and check bad string */
311 for (i = ptr1; j < 4 ; i++) {
312 if (in2[i] == '\n') {
315 } else if (in2[i] == ' ') {
319 if ((in2[i] == 0x2B) ||
322 ((0x30 <= in2[i]) && (in2[i] <= 0x39)) ||
323 ((0x41 <= in2[i]) && (in2[i] <= 0x5A)) ||
324 ((0x61 <= in2[i]) && (in2[i] <= 0x7A))) {
329 /* BAD BASE64 String */
330 ERROR("bad base64 data string, 0x%0x", in2[i]);
335 /* BASE64 -> Plain */
337 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
338 (_b64trans(inbuf[1]) >> 4);
339 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
340 (_b64trans(inbuf[2]) >> 2);
341 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
343 len2 -= 4; // skip chars has been removed in len2
346 } else if ( inbuf[1] == '=' ) {
347 out[ptr2 ] = _b64trans(inbuf[0]) << 2;
350 } else if ( inbuf[2] == '=' ) {
351 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
352 (_b64trans(inbuf[1]) >> 4);
355 } else if ( inbuf[3] == '=' ) {
356 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
357 (_b64trans(inbuf[1]) >> 4);
358 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
359 (_b64trans(inbuf[2]) >> 2);
363 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
364 (_b64trans(inbuf[1]) >> 4);
365 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
366 (_b64trans(inbuf[2]) >> 2);
367 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
374 /* Anyway, add \0 at the end of buffer */
385 * Decode Base64(with CRLF) string to BYTE[]
387 * @param *in buffer of base64 string
388 * @param inlen length
389 * @raram *outlen size of BYTE[] array from base64 string, malloced size is bigger then this
390 * @return *out malloc new buffer
392 unsigned char *decodeBase64(char * in, int inlen, int *outlen) {
399 ERROR("null input\n");
403 len1 = _sizeofBase64Decode(inlen);
404 out = (unsigned char *) xmalloc_assert(len1);
410 memset(out, 0, len1);
412 len2 = _decodeBase64(out, in, inlen);
414 ERROR("fatal error");
420 /* return actial data size created from base64 */