(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 krisbash 1.3             buf[n++] = Enc6Bits((unsigned char) 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 krisbash 1.3             buf[n++] = Enc6Bits((unsigned char)i2);
 98 mike     1.1         }
 99                      else
100                      {
101 krisbash 1.3             buf[n++] = Enc6Bits((unsigned char)i2);
102 mike     1.1             done = 1;
103                      }
104              
105                      /* Process byte 3 */
106              
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 krisbash 1.3             buf[n++] = Enc6Bits((unsigned char)i3);
117                          buf[n++] = Enc6Bits((unsigned char)i4);
118 mike     1.1         }
119                      else if (!done)
120                      {
121 krisbash 1.3             buf[n++] = Enc6Bits((unsigned char)i3);
122 mike     1.1         }
123              
124                      /* Add padding */
125              
126                      switch (m)
127                      {
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 mike     1.1 
144                  return 0;
145              }
146              
147              #if !defined(CONFIG_FAVORSIZE)
148              
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 mike     1.1     /* 0 -9 */
165                  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 
166              
167                  /* :;<=>? */
168                  0xFF,0xFF,0xFF,64,0xFF,0xFF,
169              
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 mike     1.1 
186              #endif /* CONFIG_FAVORSIZE */
187              
188              static unsigned char DecChar(unsigned char c)
189              {
190              #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 mike     1.1 
207                  if (c == '=')
208                      return 64;
209              
210                  return 0xFF;
211              
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 mike     1.1 {
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              
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 mike     1.1         c1 = DecChar((*data++) & 0x7f);
249              
250                      if (c1 == 0xFF || data == end)
251                          return -1;
252              
253                      /* 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 mike     1.1         c4 = DecChar((*data++) & 0x7f);
270              
271                      if (c4 == 0xFF)
272                          return -1;
273              
274                      /* 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 mike     1.1 
291                      if (c4 != 64)
292                          buf[n++] = ((c3 & 0x3) << 6) | c4;
293                  }
294              
295                  /* Send any remaining bytes */
296              
297                  if (n)
298                  {
299                      if ((*callback)(buf, n, callbackData) != 0)
300                          return -1;
301                  }
302              
303 krisbash 1.3     // return the size of the decoded buffer
304                  return n;
305 mike     1.1 }

ViewCVS 0.9.2