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-08-17 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.
49 * string(or binary data) => base64 string + 1
50 * Output is actual string size + 1 (for \0)
52 int _sizeofBase64Encode(int len) {
54 if (len < 0) return 0;
55 if (len == 0) return 1;
57 return (len + 2 - ((len + 2) % 3)) * 4 / 3 + 1;
60 int getDecodedBase64Size(unsigned char *in, int inLen) {
68 outCount = inCount * 3;
71 if ( in[inCount+1] == '=' ) {
73 } else if ( in[inCount+2] == '=' ) {
75 } else if ( in[inCount+3] == '=' ) {
85 * calc original data size from base64 string size
87 * This is rough estimation.
88 * Output is actual string size (+1 or +2) + 1 (for \0)
91 int _sizeofBase64Decode(int len) {
93 if (len < 0) return 0;
94 if (len == 0) return 1;
96 return (len / 4 * 3) + 1;
101 * Encode BYTE[] to Base64 string
103 int _encodeBase64(char *out, unsigned char * in, int len) {
108 static unsigned char transTable[64] = {
110 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
112 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
114 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
116 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
117 /* 30h - 39h, 2Bh, 2Fh */
118 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
122 ERROR("out is NULL\n");
135 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
136 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
137 (in[ptr1+1]&0xF0) >> 4) ];
138 out[ptr2+2] = transTable[ ((in[ptr1+1]&0x0F) <<2 |
139 (in[ptr1+2]&0xC0) >> 6) ];
140 out[ptr2+3] = transTable[ (in[ptr1+2]&0x3F) ];
144 } else if ( len == 2 ) {
145 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
146 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
147 (in[ptr1+1]&0xF0) >> 4) ];
148 out[ptr2+2] = transTable[ (in[ptr1+1]&0x0F) <<2 ];
152 } else if ( len == 1 ) {
153 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
154 out[ptr2+1] = transTable[ (in[ptr1 ]&0x03) <<4 ];
164 /* add \0 at the end of buffer */
170 * Encode BYTE[] to Base64 string
172 * @param *in buffer of input data
173 * @param inlen length
174 * @raram *outlen size of output
175 * @return *out Base64 string, malloc new buffer
177 char *encodeBase64(unsigned char * in, int inlen, int *outlen) {
181 *outlen = _sizeofBase64Encode(inlen);
182 out = (char *) xmalloc_assert(*outlen);
188 memset(out, 0, *outlen);
190 len2 = _encodeBase64(out, in, inlen);
191 if (len2 > *outlen) {
192 ERROR("fatal error");
203 * trans (do not check the bad input)
205 unsigned char _b64trans(unsigned char in) {
206 if (in == '+') return 62;
207 if (in == '/') return 63;
208 if (in >= 'a') return (in-'a' + 26);
209 if (in >= 'A') return (in-'A');
210 if (in >= '0') return (in-'0' + 52);
215 * string length without space at the end
217 * 2011-11-30 Munetoh - fixed to skip the char in the middle of string
219 int _strippedlength(char * in, int len) {
230 //>>>>>>> 042e40b0979f3e44e75200271e4d1282ce08f72c
234 } else if (in[i] == ' ') {
247 * Decode Base64 string to BYTE[]
249 * caller must provide the buffer
251 * return size of BYTE[] array
253 int _decodeBase64(unsigned char *out, char * in, int len) {
264 ERROR("decodeBase64core - out is NULL\n");
269 ERROR("decodeBase64core - in is NULL\n");
272 /* in[0] => out[0]=\0 */
278 len2 = _strippedlength(in, len);
283 /* check remain buffer size >= 4 */
285 ERROR("bad base64 data size");
288 /* remove CR and Space and check bad string */
291 for (i = ptr1; j < 4 ; i++) {
292 if (in2[i] == '\n') {
295 } else if (in2[i] == ' ') {
299 if ((in2[i] == 0x2B) ||
302 ((0x30 <= in2[i]) && (in2[i] <= 0x39)) ||
303 ((0x41 <= in2[i]) && (in2[i] <= 0x5A)) ||
304 ((0x61 <= in2[i]) && (in2[i] <= 0x7A))) {
309 /* BAD BASE64 String */
310 ERROR("bad base64 data string, 0x%0x", in2[i]);
315 /* BASE64 -> Plain */
317 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
318 (_b64trans(inbuf[1]) >> 4);
319 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
320 (_b64trans(inbuf[2]) >> 2);
321 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
323 len2 -= 4; // skip chars has been removed in len2
326 } else if ( inbuf[1] == '=' ) {
327 out[ptr2 ] = _b64trans(inbuf[0]) << 2;
330 } else if ( inbuf[2] == '=' ) {
331 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
332 (_b64trans(inbuf[1]) >> 4);
335 } else if ( inbuf[3] == '=' ) {
336 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
337 (_b64trans(inbuf[1]) >> 4);
338 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
339 (_b64trans(inbuf[2]) >> 2);
343 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
344 (_b64trans(inbuf[1]) >> 4);
345 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
346 (_b64trans(inbuf[2]) >> 2);
347 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
354 /* Anyway, add \0 at the end of buffer */
365 * Decode Base64(with CRLF) string to BYTE[]
367 * @param *in buffer of base64 string
368 * @param inlen length
369 * @raram *outlen size of BYTE[] array from base64 string, malloced size is bigger then this
370 * @return *out malloc new buffer
372 unsigned char *decodeBase64(char * in, int inlen, int *outlen) {
377 len1 = _sizeofBase64Decode(inlen);
378 out = (unsigned char *) xmalloc_assert(len1);
384 memset(out, 0, len1);
386 len2 = _decodeBase64(out, in, inlen);
388 ERROR("fatal error");
394 /* return actial data size created from base64 */