Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

inet/base64.cpp

Go to the documentation of this file.
00001 /*  base64.cpp
00002     Encoding of binary data according to RFC2045 base64 encoding
00003 
00004     13.08.2001: tk, initial implementation, based on base64.c
00005                     from the PHP 4.06 source code.
00006 
00007     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
00008 
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of
00012     the License, or (at your option) any later version. Read the
00013     full License at http://www.gnu.org/copyleft for more details.
00014 */
00015 
00016 // include files ----------
00017 //
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <stdio.h>
00021 #include <assert.h>
00022 #include "inet/base64.h"
00023 
00024 static char base64_table[] =
00025   { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
00026     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
00027     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
00028     'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
00029     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
00030   };
00031 
00032 static char base64_pad = '=';
00033 
00051 unsigned char *base64encode(const unsigned char *str, 
00052                             unsigned   length, 
00053                             unsigned  *ret_length) 
00054 {
00055   const unsigned char *current = str;
00056   unsigned char *result;
00057   
00058   result = (unsigned char *)malloc((length+3 - length%3)*4/3 + 1);
00059   if (!result)
00060     return NULL;
00061 
00062   // keep going until we have less than 24 bits
00063   //
00064   unsigned i = 0;
00065 
00066   while (length > 2) { 
00067     result[i++] = base64_table[current[0] >> 2];
00068     result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
00069     result[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
00070     result[i++] = base64_table[current[2] & 0x3f];
00071 
00072     current += 3;
00073     length  -= 3;   // we just handle 3 octets of data
00074   }
00075 
00076   // now deal with the tail end of things
00077   //
00078   if (length != 0) {
00079     result[i++] = base64_table[current[0] >> 2];
00080     if (length > 1) {
00081       result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
00082       result[i++] = base64_table[(current[1] & 0x0f) << 2];
00083       result[i++] = base64_pad;
00084     }
00085     else {
00086       result[i++] = base64_table[(current[0] & 0x03) << 4];
00087       result[i++] = base64_pad;
00088       result[i++] = base64_pad;
00089     }
00090   }
00091   if(ret_length)
00092     *ret_length = i;
00093 
00094   result[i]='\0';
00095   return result;
00096 }
00097 
00098 
00116 unsigned char *base64decode( const unsigned char *str,
00117                              unsigned  length,
00118                              unsigned *ret_length)
00119 {
00120   static int  reverse_table[256];
00121   static bool table_built = false;
00122 
00123   if (!table_built) {
00124     for(int ch = 0; ch < 256; ch++) {
00125       char *chp = strchr(base64_table, ch);
00126       if (chp) {
00127         reverse_table[ch] = (int)(chp - base64_table);
00128       }
00129       else
00130         reverse_table[ch] = -1;
00131     }
00132     table_built = true;
00133   }
00134 
00135   unsigned char *result;
00136   result = (unsigned char *)malloc(length + 1);
00137   if (result == NULL)
00138     return NULL;
00139 
00140   // run through the whole string, converting as we go
00141   //
00142   const unsigned char *current = str;
00143   int   ch, i = 0, j = 0, k;
00144 
00145   // run through the whole string, converting as we go
00146   while ((ch = *current++) != '\0') {
00147     if (ch == base64_pad)
00148       break;
00149 
00150     // When Base64 gets POSTed, all pluses are interpreted as spaces.
00151     // This line changes them back.  It's not exactly the Base64 spec,
00152     // but it is completely compatible with it (the spec says that
00153     // spaces are invalid).  This will also save many people considerable
00154     // headache.  - Turadg Aleahmad <turadg@wise.berkeley.edu>
00155     //
00156     if (ch == ' ') 
00157       ch = '+'; 
00158 
00159     ch = reverse_table[ch];
00160     if (ch < 0) 
00161       continue;
00162 
00163     switch(i % 4) {
00164       case 0:
00165         result[j] = ch << 2;
00166         break;
00167       case 1:
00168         result[j++] |= ch >> 4;
00169         result[j] = (ch & 0x0f) << 4;
00170         break;
00171       case 2:
00172         result[j++] |= ch >>2;
00173         result[j] = (ch & 0x03) << 6;
00174         break;
00175       case 3:
00176         result[j++] |= ch;
00177         break;
00178     }
00179     i++;
00180   }
00181   
00182   // mop things up if we ended on a boundary
00183   //
00184   k = j;
00185   if (ch == base64_pad) {
00186     switch(i % 4) {
00187       case 0:
00188       case 1:
00189         free(result);
00190         return NULL;
00191       case 2:
00192         k++;
00193       case 3:
00194         result[k++] = 0;
00195     }
00196   }
00197   assert(j<length); 
00198   
00199   if (ret_length)
00200     *ret_length = j;
00201 
00202   result[k] = '\0';
00203   return result;
00204 }
00205 

Generated on Sun Aug 4 21:47:28 2002 for k/os mp3v2 by doxygen1.2.16