e1635ad403d8dfe4d426ab6fe28999d6b552587e
[platform/upstream/syncevolution.git] / src / synthesis / src / sysync_SDK / Sources / sysync_b64.cpp
1 /* b64 encoding/decoding */
2
3 #include "prefix_file.h"
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "sysync_b64.h"
9 #include "sync_include.h"
10
11 using namespace b64;
12
13 static const char table [64] = {
14
15   'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
16
17   'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
18
19   'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
20
21   'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
22 };
23
24 char *b64::encode (const uInt8 *instr, uInt32 len, uInt32 *outlenP, sInt16 maxLineLen, bool crLineEnd) {
25
26
27   // no line breaks -- this is just a straight b64 transform
28
29   uInt32 i_off = 0;
30   uInt32 o_off = 0;
31   uInt8 inbuf [3];
32   uInt32 inlen,outlen,inover;
33   uInt32 triples;
34   uInt32 i;
35   sInt16 linechars;
36   char *outstr = NULL;
37
38   if ( (instr == NULL) || (len == 0) ) {
39     return(NULL);
40   }
41
42   inlen = len;
43   inover = inlen%3;
44   triples = ((inlen-inover)/3);
45
46   outlen = 4*triples+1;
47   if (inover) {
48     outlen+=4;
49   }
50   if (maxLineLen) {
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
54     outlen +=
55       (outlen/maxLineLen+1) << (crLineEnd ? 0 : 1);
56   }
57
58   outstr = (char *)malloc(outlen*sizeof(char));
59   memset(outstr,0,outlen);
60
61   linechars=0;
62   o_off=0;
63   for (i = 0; i < triples; i++) {
64
65     i_off = i*3;
66     // o_off = i*4; %%% not ok as there might be line ends in between
67
68     inbuf[0] = instr[i_off];
69     inbuf[1] = instr[i_off+1];
70     inbuf[2] = instr[i_off+2];
71
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];
76
77     // check line wrapping
78     linechars+=4;
79     if (
80       maxLineLen && linechars>=maxLineLen && // line limit enabled
81       (i<triples-1 || inover) // and more to come (either full quad or inover padded quad)
82     ) {
83       if (crLineEnd)
84         outstr[o_off++]='\r';
85       else {
86         outstr[o_off++]=0x0D;
87         outstr[o_off++]=0x0A;
88       }
89       linechars=0;
90     }
91   }
92
93   if (inover) {
94     i_off = i*3;
95     // o_off = i*4; %%% not ok as there might be line ends in between
96
97     memset(inbuf,0,3);
98     inbuf[0] = instr[i_off];
99     if (inover > 1 ) {
100       inbuf[1] = instr[i_off+1];
101     }
102     inbuf[2] = 0;
103
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];
108
109     //   generate b64 strings that are padded with = to
110     //   make multiple's of 4 (this is how it must be)
111
112     if (inover < 3 ) {
113       outstr[o_off+3] = '=';
114       if (inover < 2 ) {
115         outstr[o_off+2] = '=';
116       }
117     }
118   }
119
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);
124
125   return(outstr);
126 }
127
128
129 uInt8 *b64::decode(const char *instr, uInt32 len, uInt32 *outlenP)
130 {
131
132   uInt8 inbuf [4];
133   uInt32 n;
134   sInt16 quadi;
135   bool done;
136   const char *p;
137   char c=0;
138   uInt8 *outstr,*q;
139
140   // get length if not passed as argument
141   if (!instr)
142     len=0;
143   else
144     if (len==0) len=strlen(instr);
145   p = instr;
146
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;
151   q=outstr;
152
153   // process input string now
154   n=0;
155   quadi=0; // index within quad
156   done=false; // not done yet
157
158   while (!done) {
159     if (n<len) {
160       // init new quad if needed
161       if (quadi==0) {
162         // new quad starting, clear buffer
163         memset(inbuf,0,4);
164       }
165       // get next char
166       c=*p++;
167       n++;
168       // process char
169       if ((c >= 'A') && (c <= 'Z'))
170         c = c - 'A';
171       else if ((c >= 'a') && (c <= 'z'))
172         c = c - 'a' + 26;
173       else if ((c >= '0') && (c <= '9'))
174         c = c - '0' + 52;
175       else if (c == '+')
176         c = 62;
177       else if (c == '/')
178         c = 63;
179       else if (c == '=') {
180         // reaching a "=" is like end of data
181         done=true;
182       }
183       else
184         continue; // ignore all others
185     }
186     else
187       done=true;
188     // save in char
189     if (!done) inbuf[quadi++] = c;
190     // check if done or full quadruple
191     if (done || quadi==4) {
192       // produce data now
193       if (quadi>=2) {
194         // two input bytes, first byte is there for sure
195         *q++ = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
196         if (quadi>=3) {
197           // three input bytes, two output bytes are there
198           *q++ = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
199           if (quadi==4) {
200             // all 4 bytes there, produce three bytes
201             *q++ = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
202           }
203         }
204       }
205       // start new quad
206       quadi=0;
207     }
208   } // while
209
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
213   *q=0;
214   // return string
215   return(outstr);
216
217
218   /*
219   unsigned int i_off, o_off;
220   uInt8 inbuf [4];
221   unsigned int inlen,outlen,inover;
222   unsigned int quads;
223   int i,cnt;
224   uInt8 *outstr = NULL;
225   char ch;
226
227   if (len==0) len=strlen(instr);
228
229   if ( (instr == NULL) || (len==0) ) {
230     return(NULL);
231   }
232
233   inlen = len;
234   inover = inlen%4;
235   quads = ((inlen-inover)/4);
236
237   // this should always be more than enough len
238   outlen = (3*(quads+1))+1;
239
240   outstr = (uInt8 *)malloc(outlen * sizeof(char));
241   memset(outstr,0,outlen);
242   for (i = 0; i < quads; i++) {
243
244     i_off = i*4;
245     o_off = i*3;
246
247     for (cnt = 0; cnt < 4; cnt++) {
248       ch = instr[i_off+cnt];
249
250       if ((ch >= 'A') && (ch <= 'Z'))
251         ch = ch - 'A';
252
253       else if ((ch >= 'a') && (ch <= 'z'))
254         ch = ch - 'a' + 26;
255
256       else if ((ch >= '0') && (ch <= '9'))
257         ch = ch - '0' + 52;
258
259       else if (ch == '+')
260         ch = 62;
261
262       else if (ch == '=') //no op -- can't ignore this one*
263         ch = 0;
264
265       else if (ch == '/')
266         ch = 63;
267
268       inbuf[cnt] = ch;
269
270     }
271
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);
275   }
276
277   // handle b64 strings that are not padded correctly
278
279   if (inover) {
280     i_off = i*4;
281     o_off = i*3;
282
283     memset(inbuf,0,4);
284
285     for (cnt = 0; cnt < inover; cnt++) {
286       ch = instr[i_off+cnt];
287
288       if ((ch >= 'A') && (ch <= 'Z'))
289               ch = ch - 'A';
290
291       else if ((ch >= 'a') && (ch <= 'z'))
292         ch = ch - 'a' + 26;
293
294       else if ((ch >= '0') && (ch <= '9'))
295         ch = ch - '0' + 52;
296
297       else if (ch == '+')
298         ch = 62;
299
300       else if (ch == '=') //no op -- can't ignore this one*
301         ch = 0;
302
303       else if (ch == '/')
304         ch = 63;
305
306       inbuf[cnt] = ch;
307     }
308
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);
312
313   }
314
315   if (outlenP) *outlenP = o_off+3;
316
317   return(outstr);
318   */
319 }
320
321 // eof