(file) Return to base64.c CVS log (file) (dir) Up to [OMI] / omi / base

  1 mike  1.1 #include "common.h"
  2           #include "base64.h"
  3           
  4           /* Maximum block size to send to Base64EncCallback (a multiple of 4) */
  5           
  6           #if defined(CONFIG_FAVORSIZE)
  7           # define BASE64ENC_BLOCK_SIZE 64
  8           #else
  9           # define BASE64ENC_BLOCK_SIZE 512
 10           #endif
 11           
 12           /* Maximum block size to send to Base64DecCallback (a multiple of 3) */
 13           #if defined(CONFIG_FAVORSIZE)
 14           # define BASE64DEC_BLOCK_SIZE 64
 15           #else
 16           # define BASE64DEC_BLOCK_SIZE 512
 17           #endif
 18           
 19           static const char encTable[64] =
 20           {
 21               'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
 22 mike  1.1     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
 23               'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
 24               'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
 25               'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
 26               'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
 27               'w', 'x', 'y', 'z', '0', '1', '2', '3', 
 28               '4', '5', '6', '7', '8', '9', '+', '/',
 29           };
 30           
 31           MI_INLINE char Enc6Bits(unsigned char x)
 32           {
 33               return encTable[x];
 34           }
 35           
 36           int Base64Enc(
 37               const void* data_,
 38               size_t size,
 39               Base64EncCallback callback,
 40               void* callbackData)
 41           {
 42               const unsigned char* data = (const unsigned char*)data_;
 43 mike  1.1     char buf[BASE64ENC_BLOCK_SIZE];
 44               size_t n = 0;
 45           
 46               /* Encode each group of 3 bytes into a group of 4 characters */
 47           
 48               while (size)
 49               {
 50                   unsigned int i1 = 0;
 51                   unsigned int i2 = 0;
 52                   unsigned int i3 = 0;
 53                   unsigned int i4 = 0;
 54                   size_t m = 0;
 55                   int done = 0;
 56           
 57                   /* Check whether there is room in the buffer for 4 more bytes (the
 58                    * maximum number of bytes that one pass of this loop can inject.
 59                    */
 60           
 61                   if (n + 4 > BASE64ENC_BLOCK_SIZE)
 62                   {
 63                       if ((*callback)(buf, n, callbackData) != 0)
 64 mike  1.1                 return -1;
 65           
 66                       n = 0;
 67                   }
 68           
 69                   /*
 70                    * B1       B2       B3
 71                    * +--------+--------+--------+
 72                    * |11111100|00002222|22333333|
 73                    * +--------+--------+--------+
 74                    */
 75           
 76                   /* Process byte 1 */
 77                   {
 78                       unsigned char b1 = *data++;
 79                       size--;
 80                       m++;
 81           
 82                       i1 |= (b1 & 0xFC) >> 2;
 83                       i2 |= (b1 & 0x03) << 4;
 84                       buf[n++] = Enc6Bits(i1);
 85 mike  1.1         }
 86           
 87                   /* Process byte 2 */
 88           
 89                   if (size)
 90                   {
 91                       unsigned char b2 = *data++;
 92                       size--;
 93                       m++;
 94           
 95                       i2 |= (b2 & 0xF0) >> 4;
 96                       i3 |= (b2 & 0x0F) << 2;
 97                       buf[n++] = Enc6Bits(i2);
 98                   }
 99                   else
100                   {
101                       buf[n++] = Enc6Bits(i2);
102                       done = 1;
103                   }
104           
105                   /* Process byte 3 */
106 mike  1.1 
107                   if (size)
108                   {
109                       unsigned char b3 = *data++;
110                       size--;
111                       m++;
112           
113                       i3 |= (b3 & 0xCF) >> 6;
114                       i4 |= b3 & 0x3F;
115           
116                       buf[n++] = Enc6Bits(i3);
117                       buf[n++] = Enc6Bits(i4);
118                   }
119                   else if (!done)
120                   {
121                       buf[n++] = Enc6Bits(i3);
122                   }
123           
124                   /* Add padding */
125           
126                   switch (m)
127 mike  1.1         {
128                       case 1:
129                           buf[n++] = '=';
130                           /* Fallthorugh intentional */
131                       case 2:
132                           buf[n++] = '=';
133                   }
134               }
135           
136               /* Send any remaining bytes */
137           
138               if (n)
139               {
140                   if ((*callback)(buf, n, callbackData) != 0)
141                       return -1;
142               }
143           
144               return 0;
145           }
146           
147           #if !defined(CONFIG_FAVORSIZE)
148 mike  1.1 
149           /* decoding table: 0-63 - valid value, 64-padding, 65-skip, 0xFF-invalid */
150           static const unsigned char decTable[128] = 
151           {
152               /* 0 - 31 */
153               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
154               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
155               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
156               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
157           
158               /* 32 - 39:  !"#$%&' */
159               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
160           
161               /* 40 - 42: ()*+,-./ */
162               0xFF, 0xFF, 0xFF, 62, 0xFF, 0xFF, 0xFF, 63,   
163           
164               /* 0 -9 */
165               52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 
166           
167               /* :;<=>? */
168               0xFF,0xFF,0xFF,64,0xFF,0xFF,
169 mike  1.1 
170               /* @ A-Z */
171               0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
172               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 
173           
174               /* []\\^_` */
175               0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
176           
177               /* a-z */
178               26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 
179               42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 
180           
181           
182               /* {|} ~ 127 */
183               0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
184           };
185           
186           #endif /* CONFIG_FAVORSIZE */
187           
188           static unsigned char DecChar(unsigned char c)
189           {
190 mike  1.1 #if defined(CONFIG_FAVORSIZE)
191           
192               if (c >= 'A' && c <= 'Z')
193                   return c - 'A';
194           
195               if (c >= 'a' && c <= 'z')
196                   return c - 'a' + 26;
197           
198               if (c >= '0' && c <= '9')
199                   return c - '0' + 52;
200           
201               if (c == '+')
202                   return 62;
203           
204               if (c == '/')
205                   return 63;
206           
207               if (c == '=')
208                   return 64;
209           
210               return 0xFF;
211 mike  1.1 
212           #else /* defined(CONFIG_FAVORSIZE) */
213           
214               if (c >= 128)
215                   return 0xFF;
216           
217               return decTable[c];
218           
219           #endif /* !defined(CONFIG_FAVORSIZE) */
220           }
221           
222           int Base64Dec(
223               const void* data_,
224               size_t size,
225               Base64DecCallback callback,
226               void* callbackData)
227           {
228               unsigned char* data = (unsigned char*)data_;
229               unsigned char* end = data + size;
230               unsigned char buf[BASE64DEC_BLOCK_SIZE];
231               size_t n = 0;
232 mike  1.1 
233               /* perform decoding - 4 input bytes are converted into 3 output, 
234                * using porvided pointers data/tgt
235                * since decoding is done inplace and result is smaller than input, 
236                * no checks for buffer size is required
237                */
238           
239               while (data != end)
240               {
241                   unsigned char c1;
242                   unsigned char c2;
243                   unsigned char c3;
244                   unsigned char c4;
245           
246                   /* Decode character 1 */
247           
248                   c1 = DecChar((*data++) & 0x7f);
249           
250                   if (c1 == 0xFF || data == end)
251                       return -1;
252           
253 mike  1.1         /* Decode character 2 */
254           
255                   c2 = DecChar((*data++) & 0x7f);
256           
257                   if (c2 == 0xFF || data == end)
258                       return -1;
259           
260                   /* Decode character 3 */
261           
262                   c3 = DecChar((*data++) & 0x7f);
263           
264                   if (c3 == 0xFF || data == end)
265                       return -1;
266           
267                   /* Decode character 4 */
268           
269                   c4 = DecChar((*data++) & 0x7f);
270           
271                   if (c4 == 0xFF)
272                       return -1;
273           
274 mike  1.1         /* Invoke callback if buffer would overflow below */
275           
276                   if (n + 3 > BASE64ENC_BLOCK_SIZE)
277                   {
278                       if ((*callback)(buf, n, callbackData) != 0)
279                           return -1;
280           
281                       n = 0;
282                   }
283           
284                   /* Convert 4 characters to 3 bytes */
285           
286                   buf[n++] = (c1 << 2) | (c2 >> 4);
287           
288                   if (c3 != 64)
289                       buf[n++] = ((c2 & 0xF) << 4) | (c3 >> 2);
290           
291                   if (c4 != 64)
292                       buf[n++] = ((c3 & 0x3) << 6) | c4;
293               }
294           
295 mike  1.1     /* Send any remaining bytes */
296           
297               if (n)
298               {
299                   if ((*callback)(buf, n, callbackData) != 0)
300                       return -1;
301               }
302           
303               return 0;
304           }

ViewCVS 0.9.2