1 /* b64 encoding/decoding */
3 #include "prefix_file.h"
8 #include "sysync_b64.h"
9 #include "sync_include.h"
13 static const char table [64] = {
15 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
17 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
19 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
21 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
24 char *b64::encode (const uInt8 *instr, uInt32 len, uInt32 *outlenP, sInt16 maxLineLen, bool crLineEnd) {
27 // no line breaks -- this is just a straight b64 transform
32 uInt32 inlen,outlen,inover;
38 if ( (instr == NULL) || (len == 0) ) {
44 triples = ((inlen-inover)/3);
51 // make whole number of quads fit on one line
52 maxLineLen &= ~3; // clear bit 0&1
53 // also add room for CRs or CRLFs
55 (outlen/maxLineLen+1) << (crLineEnd ? 0 : 1);
58 outstr = (char *)malloc(outlen*sizeof(char));
59 memset(outstr,0,outlen);
63 for (i = 0; i < triples; i++) {
66 // o_off = i*4; %%% not ok as there might be line ends in between
68 inbuf[0] = instr[i_off];
69 inbuf[1] = instr[i_off+1];
70 inbuf[2] = instr[i_off+2];
72 outstr[o_off++] = table[(inbuf [0] & 0xFC) >> 2];
73 outstr[o_off++] = table[((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4)];
74 outstr[o_off++] = table[((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6)];
75 outstr[o_off++] = table[inbuf [2] & 0x3F];
77 // check line wrapping
80 maxLineLen && linechars>=maxLineLen && // line limit enabled
81 (i<triples-1 || inover) // and more to come (either full quad or inover padded quad)
95 // o_off = i*4; %%% not ok as there might be line ends in between
98 inbuf[0] = instr[i_off];
100 inbuf[1] = instr[i_off+1];
104 outstr[o_off] = table[(inbuf [0] & 0xFC) >> 2];
105 outstr[o_off+1] = table[((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4)];
106 outstr[o_off+2] = table[((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6)];
107 outstr[o_off+3] = table[inbuf [2] & 0x3F];
109 // generate b64 strings that are padded with = to
110 // make multiple's of 4 (this is how it must be)
113 outstr[o_off+3] = '=';
115 outstr[o_off+2] = '=';
120 // output length is either size of all complete quadruples including line feeds (o_off) or 4 more if
121 // input was not evenly divisible by 3
122 // (%%% luz added case for inover<>0, which produced 4 NULLs at end of string on inover==0)
123 if (outlenP) *outlenP = o_off+ (inover==0 ? 0 : 4);
129 uInt8 *b64::decode(const char *instr, uInt32 len, uInt32 *outlenP)
140 // get length if not passed as argument
144 if (len==0) len=strlen(instr);
147 // this should always be more than enough len:
148 // 3 times number of quads touched plus one for NUL terminator
149 outstr = (uInt8 *)malloc(((3*(len/4+1))+1) * sizeof(char));
150 if (!outstr) return NULL;
153 // process input string now
155 quadi=0; // index within quad
156 done=false; // not done yet
160 // init new quad if needed
162 // new quad starting, clear buffer
169 if ((c >= 'A') && (c <= 'Z'))
171 else if ((c >= 'a') && (c <= 'z'))
173 else if ((c >= '0') && (c <= '9'))
180 // reaching a "=" is like end of data
184 continue; // ignore all others
189 if (!done) inbuf[quadi++] = c;
190 // check if done or full quadruple
191 if (done || quadi==4) {
194 // two input bytes, first byte is there for sure
195 *q++ = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
197 // three input bytes, two output bytes are there
198 *q++ = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
200 // all 4 bytes there, produce three bytes
201 *q++ = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
210 // return length if requested
211 if (outlenP) *outlenP = q-outstr;
212 // make sure output ends with NUL in case it is interpreted as a c string
219 unsigned int i_off, o_off;
221 unsigned int inlen,outlen,inover;
224 uInt8 *outstr = NULL;
227 if (len==0) len=strlen(instr);
229 if ( (instr == NULL) || (len==0) ) {
235 quads = ((inlen-inover)/4);
237 // this should always be more than enough len
238 outlen = (3*(quads+1))+1;
240 outstr = (uInt8 *)malloc(outlen * sizeof(char));
241 memset(outstr,0,outlen);
242 for (i = 0; i < quads; i++) {
247 for (cnt = 0; cnt < 4; cnt++) {
248 ch = instr[i_off+cnt];
250 if ((ch >= 'A') && (ch <= 'Z'))
253 else if ((ch >= 'a') && (ch <= 'z'))
256 else if ((ch >= '0') && (ch <= '9'))
262 else if (ch == '=') //no op -- can't ignore this one*
272 outstr[o_off] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
273 outstr[o_off+1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
274 outstr[o_off+2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
277 // handle b64 strings that are not padded correctly
285 for (cnt = 0; cnt < inover; cnt++) {
286 ch = instr[i_off+cnt];
288 if ((ch >= 'A') && (ch <= 'Z'))
291 else if ((ch >= 'a') && (ch <= 'z'))
294 else if ((ch >= '0') && (ch <= '9'))
300 else if (ch == '=') //no op -- can't ignore this one*
309 outstr[o_off] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
310 outstr[o_off+1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
311 outstr[o_off+2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
315 if (outlenP) *outlenP = o_off+3;