00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "base64.h"
00018
00019
00020
00021 static const unsigned char *_base64_encode=(unsigned char *)
00022 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00023 "abcdefghijklmnopqrstuvwxyz"
00024 "0123456789+/";
00025
00026
00027
00028
00029
00030
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,int lwidth)
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
00101
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
00120 *state =
00121 (((uint32)ci)<<18) |
00122 (((uint32)ai)<<16) |
00123 acc;
00124 }
00125 else
00126 {
00127 if(state) *state=0;
00128
00129
00130 if(outend-out<(ai+2))
00131 { return(-4); }
00132
00133
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
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 )
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;
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)
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
00213 case 0xfdU: goto breakfor;
00214 }
00215
00216 }
00217 breakfor:;
00218
00219
00220 if(state && dec!=0xfdU)
00221 {
00222
00223 *state = (((uint32)ai)<<24) | acc;
00224 }
00225 else
00226 {
00227 if(state) *state=0U;
00228
00229 if(ob+ai-2>=ob_end)
00230 { return(-4); }
00231 switch(ai)
00232 {
00233 case 3:
00234 *(ob++)=(unsigned char)((acc>>10) & 0xffU);
00235 *(ob++)=(unsigned char)((acc>> 2) & 0xffU);
00236 break;
00237 case 2:
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
00274
00275 #define TEST_ENCODE 1
00276
00277 #include <stdio.h>
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
00293
00294
00295
00296
00297 #else
00298
00299
00300
00301
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;
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