Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/crypto/base64.cc

Go to the documentation of this file.
00001 /*
00002  * base64.cc
00003  *
00004  * Implementation of base64 encoding/decoding algorithm. 
00005  *
00006  * Copyright (c) 2001--2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [
00007  *
00008  * This file may be distributed and/or modified under the terms of the 
00009  * GNU General Public License version 2 as published by the Free Software 
00010  * Foundation. (See COPYING.GPL for details.)
00011  *
00012  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014  *
00015  */
00016 
00017 #include "base64.h"
00018 
00019 
00020 /* Maps the values in range 0...63 to base64 chars. */
00021 static const unsigned char *_base64_encode=(unsigned char *)
00022     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00023     "abcdefghijklmnopqrstuvwxyz"
00024     "0123456789+/";
00025 
00026 /* Maps the first 128 ASCII chars to their base64 code (in range 0...63) 
00027  * Special meaning: 
00028  * 0xff -> illegal
00029  * 0xfe -> ignored (space, CR, LF, tab, backslash, \f, \v, \b, DEL)
00030  * 0xfd -> end of message (`=') */
00031 static const unsigned char *_base64_decode=(const unsigned char *)
00032     "\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff"
00033     "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
00034     "\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3e\xff\xff\xff\x3f"
00035     "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xff\xff\xff\xfd\xff\xff"
00036     "\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
00037     "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\xff\xfe\xff\xff\xff"
00038     "\xff\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28"
00039     "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\xff\xff\xff\xff\xfe";
00040 
00041 
00071 static ssize_t Base64Encode(
00072     const char *_in,size_t inlen,
00073     char *_out,size_t outlen,
00074     uint32 *state/*=NULL*/,int lwidth/*=0*/)
00075 {
00076     unsigned char *in=(unsigned char *)_in;
00077     unsigned char *out=(unsigned char *)_out;
00078     unsigned char *inend=in+inlen;
00079     unsigned char *outend=out+outlen;
00080     uint32 acc;
00081     int ai,ci;
00082     if(state)
00083     {
00084         acc=(*state)&0xffffU;
00085         ai=((*state)>>16)&0x3U;
00086         ci=((*state)>>18);
00087     }
00088     else
00089     {  acc=0U;  ai=0;  ci=0;  }
00090     
00091     for(;in<inend;in++)
00092     {
00093         acc<<=8;
00094         acc|=(uint32)(*in);
00095         ++ai;
00096         if(ai==3)
00097         {
00098             if(out+4>outend)
00099             {  return(-4);  }
00100             //for(int i=18; i>=0; i-=6)
00101             //{  *(out++)=_base64_encode[(acc>>i) & 0x3fU];  }
00102             *(out++)=_base64_encode[(acc>>18) & 0x3fU];
00103             *(out++)=_base64_encode[(acc>>12) & 0x3fU];
00104             *(out++)=_base64_encode[(acc>> 6) & 0x3fU];
00105             *(out++)=_base64_encode[ acc      & 0x3fU];
00106             ai=0;
00107             acc=0U;
00108             if(lwidth)  if((++ci)==lwidth)
00109             {
00110                 if(out>=outend)  return(-4);
00111                 *((char*)(out++))='\n';
00112                 ci=0;
00113             }
00114         }
00115     }
00116     
00117     if(state && inlen)
00118     {
00119         /* save carry in state (ai=0,1,2) */
00120         *state = 
00121             (((uint32)ci)<<18) | 
00122             (((uint32)ai)<<16) | 
00123             acc;
00124     }
00125     else
00126     {
00127         if(state)  *state=0;
00128         
00129         /* store rest of input in output */
00130         if(outend-out<(ai+2))   /* +2 for expand & termination char */
00131         {  return(-4);  }
00132         
00133         /* ai==3 never possible here. */
00134         switch(ai)
00135         {
00136             case 1:
00137                 *(out++)=_base64_encode[(acc>>2) & 0x3fU];
00138                 *(out++)=_base64_encode[(acc<<4) & 0x3fU];
00139                 break;
00140             case 2:
00141                 *(out++)=_base64_encode[(acc>>10) & 0x3fU];
00142                 *(out++)=_base64_encode[(acc>> 4) & 0x3fU];
00143                 *(out++)=_base64_encode[(acc<< 2) & 0x3fU];
00144                 break;
00145         }
00146         
00147         /* and append termination char */
00148         *((char*)(out++))='=';
00149     }
00150     
00151     return(out-(unsigned char*)_out);
00152 }
00153 
00154 
00178 static ssize_t Base64Decode(
00179     const char *_in,size_t inlen,
00180     char *_out,size_t outlen,
00181     uint32 *state /*=NULL*/)
00182 {
00183     unsigned char *ib=(unsigned char*)_in;
00184     unsigned char *ib_end=ib+inlen;
00185     unsigned char *ob=(unsigned char*)_out;
00186     unsigned char *ob_end=ob+outlen;
00187     
00188     uint32 dec=0xfdU;   /* simulate end char in case inlen=0 */
00189     uint32 acc = state ? ((*state)&0xffffffU) : 0U;
00190     int    ai  = state ? ((*state)>>24) : 0;
00191     
00192     for(; ib<ib_end; ib++)
00193     {
00194         if((*ib)>=128U)  return(-2);
00195         dec=_base64_decode[(int)(*ib)];
00196         if(dec<64)
00197         {
00198             acc=(acc<<6)|dec;
00199             ++ai;
00200             if(ai==4)  /* got 4 chars */
00201             {
00202                 if(ob+2>=ob_end)  return(-4);
00203                 *(ob++)=(unsigned char)((acc>>16) & 0xffU);
00204                 *(ob++)=(unsigned char)((acc>> 8) & 0xffU);
00205                 *(ob++)=(unsigned char)( acc      & 0xffU);
00206                 acc=0U;  ai=0;
00207             }
00208         }
00209         else switch(dec)
00210         {
00211             case 0xffU:  return(-2);
00212             /*case 0xfeU:  goto forcont;*/
00213             case 0xfdU:  goto breakfor;
00214         }
00215         /*forcont:;*/
00216     }
00217     breakfor:;
00218     /* ai==4 not possible here. ai<4 here. */
00219     
00220     if(state && dec!=0xfdU)  /* state and no end char */
00221     {
00222         /* Save carry in state. */
00223         *state = (((uint32)ai)<<24) | acc;
00224     }
00225     else
00226     {
00227         if(state)  *state=0U;
00228         /* Save the last bytes in the output buffer. */
00229         if(ob+ai-2>=ob_end)
00230         {  return(-4);  }
00231         switch(ai)
00232         {
00233             case 3:  /* got 3 chars */
00234                 *(ob++)=(unsigned char)((acc>>10) & 0xffU);
00235                 *(ob++)=(unsigned char)((acc>> 2) & 0xffU);
00236                 break;
00237             case 2:  /* got 2 chars */
00238                 *(ob++)=(unsigned char)((acc>> 4) & 0xffU);
00239                 break;
00240             case 1: return(-3);
00241         }
00242     }
00243     return((char*)ob-_out);
00244 }
00245 
00246 
00247 ssize_t Base64Encoder::encode(const char *in,size_t inlen,
00248     char *out,size_t outlen)
00249 {
00250     return(::Base64Encode(in,inlen,out,outlen,&state,lwidth));
00251 }
00252 
00253 ssize_t Base64Encoder::EncodeBuf(const char *in,size_t inlen,
00254     char *out,size_t outlen,int lwidth)
00255 {
00256     return(::Base64Encode(in,inlen,out,outlen,NULL,lwidth));
00257 }
00258 
00259 
00260 ssize_t Base64Decoder::decode(const char *in,size_t inlen,
00261     char *out,size_t outlen)
00262 {
00263     return(::Base64Decode(in,inlen,out,outlen,&state));
00264 }
00265 
00266 ssize_t Base64Decoder::DecodeBuf(const char *in,size_t inlen,
00267     char *out,size_t outlen)
00268 {
00269     return(::Base64Decode(in,inlen,out,outlen,NULL));
00270 }
00271 
00272 
00273 #if 0   /* compile little test proggy */
00274 
00275 #define TEST_ENCODE 1
00276 
00277 #include <stdio.h>  /* test program */
00278 #include <unistd.h>
00279 #include <string.h>
00280 #include <sys/types.h>
00281 #include <stdlib.h>
00282 #include <time.h>
00283 
00284 #define OBLEN 256000
00285 
00286 int main(int argc,char **arg)
00287 {
00288     char ob[OBLEN];
00289     ssize_t rv;
00290     
00291 #if TEST_ENCODE
00292     /*rv=Base64Encode(arg[1],strlen(arg[1]),ob,OBLEN,NULL,8);
00293     fprintf(stderr,"Return=%d\n",rv);
00294     if(rv>0)
00295     {  write(1,ob,rv);  printf("<<\n");  fflush(stdout);  }
00296     */
00297 #else
00298     /*rv=Base64Decode(arg[1],strlen(arg[1]),ob,OBLEN,NULL);
00299     fprintf(stderr,"Return=%d\n",rv);
00300     if(rv>0)
00301     {  write(1,ob,rv);  printf("<<\n");  fflush(stdout);  }
00302     */
00303 #endif
00304     
00305     srandom(time(NULL)*getpid());
00306     
00307     {
00308         uint32 state=0;
00309         char *ibuf=arg[1];
00310         char *ibufend=ibuf+strlen(ibuf);
00311         char *obuf=ob;
00312         for(;;)
00313         {
00314             int inlen=(random()%33)+1;  // ...or try 32
00315             if(ibuf+inlen>ibufend)
00316             {  inlen=ibufend-ibuf;  }
00317 #if TEST_ENCODE
00318             rv=Base64Encode(ibuf,inlen,obuf,ob+OBLEN-obuf,&state,8);
00319             if(rv<0)
00320             {  fprintf(stderr,"Enc(%d)=%d\n",inlen,rv);  }
00321 #else
00322             rv=Base64Decode(ibuf,inlen,obuf,ob+OBLEN-obuf,&state);
00323             if(rv<0)
00324             {  fprintf(stderr,"Dec(%d)=%d\n",inlen,rv);  }
00325 #endif
00326             if(rv<0)  break;
00327             ibuf+=inlen;
00328             obuf+=rv;
00329             if(!inlen)  break;
00330         }
00331         
00332         write(1,ob,obuf-ob);  printf("<<\n");  fflush(stdout);
00333     }
00334     
00335     return(0);
00336 }
00337 
00338 #endif

Generated on Sat Feb 19 22:33:45 2005 for Ray by doxygen 1.3.5