Base64 Supermarket - 暈

来源:互联网 发布:matlab画数组 编辑:程序博客网 时间:2024/06/11 13:06

When there are too many standards, there is no standard. ---Not by G. C. Patton

五花八門 亂奇八糟 你/妳如不頭暈 1) 不干你/妳的事 2)  你/妳必是天才

This is worse than in a supermarket, in supermarket, they at least shelf everything right. If you don't care 1) because you only love yourself, 2) you are too smart and you are beyond them.

Just look at those licenses, if you are not amazed how everyone is trying to protect oneself then you must be from Mars.

光是看所有的版權 似乎作者都在保護自己的作品 This must be started before Taipan.

From SSLeay =========================================

#include <stdio.h>
#include <errno.h>
#include "cryptlib.h"
#include "buffer.h"
#include "evp.h"

#ifndef NOPROTO
static int b64_write(BIO *h,char *buf,int num);
static int b64_read(BIO *h,char *buf,int size);
/*static int b64_puts(BIO *h,char *str); */
/*static int b64_gets(BIO *h,char *str,int size); */
static long b64_ctrl(BIO *h,int cmd,long arg1,char *arg2);
static int b64_new(BIO *h);
static int b64_free(BIO *data);
#else
static int b64_write();
static int b64_read();
/*static int b64_puts(); */
/*static int b64_gets(); */
static long b64_ctrl();
static int b64_new();
static int b64_free();
#endif

#define B64_BLOCK_SIZE 1024
#define B64_BLOCK_SIZE2 768
#define B64_NONE 0
#define B64_ENCODE 1
#define B64_DECODE 2

typedef struct b64_struct
 {
 /*BIO *bio; moved to the BIO structure */
 int buf_len;
 int buf_off;
 int tmp_len;  /* used to find the start when decoding */
 int tmp_nl;  /* If true, scan until '/n' */
 int encode;
 int start;  /* have we started decoding yet? */
 int cont;  /* <= 0 when finished */
 EVP_ENCODE_CTX base64;
 char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE)+10];
 char tmp[B64_BLOCK_SIZE];
 } BIO_B64_CTX;

static BIO_METHOD methods_b64=
 {
 BIO_TYPE_BASE64,"base64 encoding",
 b64_write,
 b64_read,
 NULL, /* b64_puts, */
 NULL, /* b64_gets, */
 b64_ctrl,
 b64_new,
 b64_free,
 };

BIO_METHOD *BIO_f_base64()
 {
 return(&methods_b64);
 }

static int b64_new(bi)
BIO *bi;
 {
 BIO_B64_CTX *ctx;

 ctx=(BIO_B64_CTX *)Malloc(sizeof(BIO_B64_CTX));
 if (ctx == NULL) return(0);

 ctx->buf_len=0;
 ctx->tmp_len=0;
 ctx->tmp_nl=0;
 ctx->buf_off=0;
 ctx->cont=1;
 ctx->start=1;
 ctx->encode=0;

 bi->init=1;
 bi->ptr=(char *)ctx;
 bi->flags=0;
 return(1);
 }

static int b64_free(a)
BIO *a;
 {
 if (a == NULL) return(0);
 Free(a->ptr);
 a->ptr=NULL;
 a->init=0;
 a->flags=0;
 return(1);
 }
 
static int b64_read(b,out,outl)
BIO *b;
char *out;
int outl;
 {
 int ret=0,i,ii,j,k,x,n,num,ret_code=0;
 BIO_B64_CTX *ctx;
 unsigned char *p,*q;

 if (out == NULL) return(0);
 ctx=(BIO_B64_CTX *)b->ptr;

 if ((ctx == NULL) || (b->next_bio == NULL)) return(0);

 if (ctx->encode != B64_DECODE)
  {
  ctx->encode=B64_DECODE;
  ctx->buf_len=0;
  ctx->buf_off=0;
  ctx->tmp_len=0;
  EVP_DecodeInit(&(ctx->base64));
  }

 /* First check if there are bytes decoded/encoded */
 if (ctx->buf_len > 0)
  {
  i=ctx->buf_len-ctx->buf_off;
  if (i > outl) i=outl;
  memcpy(out,&(ctx->buf[ctx->buf_off]),i);
  ret=i;
  out+=i;
  outl-=i;
  ctx->buf_off+=i;
  if (ctx->buf_len == ctx->buf_off)
   {
   ctx->buf_len=0;
   ctx->buf_off=0;
   }
  }

 /* At this point, we have room of outl bytes and an empty
  * buffer, so we should read in some more. */

 ret_code=0;
 while (outl > 0)
  {
  if (ctx->cont <= 0) break;

  i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
   B64_BLOCK_SIZE-ctx->tmp_len);

  if (i <= 0)
   {
   ret_code=i;

   /* Should be continue next time we are called? */
   if (!BIO_should_retry(b->next_bio))
    ctx->cont=i;
   /* else we should continue when called again */
   break;
   }
  i+=ctx->tmp_len;

  /* We need to scan, a line at a time until we
   * have a valid line if we are starting. */
  if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL))
   {
   /* ctx->start=1; */
   ctx->tmp_len=0;
   }
  else if (ctx->start)
   {
   q=p=(unsigned char *)ctx->tmp;
   for (j=0; j<i; j++)
    {
    if (*(q++) != '/n') continue;

    /* due to a previous very long line,
     * we need to keep on scanning for a '/n'
     * before we even start looking for
     * base64 encoded stuff. */
    if (ctx->tmp_nl)
     {
     p=q;
     ctx->tmp_nl=0;
     continue;
     }

    k=EVP_DecodeUpdate(&(ctx->base64),
     (unsigned char *)ctx->buf,
     &num,p,q-p);
    if ((k <= 0) && (num == 0) && (ctx->start))
     EVP_DecodeInit(&ctx->base64);
    else
     {
     if (p != (unsigned char *)
      &(ctx->tmp[0]))
      {
      i-=(p- (unsigned char *)
       &(ctx->tmp[0]));
      for (x=0; x < i; x++)
       ctx->tmp[x]=p[x];
      EVP_DecodeInit(&ctx->base64);
      }
     ctx->start=0;
     break;
     }
    p=q;
    }

   /* we fell off the end without starting */
   if (j == i)
    {
    /* Is this is one long chunk?, if so, keep on
     * reading until a new line. */
    if (p == (unsigned char *)&(ctx->tmp[0]))
     {
     ctx->tmp_nl=1;
     ctx->tmp_len=0;
     }
    else if (p != q) /* finished on a '/n' */
     {
     n=q-p;
     for (ii=0; ii<n; ii++)
      ctx->tmp[ii]=p[ii];
     ctx->tmp_len=n;
     }
    /* else finished on a '/n' */
    continue;
    }
   else
    ctx->tmp_len=0;
   }

  if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
   {
   int z,jj;

   jj=(i>>2)<<2;
   z=EVP_DecodeBlock((unsigned char *)ctx->buf,
    (unsigned char *)ctx->tmp,jj);
   if (jj > 2)
    {
    if (ctx->tmp[jj-1] == '=')
     {
     z--;
     if (ctx->tmp[jj-2] == '=')
      z--;
     }
    }
   /* z is now number of output bytes and jj is the
    * number consumed */
   if (jj != i)
    {
    memcpy((unsigned char *)ctx->tmp,
     (unsigned char *)&(ctx->tmp[jj]),i-jj);
    ctx->tmp_len=i-jj;
    }
   ctx->buf_len=0;
   if (z > 0)
    {
    ctx->buf_len=z;
    i=1;
    }
   else
    i=z;
   }
  else
   {
   i=EVP_DecodeUpdate(&(ctx->base64),
    (unsigned char *)ctx->buf,&ctx->buf_len,
    (unsigned char *)ctx->tmp,i);
   }
  ctx->cont=i;
  ctx->buf_off=0;
  if (i < 0)
   {
   ret_code=0;
   ctx->buf_len=0;
   break;
   }

  if (ctx->buf_len <= outl)
   i=ctx->buf_len;
  else
   i=outl;

  memcpy(out,ctx->buf,i);
  ret+=i;
  ctx->buf_off=i;
  if (ctx->buf_off == ctx->buf_len)
   {
   ctx->buf_len=0;
   ctx->buf_off=0;
   }
  outl-=i;
  out+=i;
  }
 BIO_clear_retry_flags(b);
 BIO_copy_next_retry(b);
 return((ret == 0)?ret_code:ret);
 }

static int b64_write(b,in,inl)
BIO *b;
char *in;
int inl;
 {
 int ret=inl,n,i;
 BIO_B64_CTX *ctx;

 ctx=(BIO_B64_CTX *)b->ptr;
 BIO_clear_retry_flags(b);

 if (ctx->encode != B64_ENCODE)
  {
  ctx->encode=B64_ENCODE;
  ctx->buf_len=0;
  ctx->buf_off=0;
  ctx->tmp_len=0;
  EVP_EncodeInit(&(ctx->base64));
  }

 n=ctx->buf_len-ctx->buf_off;
 while (n > 0)
  {
  i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
  if (i <= 0)
   {
   BIO_copy_next_retry(b);
   return(i);
   }
  ctx->buf_off+=i;
  n-=i;
  }
 /* at this point all pending data has been written */

 if ((in == NULL) || (inl <= 0)) return(0);

 ctx->buf_off=0;
 while (inl > 0)
  {
  n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl;

  if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
   {
   if (ctx->tmp_len > 0)
    {
    n=3-ctx->tmp_len;
    memcpy(&(ctx->tmp[ctx->tmp_len]),in,n);
    ctx->tmp_len+=n;
    n=ctx->tmp_len;
    if (n < 3)
     break;
    ctx->buf_len=EVP_EncodeBlock(
     (unsigned char *)ctx->buf,
     (unsigned char *)ctx->tmp,n);
    }
   else
    {
    if (n < 3)
     {
     memcpy(&(ctx->tmp[0]),in,n);
     ctx->tmp_len=n;
     break;
     }
    n-=n%3;
    ctx->buf_len=EVP_EncodeBlock(
     (unsigned char *)ctx->buf,
     (unsigned char *)in,n);
    }
   }
  else
   {
   EVP_EncodeUpdate(&(ctx->base64),
    (unsigned char *)ctx->buf,&ctx->buf_len,
    (unsigned char *)in,n);
   }
  inl-=n;
  in+=n;

  ctx->buf_off=0;
  n=ctx->buf_len;
  while (n > 0)
   {
   i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
   if (i <= 0)
    {
    BIO_copy_next_retry(b);
    return((ret == 0)?i:ret);
    }
   n-=i;
   ctx->buf_off+=i;
   }
  ctx->buf_len=0;
  ctx->buf_off=0;
  }
 return(ret);
 }

static long b64_ctrl(b,cmd,num,ptr)
BIO *b;
int cmd;
long num;
char *ptr;
 {
 BIO_B64_CTX *ctx;
 long ret=1;
 int i;

 ctx=(BIO_B64_CTX *)b->ptr;

 switch (cmd)
  {
 case BIO_CTRL_RESET:
  ctx->cont=1;
  ctx->start=1;
  ctx->encode=B64_NONE;
  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;
 case BIO_CTRL_EOF: /* More to read */
  if (ctx->cont <= 0)
   ret=1;
  else
   ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;
 case BIO_CTRL_WPENDING: /* More to write in buffer */
  ret=ctx->buf_len-ctx->buf_off;
  if ((ret == 0) && (ctx->base64.num != 0))
   ret=1;
  else if (ret <= 0)
   ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;
 case BIO_CTRL_PENDING: /* More to read in buffer */
  ret=ctx->buf_len-ctx->buf_off;
  if (ret <= 0)
   ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;
 case BIO_CTRL_FLUSH:
  /* do a final write */
again:
  while (ctx->buf_len != ctx->buf_off)
   {
   i=b64_write(b,NULL,0);
   if (i < 0)
    {
    ret=i;
    break;
    }
   }
  if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
   {
   if (ctx->tmp_len != 0)
    {
    ctx->buf_len=EVP_EncodeBlock(
     (unsigned char *)ctx->buf,
     (unsigned char *)ctx->tmp,
     ctx->tmp_len);
    ctx->buf_off=0;
    ctx->tmp_len=0;
    goto again;
    }
   }
  else if (ctx->base64.num != 0)
   {
   ctx->buf_off=0;
   EVP_EncodeFinal(&(ctx->base64),
    (unsigned char *)ctx->buf,
    &(ctx->buf_len));
   /* push out the bytes */
   goto again;
   }
  /* Finally flush the underlying BIO */
  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;

 case BIO_C_DO_STATE_MACHINE:
  BIO_clear_retry_flags(b);
  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  BIO_copy_next_retry(b);
  break;

 case BIO_CTRL_DUP:
  break;
 case BIO_CTRL_INFO:
 case BIO_CTRL_GET:
 case BIO_CTRL_SET:
 default:
  ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  break;
  }
 return(ret);
 }

From Cryptolib ==================================================

int base64checkHeader( const char *data, const int dataLength,
        int *startPos )
 {
 STREAM stream;
 BOOLEAN seenTransferEncoding = FALSE, isBinaryEncoding = FALSE;
 int position, ch, iterationCount, status;

 assert( isReadPtr( data, dataLength ) );
 assert( isWritePtr( startPos, sizeof( int ) ) );

 /* Clear return value */
 *startPos = 0;

 /* If the item is too small to contain any useful data, we don't even
    try and examine it.  We don't treat this as a data or underflow error
    since it may be a short but valid data object like an empty CRL */
 if( dataLength < 64 )
  return( CRYPT_CERTFORMAT_NONE );

 sMemConnect( &stream, data, dataLength );

 /* Sometimes the object can be preceded by a few blank lines.  We're
    fairly lenient with this.  Note that we can't use readTextLine() at
    this point because we don't know yet whether we're getting binary or
    ASCII data */
 iterationCount = 0;
 do
  ch = sgetc( &stream );
 while( ch == '/r' || ch == '/n' && /
     iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
 if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
  return( CRYPT_ERROR_BADDATA );
 if( cryptStatusError( ch ) )
  {
  sMemDisconnect( &stream );
  return( ch );
  }
 position = stell( &stream ) - 1;
 sseek( &stream, position );

 /* Perform a quick check to weed out unencoded cert data, which is
    usually the case */
 status = readSequenceI( &stream, NULL );
 if( cryptStatusOK( status ) )
  {
  sMemDisconnect( &stream );
  return( CRYPT_CERTFORMAT_NONE );
  }
 sClearError( &stream );
 sseek( &stream, position );

 /* If it starts with a dash, check for PEM header encapsulation */
 if( ch == '-' )
  {
  position = checkPEMHeader( &stream );
  if( cryptStatusError( position ) )
   {
   sMemDisconnect( &stream );
   return( position );
   }
  if( checkBase64( &stream ) )
   {
   sMemDisconnect( &stream );
   *startPos = position;
   return( CRYPT_CERTFORMAT_TEXT_CERTIFICATE );
   }
  sMemDisconnect( &stream );
  return( CRYPT_ERROR_BADDATA );
  }

 /* Check for raw base64 data */
 if( checkBase64( &stream ) )
  {
  sMemDisconnect( &stream );
  *startPos = position;
  return( CRYPT_CERTFORMAT_TEXT_CERTIFICATE );
  }
 sseek( &stream, position );

 /* It doesn't look like raw base64, check for an S/MIME header */
 iterationCount = 0;
 do
  {
  char buffer[ 1024 + 8 ];

  status = readTextLine( readCharFunction, &stream, buffer,
          1024, NULL );
  if( !cryptStatusError( status ) && status >= 33 && /
   !strCompare( buffer, "Content-Transfer-Encoding:", 26 ) )
   {
   const int length = status;
   int index;

   /* Check for a valid content encoding type */
   for( index = 26; index < length && buffer[ index ] == ' ';
     index++ );
   if( length - index < 6 )
    /* It's too short to be a valid encoding type, skip it */
    continue;
   if( !strCompare( buffer + index, "base64", 6 ) )
    seenTransferEncoding = TRUE;
   else
    if( !strCompare( buffer + index, "binary", 6 ) )
     seenTransferEncoding = isBinaryEncoding = TRUE;
   }
  }
 while( status > 0 && iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
 if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
  return( CRYPT_ERROR_BADDATA );
 if( cryptStatusError( status ) || !seenTransferEncoding )
  {
  sMemDisconnect( &stream );
  return( cryptStatusError( status ) ? status : CRYPT_ERROR_BADDATA );
  }

 /* Skip trailing blank lines */
 iterationCount = 0;
 do
  ch = sgetc( &stream );
 while( ch == '/r' || ch == '/n' && /
     iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
 if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
  return( CRYPT_ERROR_BADDATA );
 if( cryptStatusError( ch ) )
  {
  sMemDisconnect( &stream );
  return( ch );
  }
 position = stell( &stream ) - 1;

 /* Make sure that the content is some form of encoded cert */
 *startPos = position;
 if( isBinaryEncoding )
  status = CRYPT_CERTFORMAT_CERTIFICATE;
 else
  {
  sseek( &stream, position );
  status = checkBase64( &stream ) ? CRYPT_ICERTFORMAT_SMIME_CERTIFICATE : /
            CRYPT_ERROR_BADDATA;
  }
 sMemDisconnect( &stream );
 return( status );
 }

/* Encode a block of binary data into the base64 format, returning the total
   number of output bytes */

int base64encode( char *dest, const int destMaxLen, const void *src,
      const int srcLen, const CRYPT_CERTTYPE_TYPE certType )
 {
 const BYTE *srcPtr = src;
 int srcIndex = 0, destIndex = 0, lineByteCount = 0;
 int remainder = srcLen % 3, headerInfoIndex;

 assert( destMaxLen > 10 && isWritePtr( dest, destMaxLen ) );
 assert( srcLen > 10 && isReadPtr( src, srcLen ) );

 /* If it's a certificate object, add the header */
 if( certType != CRYPT_CERTTYPE_NONE )
  {
  for( headerInfoIndex = 0;
    headerInfo[ headerInfoIndex ].type != certType && /
    headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE && /
    headerInfoIndex < FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO );
    headerInfoIndex++ );
  if( headerInfoIndex >= FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO ) )
   retIntError();
  assert( headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE );
  destIndex = strlen( headerInfo[ headerInfoIndex ].header );
  if( destIndex >= destMaxLen )
   return( CRYPT_ERROR_OVERFLOW );
  memcpy( dest, headerInfo[ headerInfoIndex ].header, destIndex );
  }

 /* Encode the data */
 while( srcIndex < srcLen )
  {
  const int srcLeft = srcLen - srcIndex;

  /* If we've reached the end of a line of binary data and it's a
     certificate, add the EOL marker */
  if( certType != CRYPT_CERTTYPE_NONE && /
   lineByteCount >= BINARY_LINESIZE )
   {
   if( destIndex + EOL_LEN >= destMaxLen )
    return( CRYPT_ERROR_OVERFLOW );
   memcpy( dest + destIndex, EOL, EOL_LEN );
   destIndex += EOL_LEN;
   lineByteCount = 0;
   }

  /* Encode a block of data from the input buffer */
  if( destIndex + 4 >= destMaxLen )
   return( CRYPT_ERROR_OVERFLOW );
  dest[ destIndex++ ] = encode( srcPtr[ srcIndex ] >> 2 );
  if( srcLeft < 2 )
   {
   assert( remainder == 1 );
   dest[ destIndex++ ] = encode( ( srcPtr[ srcIndex ] << 4 ) & 0x30 );
   break;
   }
  dest[ destIndex++ ] = encode( ( ( srcPtr[ srcIndex ] << 4 ) & 0x30 ) | /
           ( ( srcPtr[ srcIndex + 1 ] >> 4 ) & 0x0F ) );
  srcIndex++;
  if( srcLeft < 3 )
   {
   assert( remainder == 2 );
   dest[ destIndex++ ] = encode( ( srcPtr[ srcIndex ] << 2 ) & 0x3C );
   break;
   }
  dest[ destIndex++ ] = encode( ( ( srcPtr[ srcIndex ] << 2 ) & 0x3C ) | /
           ( ( srcPtr[ srcIndex + 1 ] >> 6 ) & 0x03 ) );
  srcIndex++;
  dest[ destIndex++ ] = encode( srcPtr[ srcIndex++ ] & 0x3F );
  lineByteCount += 3;
  }

 /* Add padding if it's not raw base64 data.  For 0 bytes remainder
    there's no padding (the data fits exactly), for 1 byte remainder
    there's 2 bytes padding ("X=="), and for 2 bytes remainder there's 1
    byte padding ("XX=") */
 if( certType != CRYPT_CERTTYPE_NONE && remainder > 0 )
  {
  dest[ destIndex++ ] = BPAD;
  if( remainder == 1 )
   dest[ destIndex++ ] = BPAD;
  }

 /* If it's a certificate object, add the trailer */
 if( certType != CRYPT_CERTTYPE_NONE )
  {
  const int length = strlen( headerInfo[ headerInfoIndex ].trailer );

  if( destIndex + EOL_LEN + length > destMaxLen )
   return( CRYPT_ERROR_OVERFLOW );
  memcpy( dest + destIndex, EOL, EOL_LEN );
  memcpy( dest + destIndex + EOL_LEN,
    headerInfo[ headerInfoIndex ].trailer, length );
  destIndex += EOL_LEN + length;
  }

 /* Return a count of encoded bytes */
 return( destIndex );
 }

/* Decode a block of binary data from the base64 format, returning the total
   number of decoded bytes */

static int fixedBase64decode( BYTE *dest, const int destMaxLen,
         const char *src, const int srcLen )
 {
 int srcIndex = 0, destIndex = 0;

 /* Decode the base64 string as a fixed-length continuous string without
    padding or newlines */
 while( srcIndex < srcLen )
  {
  int status;

  status = decodeBase64chunk( dest + destIndex, destMaxLen - destIndex,
         src + srcIndex, srcLen - srcIndex,
         TRUE );
  if( cryptStatusError( status ) )
   return( status );
  srcIndex += 4;
  destIndex += status;
  }

 /* Return a count of decoded bytes */
 return( destIndex );
 }

int base64decode( void *dest, const int destMaxLen, const char *src,
      const int srcLen, const CRYPT_CERTFORMAT_TYPE format )
 {
 int srcIndex = 0, destIndex = 0, lineByteCount = 0, lineSize = 0;
 BYTE *destPtr = dest;

 assert( destMaxLen > 10 && isWritePtr( dest, destMaxLen ) );
 assert( srcLen > 10 && isReadPtr( src, srcLen ) );

 /* If it's not a certificate, it's a straight base64 string and we can
    use the simplified decoding routines */
 if( format == CRYPT_CERTFORMAT_NONE )
  return( fixedBase64decode( dest, destMaxLen, src, srcLen ) );

 /* Decode the encoded object */
 while( srcIndex < srcLen )
  {
  int status;

  /* Depending on implementations, the length of the base64-encoded
     line can vary from 60 to 72 chars.  We adjust for this by
     checking for the first EOL and setting the line length to the
     size of the first line of base64 text */
  if( lineSize <= 0 && /
   src[ srcIndex ] == '/r' || src[ srcIndex ] == '/n' )
   {
   if( lineByteCount < 56 )
    /* Suspiciously short text line */
    return( CRYPT_ERROR_BADDATA );
   lineSize = lineByteCount;
   }

  /* If we've reached the end of a line of text, look for the EOL
     marker */
  if( lineSize > 0 && lineByteCount >= lineSize )
   {
   status = checkEOL( src + srcIndex, srcLen - srcIndex, format );
   if( status <= 0 )
    break; /* End of input reached, exit */
   srcIndex += status;
   lineByteCount = 0;
   }

  /* Decode a chunk of data from the input buffer */
  status = decodeBase64chunk( destPtr + destIndex,
         destMaxLen - destIndex,
         src + srcIndex, srcLen - srcIndex,
         FALSE );
  if( cryptStatusError( status ) )
   return( status );
  destIndex += status;
  if( status < 3 )
   /* We've reached the end marker on the input data, exit.  Note
      that we can't just wait for srcIndex to pass srcLen as for
      the fixed-length decode because there could be extra trailer
      data following the base64 data.

      In theory we could call checkEOL() here to make sure that the
      trailer is well-formed, but if the data is truncated right on
      the bas64 end marker then this would produce an error, so we
      just stop decoding as soon as we find the end marker */
   break;
  srcIndex += 4;
  lineByteCount += 4;
  }

 /* Return a count of decoded bytes */
 return( destIndex );
 }

/* Calculate the size of a quantity of data once it's en/decoded */

int base64decodeLen( const char *data, const int dataLength )
 {
 STREAM stream;
 int ch, length, iterationCount = 0;

 assert( isReadPtr( data, dataLength ) );

 /* Skip ahead until we find the end of the decodable data.  Note that
    this ignores errors on the input stream since at this point all that
    we're interested in is how much we can decode from it, not whether
    it's valid or not */
 sMemConnect( &stream, data, dataLength );
 do
  {
  ch = sgetc( &stream );
  if( cryptStatusError( ch ) || ch == BPAD )
   break;
  ch = decode( ch );
  }
 while( ch != BERR && iterationCount++ < FAILSAFE_ITERATIONS_MAX );
 if( iterationCount >= FAILSAFE_ITERATIONS_MAX )
  retIntError();
 length = stell( &stream );
 sMemDisconnect( &stream );

 /* Return a rough estimate of how much room the decoded data will occupy.
    This ignores the EOL size so it always overestimates, but a strict
    value isn't necessary since it's only used for memory buffer
    allocation */
 return( ( length * 3 ) / 4 );
 }

int base64encodeLen( const int dataLength,
      const CRYPT_CERTTYPE_TYPE certType )
 {
 int length = roundUp( ( dataLength * 4 ) / 3, 4 ), headerInfoIndex;

 for( headerInfoIndex = 0;
   headerInfo[ headerInfoIndex ].type != certType && /
   headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE && /
   headerInfoIndex < FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO );
   headerInfoIndex++ );
 if( headerInfoIndex >= FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO ) )
  retIntError();
 assert( headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE );

 /* Calculate the extra length due to EOL's */
 length += ( ( roundUp( length, TEXT_LINESIZE ) / TEXT_LINESIZE ) * EOL_LEN );

 /* Return the total length due to delimiters */
 return( strlen( headerInfo[ headerInfoIndex ].header ) + length + /
   strlen( headerInfo[ headerInfoIndex ].trailer ) );
 }

From CrypTool ===================================================

/*
 * base64.c
 *

#include "stdafx.h"
#include "CryptDoc.h"
#include "FileTools.h"
#include "Cryptography.h"
#include <ios>
#include <string>
#include <iostream>
#include <fstream>
#include "ScintillaDoc.h"
#include "ScintillaView.h"


#define STREAM_IN_BLOCKLENGTH_ENC 4080  //Gr÷▀e des Einlesebuffers beim Enkodieren
#define STREAM_OUT_BLOCKLENGTH_ENC (STREAM_IN_BLOCKLENGTH_ENC*4/3+STREAM_IN_BLOCKLENGTH_ENC/48*1)  //Gr÷▀e des Auslesebuffers beim Enkodieren
#define STREAM_IN_BLOCKLENGTH_DEC 4096   //Gr÷▀e des Einlesebuffers beim Dekodieren
#define STREAM_OUT_BLOCKLENGTH_DEC STREAM_IN_BLOCKLENGTH_DEC*3/4 

#define HLIB_IN_HLIB 1
#include "base64.h"

/* Maps the values in range 0...63 to base64 chars. */
static const unsigned char *_base64_encode=(unsigned char *)
 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "abcdefghijklmnopqrstuvwxyz"
 "0123456789+/";

ssize_t Base64Encode(
 const char *_in,size_t inlen,
 char *_out,size_t outlen,
 u_int32_t *state/*=NULL*/,int lwidth/*=0*/,ssize_t *outfill)
{
 unsigned char *in=(unsigned char *)_in;
 unsigned char *out=(unsigned char *)_out;
 unsigned char *inend=in+inlen;
 unsigned char *outend=out+outlen;
 u_int32_t acc;
 int ai,ci;

 if(state)
 {
  acc=(*state)&0xffffU;
  ai=((*state)>>16)&0x3U;
  ci=((*state)>>18);
 }
 else
 {  acc=0;  ai=0;  ci=0;  }
 
 for(;in<inend;in++)
 {
  acc<<=8;
  acc|=(u_int32_t)(*in);
  ++ai;
  if(ai==3)
  {
   *(out++)=_base64_encode[(acc>>18) & 0x3fU];
   *(out++)=_base64_encode[(acc>>12) & 0x3fU];
   *(out++)=_base64_encode[(acc>> 6) & 0x3fU];
   *(out++)=_base64_encode[ acc      & 0x3fU];
   ai=0;
   acc=0U;
   if(lwidth)  if((++ci)==lwidth)
   {
    *((char*)(out++))='/n';
    ci=0;
   }
  }
 }
 
 if(state && inlen)
 {
  /* save carry in state (ai=0,1,2) */
  *state =
   (((u_int32_t)ci)<<18) |
   (((u_int32_t)ai)<<16) |
   acc;
 }
 else
 {
   if(state)  *state=0;
 
  /* store rest of input in output */
  /* ai==3 never possible here.*/
  switch(ai)
  {
   case 0:
    break; //Wenn case 0 dann encoding vollstΣndig.
   case 1:
    *(out++)=_base64_encode[(acc>>2) & 0x3fU];
    *(out++)=_base64_encode[(acc<<4) & 0x3fU];
    *((char*)(out++))='=';
    *((char*)(out++))='=';
    break;
   case 2:
    *(out++)=_base64_encode[(acc>>10) & 0x3fU];
    *(out++)=_base64_encode[(acc>> 4) & 0x3fU];
    *(out++)=_base64_encode[(acc<< 2) & 0x3fU];
    *((char*)(out++))='=';
    break;
  } 
 }
    *outfill = out-(unsigned char*)_out;
 return(B64_CODE_NOERROR);
}

static const unsigned char *_base64_decode=(const unsigned char *)
 "/xff/xff/xff/xff/xff/xff/xff/xff/xfe/xfe/xfe/xfe/xfe/xfe/xff/xff"
 "/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff"
 "/xfe/xff/xff/xff/xff/xff/xff/xff/xff/xff/xff/x3e/xff/xff/xff/x3f"
 "/x34/x35/x36/x37/x38/x39/x3a/x3b/x3c/x3d/xff/xff/xff/xfd/xff/xff"
 "/xff/x00/x01/x02/x03/x04/x05/x06/x07/x08/x09/x0a/x0b/x0c/x0d/x0e"
 "/x0f/x10/x11/x12/x13/x14/x15/x16/x17/x18/x19/xff/xfe/xff/xff/xff"
 "/xff/x1a/x1b/x1c/x1d/x1e/x1f/x20/x21/x22/x23/x24/x25/x26/x27/x28"
 "/x29/x2a/x2b/x2c/x2d/x2e/x2f/x30/x31/x32/x33/xff/xff/xff/xff/xfe";

ssize_t Base64Decode(
 const char *_in,size_t inlen,char *_out,size_t outlen
 ,u_int32_t *state /*=NULL*/,ssize_t *outfill,ssize_t *indec, BOOL lastBlock)
{
 unsigned char *ib=(unsigned char*)_in;
 unsigned char *ib_end=ib+inlen;
 unsigned char *ob=(unsigned char*)_out;
 unsigned char *ob_end=ob+outlen;
 u_int32_t dec=0xfdU;   /* simulate end char in case inlen=0 */
 u_int32_t acc = state ? ((*state)&0xffffffU) : 0U;
 int       ai  = state ? ((*state)>>24) : 0;
 unsigned int zeichen=0;
 CString result="";

 BOOL illegal_eq = FALSE;


 for(; ib<ib_end; ib++)
 {  
  zeichen++;

  if((*ib)>=128U) 
  {
   *indec=(char*)ib-_in;
   *outfill = (char*)ob-_out;
   return(B64_DECODE_ILLEGAL_CHARACTER);
  }
  dec=_base64_decode[(int)(*ib)];
  if(dec<64)
  {
   if (illegal_eq)
   {
    *indec=(char*)ib-_in;
    *outfill = (char*)ob-_out;
    return(B64_DECODE_ILLEGAL_CHARACTER);    
   }
   acc=(acc<<6)|dec;
   ++ai;
   if(ai==4)  /* got 4 chars */
   {
    *(ob++)=(unsigned char)((acc>>16) & 0xffU);
    *(ob++)=(unsigned char)((acc>> 8) & 0xffU);
    *(ob++)=(unsigned char)( acc      & 0xffU);
    acc=0U;  ai=0;
   }
  }
  else switch(dec)
  {
   case 0xffU: 
     *indec=(char*)ib-_in;
     *outfill = (char*)ob-_out;
     return(B64_DECODE_ILLEGAL_CHARACTER);
     break;
   case 0xfdU:
     *indec=(char*)ib-_in;
     if (!lastBlock)
     {
      *outfill = (char*)ob-_out;
      return(B64_DECODE_PREMATURE_END);
     }
     else
      illegal_eq = TRUE;
     break;
     // goto breakfor;
  }
  
 }
 breakfor:;
 /* ai==4 not possible here. ai<4 here. */
 
 if(state && dec!=0xfdU)  /* state and no end char */
 {
  /* Save carry in state. */
  *state = (((u_int32_t)ai)<<24) | acc;
 }
 else
 {
  if(state)  *state=0U;
  /* Save the last bytes in the output buffer. */

  switch(ai)
  {
   case 3:  /* got 3 chars */
    if ( acc & 0x03 ) return (B64_DECODE_MISSING_CHAR); //FIXME ???
    *(ob++)=(unsigned char)((acc>>10) & 0xffU);
    *(ob++)=(unsigned char)((acc>> 2) & 0xffU);
    break;
   case 2:  /* got 2 chars */
    if ( acc & 0x0f ) return (B64_DECODE_MISSING_CHAR);// FIXME ???
    *(ob++)=(unsigned char)((acc>> 4) & 0xffU);
    break;
   case 1:
    return (B64_DECODE_MISSING_CHAR);
    break; //FIXME??
    
   }
  }
 *outfill = (char*)ob-_out;
 return(B64_CODE_NOERROR);
}

From Anonymous =======================================


void dobase64enc(const char *infile, const char *OldTitle)
{
 char outfile[CRYPTOOL_PATH_LENGTH], title[256];
    CAppDocument *NewDoc;

    GetTmpName(outfile,"cry",".tmp");

 int lwidth=16; //gewⁿnschte ZeilenlΣnge/4=lwidth
 ssize_t rv;
 int count;
 char buffer[STREAM_IN_BLOCKLENGTH_ENC];
 char ob[STREAM_OUT_BLOCKLENGTH_ENC];
 unsigned int state=0;
 ssize_t outchars=0;
 bool lf= false;

 std::fstream filein(infile, std::ios_base::in|std::ios_base::binary);
 if (!filein.is_open())
 {
  base64error( outfile,NULL,B64_FILE_OPEN_ERROR,NULL);
  return;
 }
 std::fstream fileout(outfile, std::ios_base::out|std::ios_base::binary);
 
 if (!fileout.is_open())
 {
  base64error( outfile,NULL,B64_FILE_OPEN_ERROR,NULL);
  return;
 }                      

 do
 {
  filein.read(buffer, STREAM_IN_BLOCKLENGTH_ENC);
  count = filein.gcount();
  rv=Base64Encode(buffer,count,ob,STREAM_OUT_BLOCKLENGTH_ENC,&state,lwidth, &outchars);   
   
  if(rv>=0)
  {   
  
   if(outchars)
    lf=(ob[outchars-1]=='/n') ? true : false;

   fileout.write(ob,outchars);
   if (!fileout.good())
   {
    base64error(outfile,NULL,B64_FILE_WRITE_ERROR,NULL);  
    return;
   }
  }  
 }
 while (count);

 if (lf==false)
 {
  ob[0]='/n';
  fileout.write(ob,1);
 }

 filein.close();
 fileout.close();


    NewDoc = theApp.OpenDocumentFileNoMRU(outfile);
    remove(outfile);
    if(NewDoc)
 {
  LoadString(AfxGetInstanceHandle(),IDS_STRING_MSG_BASE64ENC_OF,pc_str,STR_LAENGE_STRING_TABLE);
        MakeNewName(title,sizeof(title),pc_str,OldTitle);
        NewDoc->SetTitle(title);
    }

 CView* CView_hilf = ((CMDIFrameWnd*)theApp.m_pMainWnd)->MDIGetActive()->GetActiveView();
 ((CScintillaView*)CView_hilf)->OnViewFontCourier10();
 
}

void dobase64dec(const char *infile, const char *OldTitle)
{
 char outfile[CRYPTOOL_PATH_LENGTH], title[256];
    CAppDocument *NewDoc;

    GetTmpName(outfile,"cry",".txt");
 ssize_t rv;
 int count;
 char buffer[STREAM_IN_BLOCKLENGTH_DEC];
 char ob[STREAM_OUT_BLOCKLENGTH_DEC];
 unsigned int state=0;
 ssize_t outchars=0;
 ssize_t inchars=0;
 int zeichen=0;
 
 std::fstream filein(infile, std::ios_base::in|std::ios_base::binary);
 if (!filein.is_open())
 {
  base64error(infile,buffer[inchars],B64_FILE_OPEN_ERROR,inchars);
  return;
 }
 
 std::fstream fileout(outfile, std::ios_base::out|std::ios_base::binary);
 if (!fileout.is_open())
 {
  base64error( outfile,buffer[inchars],B64_FILE_OPEN_ERROR,inchars);
  return;
 }                       

 do
 {
   
  filein.read(buffer, STREAM_IN_BLOCKLENGTH_DEC);
  count = filein.gcount();
   
   
  rv=Base64Decode(buffer,count,ob,STREAM_OUT_BLOCKLENGTH_DEC,&state, &outchars, &inchars, filein.eof());
   

  if(rv<0)
  {
   base64error( "",buffer[inchars],rv,inchars+zeichen); 
   count=0;
  }
  if(outchars>0)
  {
   fileout.write(ob,outchars);
   if (!fileout.good())
   {
    base64error(outfile,NULL,B64_FILE_WRITE_ERROR,NULL);  
    return;
   }
  }
  zeichen=zeichen+4096;
 }
 while (count);

 filein.close();
 fileout.close();
 
    NewDoc = theApp.OpenDocumentFileNoMRU(outfile);
    remove(outfile);
    if(NewDoc)
 {
  LoadString(AfxGetInstanceHandle(),IDS_STRING_MSG_BASE64DEC_OF,pc_str,STR_LAENGE_STRING_TABLE);
        MakeNewName(title,sizeof(title),pc_str,OldTitle);
        NewDoc->SetTitle(title);
    }
 
}

From xyssl ================================================

#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif

#include "xyssl/base64.h"

static const int base64_enc_map[64] =
{
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '+', '/'
};

static const int base64_dec_map[128] =
{
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
     49,  50,  51, 127, 127, 127, 127, 127
};

/*
 * Encode a buffer into base64 format
 */
int base64_encode( unsigned char *dst, int *dlen,
                   unsigned char *src, int  slen )
{
    int i, n;
    int C1, C2, C3;
    unsigned char *p;

    if( slen == 0 )
        return( 0 );

    n = ( slen << 3 ) / 6;

    switch( ( slen << 3 ) - ( n * 6 ) )
    {
        case  2: n += 3; break;
        case  4: n += 2; break;
        default: break;
    }

    if( *dlen < n + 1 )
    {
        *dlen = n + 1;
        return( ERR_BASE64_BUFFER_TOO_SMALL );
    }

    n = ( slen / 3 ) * 3;

    for( i = 0, p = dst; i < n; i += 3 )
    {
        C1 = *src++;
        C2 = *src++;
        C3 = *src++;

        *p++ = base64_enc_map[( C1 >> 2 ) & 0x3F];
        *p++ = base64_enc_map[((( C1 &  3 ) << 4) + ( C2 >> 4 )) & 0x3F];
        *p++ = base64_enc_map[((( C2 & 15 ) << 2) + ( C3 >> 6 )) & 0x3F];
        *p++ = base64_enc_map[C3 & 0x3F];
    }

    if( i < slen )
    {
        C1 = *src++;
        C2 = ((i + 1) < slen) ? *src++ : 0;

        *p++ = base64_enc_map[( C1 >> 2 ) & 0x3F];
        *p++ = base64_enc_map[((( C1 & 3 ) << 4) + ( C2 >> 4 )) & 0x3F];
        *p++ = ((i + 1) < slen) ?
            base64_enc_map[((( C2 & 15 ) << 2)) & 0x3F] : '=';

        *p++ = '=';
    }

    *dlen = p - dst;

    return( *p = 0 );
}

/*
 * Decode a base64-formatted buffer
 */
int base64_decode( unsigned char *dst, int *dlen,
                   unsigned char *src, int  slen )
{
    int i, j, n;
    unsigned long x;
    unsigned char *p;

    for( i = j = n = 0; i < slen; i++ )
    {
        if( ( slen - i ) >= 2 &&
            src[i] == '/r' && src[i + 1] == '/n' )
            continue;

        if( src[i] == '/n' )
            continue;

        if( src[i] == '=' && ++j > 2 )
            return( ERR_BASE64_INVALID_CHARACTER );

        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
            return( ERR_BASE64_INVALID_CHARACTER );

        if( base64_dec_map[src[i]] < 64 && j != 0 )
            return( ERR_BASE64_INVALID_CHARACTER );

        n++;
    }

    if( n == 0 )
        return( 0 );

    n = ( ( n * 6 ) + 7 ) >> 3;

    if( *dlen < n )
    {
        *dlen = n;
        return( ERR_BASE64_BUFFER_TOO_SMALL );
    }

   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
   {
        if( *src == '/r' || *src == '/n' )
            continue;

        j -= ( base64_dec_map[*src] == 64 );
        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );

        if( ++n == 4 )
        {
            n = 0;
            *p++ = (unsigned char) ( x >> 16 );
            if( j > 1 ) *p++ = (unsigned char) ( x >> 8 );
            if( j > 2 ) *p++ = (unsigned char )  x;
        }
    }

    *dlen = p - dst;

    return( 0 );
}

static const char _base64_src[] = "_base64_src";

#if defined(SELF_TEST)

#include <string.h>
#include <stdio.h>

static const unsigned char base64_test_dec[64] =
{
    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
};

static const unsigned char base64_test_enc[] =
    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";

/*
 * Checkup routine
 */
int base64_self_test( int verbose )
{
    int len;
    unsigned char *src, buffer[128];

    if( verbose != 0 )
        printf( "  Base64 encoding test: " );

    len = sizeof( buffer );
    src = (unsigned char *) base64_test_dec;

    if( base64_encode( buffer, &len, src, 64 ) != 0 ||
        memcmp( base64_test_enc,  buffer, 88 ) != 0 )
    {
        if( verbose != 0 )
            printf( "failed/n" );

        return( 1 );
    }

    if( verbose != 0 )
        printf( "passed/n  Base64 decoding test: " );

    len = sizeof( buffer );
    src = (unsigned char *) base64_test_enc;

    if( base64_decode( buffer, &len, src, 88 ) != 0 ||
        memcmp( base64_test_dec,  buffer, 64 ) != 0 )
    {
        if( verbose != 0 )
            printf( "failed/n" );

        return( 1 );
    }

    if( verbose != 0 )
        printf( "passed/n/n" );

    return( 0 );
}
#else
int base64_self_test( int verbose )
{
    return( 0 );
}
#endif

From INS & IBM ========================================

namespace base64
{
  const char _to_table[64] =
  { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3',
    '4', '5', '6', '7', '8', '9', '+', '/'
  };
  const char* to_table = _to_table;


  const char* to_table_end =
    _to_table + sizeof(_to_table);

  const char _from_table[128] =
  {
    -1, -1, -1, -1, -1, -1, -1, -1, // 0
    -1, -1, -1, -1, -1, -1, -1, -1, // 8
    -1, -1, -1, -1, -1, -1, -1, -1, // 16
    -1, -1, -1, -1, -1, -1, -1, -1, // 24
    -1, -1, -1, -1, -1, -1, -1, -1, // 32
    -1, -1, -1, 62, -1, -1, -1, 63, // 40
    52, 53, 54, 55, 56, 57, 58, 59, // 48
    60, 61, -1, -1, -1,  0, -1, -1, // 56
    -1,  0,  1,  2,  3,  4,  5,  6, // 64
     7,  8,  9, 10, 11, 12, 13, 14, // 72
    15, 16, 17, 18, 19, 20, 21, 22, // 80
    23, 24, 25, -1, -1, -1, -1, -1, // 88
    -1, 26, 27, 28, 29, 30, 31, 32, // 96
    33, 34, 35, 36, 37, 38, 39, 40, // 104
    41, 42, 43, 44, 45, 46, 47, 48, // 112
    49, 50, 51, -1, -1, -1, -1, -1  // 120
  };
  const char* from_table = _from_table;
}

/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */

/*
 * Copyright (c) 1996 by Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

/*
 * Portions Copyright (c) 1995 by International Business Machines, Inc.
 *
 * International Business Machines, Inc. (hereinafter called IBM) grants
 * permission under its copyrights to use, copy, modify, and distribute this
 * Software with or without fee, provided that the above copyright notice and
 * all paragraphs of this notice appear in all copies, and that the name of IBM
 * not be used in connection with the marketing of any product incorporating
 * the Software or modifications thereof, without specific, written prior
 * permission.
 *
 * To the extent it has a right to do so, IBM grants an immunity from suit
 * under its patents, if any, for the use, sale or manufacture of products to
 * the extent that such products are used for performing Domain Name System
 * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
 * granted for any product per se or for any other function of any product.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */

#include "includes.h"

#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))

#include <sys/types.h>
#include <sys/param.h>
#ifndef HAVE_NETWARE
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>

#include <ctype.h>
#include <stdio.h>

#include <stdlib.h>
#include <string.h>

#include "base64.h"

/* XXX abort illegal in library */
#define Assert(Cond) if (!(Cond)) abort()

static const char Base64[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';

/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
   The following encoding technique is taken from RFC 1521 by Borenstein
   and Freed.  It is reproduced here in a slightly edited form for
   convenience.

   A 65-character subset of US-ASCII is used, enabling 6 bits to be
   represented per printable character. (The extra 65th character, "=",
   is used to signify a special processing function.)

   The encoding process represents 24-bit groups of input bits as output
   strings of 4 encoded characters. Proceeding from left to right, a
   24-bit input group is formed by concatenating 3 8-bit input groups.
   These 24 bits are then treated as 4 concatenated 6-bit groups, each
   of which is translated into a single digit in the base64 alphabet.

   Each 6-bit group is used as an index into an array of 64 printable
   characters. The character referenced by the index is placed in the
   output string.

                         Table 1: The Base64 Alphabet

      Value Encoding  Value Encoding  Value Encoding  Value Encoding
          0 A            17 R            34 i            51 z
          1 B            18 S            35 j            52 0
          2 C            19 T            36 k            53 1
          3 D            20 U            37 l            54 2
          4 E            21 V            38 m            55 3
          5 F            22 W            39 n            56 4
          6 G            23 X            40 o            57 5
          7 H            24 Y            41 p            58 6
          8 I            25 Z            42 q            59 7
          9 J            26 a            43 r            60 8
         10 K            27 b            44 s            61 9
         11 L            28 c            45 t            62 +
         12 M            29 d            46 u            63 /
         13 N            30 e            47 v
         14 O            31 f            48 w         (pad) =
         15 P            32 g            49 x
         16 Q            33 h            50 y

   Special processing is performed if fewer than 24 bits are available
   at the end of the data being encoded.  A full encoding quantum is
   always completed at the end of a quantity.  When fewer than 24 input
   bits are available in an input group, zero bits are added (on the
   right) to form an integral number of 6-bit groups.  Padding at the
   end of the data is performed using the '=' character.

   Since all base64 input is an integral number of octets, only the
         -------------------------------------------------                      
   following cases can arise:
  
       (1) the final quantum of encoding input is an integral
           multiple of 24 bits; here, the final unit of encoded
    output will be an integral multiple of 4 characters
    with no "=" padding,
       (2) the final quantum of encoding input is exactly 8 bits;
           here, the final unit of encoded output will be two
    characters followed by two "=" padding characters, or
       (3) the final quantum of encoding input is exactly 16 bits;
           here, the final unit of encoded output will be three
    characters followed by one "=" padding character.
   */

#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
int
b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
{
 size_t datalength = 0;
 u_char input[3];
 u_char output[4];
 int i;

 while (2 < srclength) {
  input[0] = *src++;
  input[1] = *src++;
  input[2] = *src++;
  srclength -= 3;

  output[0] = input[0] >> 2;
  output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
  output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
  output[3] = input[2] & 0x3f;
  Assert(output[0] < 64);
  Assert(output[1] < 64);
  Assert(output[2] < 64);
  Assert(output[3] < 64);

  if (datalength + 4 > targsize)
   return (-1);
  target[datalength++] = Base64[output[0]];
  target[datalength++] = Base64[output[1]];
  target[datalength++] = Base64[output[2]];
  target[datalength++] = Base64[output[3]];
 }
   
 /* Now we worry about padding. */
 if (0 != srclength) {
  /* Get what's left. */
  input[0] = input[1] = input[2] = '/0';
  for (i = 0; i < srclength; i++)
   input[i] = *src++;
 
  output[0] = input[0] >> 2;
  output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
  output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
  Assert(output[0] < 64);
  Assert(output[1] < 64);
  Assert(output[2] < 64);

  if (datalength + 4 > targsize)
   return (-1);
  target[datalength++] = Base64[output[0]];
  target[datalength++] = Base64[output[1]];
  if (srclength == 1)
   target[datalength++] = Pad64;
  else
   target[datalength++] = Base64[output[2]];
  target[datalength++] = Pad64;
 }
 if (datalength >= targsize)
  return (-1);
 target[datalength] = '/0'; /* Returned value doesn't count /0. */
 return (datalength);
}
#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */

#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)

/* skips all whitespace anywhere.
   converts characters, four at a time, starting at (or after)
   src from base - 64 numbers into three 8 bit bytes in the target area.
   it returns the number of data bytes stored at the target, or -1 on error.
 */

int
b64_pton(char const *src, u_char *target, size_t targsize)
{
 int tarindex, state, ch;
 char *pos;

 state = 0;
 tarindex = 0;

 while ((ch = *src++) != '/0') {
  if (isspace(ch)) /* Skip whitespace anywhere. */
   continue;

  if (ch == Pad64)
   break;

  pos = strchr(Base64, ch);
  if (pos == 0)   /* A non-base64 character. */
   return (-1);

  switch (state) {
  case 0:
   if (target) {
    if (tarindex >= targsize)
     return (-1);
    target[tarindex] = (pos - Base64) << 2;
   }
   state = 1;
   break;
  case 1:
   if (target) {
    if (tarindex + 1 >= targsize)
     return (-1);
    target[tarindex]   |=  (pos - Base64) >> 4;
    target[tarindex+1]  = ((pos - Base64) & 0x0f)
       << 4 ;
   }
   tarindex++;
   state = 2;
   break;
  case 2:
   if (target) {
    if (tarindex + 1 >= targsize)
     return (-1);
    target[tarindex]   |=  (pos - Base64) >> 2;
    target[tarindex+1]  = ((pos - Base64) & 0x03)
       << 6;
   }
   tarindex++;
   state = 3;
   break;
  case 3:
   if (target) {
    if (tarindex >= targsize)
     return (-1);
    target[tarindex] |= (pos - Base64);
   }
   tarindex++;
   state = 0;
   break;
  }
 }

 /*
  * We are done decoding Base-64 chars.  Let's see if we ended
  * on a byte boundary, and/or with erroneous trailing characters.
  */

 if (ch == Pad64) {  /* We got a pad char. */
  ch = *src++;  /* Skip it, get next. */
  switch (state) {
  case 0:  /* Invalid = in first position */
  case 1:  /* Invalid = in second position */
   return (-1);

  case 2:  /* Valid, means one byte of info */
   /* Skip any number of spaces. */
   for (; ch != '/0'; ch = *src++)
    if (!isspace(ch))
     break;
   /* Make sure there is another trailing = sign. */
   if (ch != Pad64)
    return (-1);
   ch = *src++;  /* Skip the = */
   /* Fall through to "single trailing =" case. */
   /* FALLTHROUGH */

  case 3:  /* Valid, means two bytes of info */
   /*
    * We know this char is an =.  Is there anything but
    * whitespace after it?
    */
   for (; ch != '/0'; ch = *src++)
    if (!isspace(ch))
     return (-1);

   /*
    * Now make sure for cases 2 and 3 that the "extra"
    * bits that slopped past the last full byte were
    * zeros.  If we don't check them, they become a
    * subliminal channel.
    */
   if (target && target[tarindex] != 0)
    return (-1);
  }
 } else {
  /*
   * We ended by seeing the end of the string.  Make sure we
   * have no partial bytes lying around.
   */
  if (state != 0)
   return (-1);
 }

 return (tarindex);
}

#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */
#endif

From Bob ===============================================

/*********************************************************************/

MODULE NAME:    b64.c

NOTE:           This source code may be used as you wish, subject to
                the MIT license.  See the LICENCE section below.

DESCRIPTION:
                This little utility implements the Base64
                Content-Transfer-Encoding standard described in
                RFC1113 (http://www.faqs.org/rfcs/rfc1113.html).

                This is the coding scheme used by MIME to allow
                binary data to be transferred by SMTP mail.

                Groups of 3 bytes from a binary stream are coded as
                groups of 4 bytes in a text stream.

                The input stream is 'padded' with zeros to create
                an input that is an even multiple of 3.

                A special character ('=') is used to denote padding so
                that the stream can be decoded back to its exact size.

                Encoded output is formatted in lines which should
                be a maximum of 72 characters to conform to the
                specification.  This program defaults to 72 characters,
                but will allow more or less through the use of a
                switch.  The program enforces a minimum line size
                of 4 characters.

                Example encoding:

                The stream 'ABCD' is 32 bits long.  It is mapped as
                follows:

                ABCD

                 A (65)     B (66)     C (67)     D (68)   (None) (None)
                01000001   01000010   01000011   01000100

                16 (Q)  20 (U)  9 (J)   3 (D)    17 (R) 0 (A)  NA (=) NA (=)
                010000  010100  001001  000011   010001 000000 000000 000000


                QUJDRA==

                Decoding is the process in reverse.  A 'decode' lookup
                table has been created to avoid string scans.

DESIGN GOALS: Specifically:
  Code is a stand-alone utility to perform base64
  encoding/decoding. It should be genuinely useful
  when the need arises and it meets a need that is
  likely to occur for some users.
  Code acts as sample code to show the author's
  design and coding style.

  Generally:
  This program is designed to survive:
  Everything you need is in a single source file.
  It compiles cleanly using a vanilla ANSI C compiler.
  It does its job correctly with a minimum of fuss.
  The code is not overly clever, not overly simplistic
  and not overly verbose.
  Access is 'cut and paste' from a web page.
  Terms of use are reasonable.

VALIDATION:     Non-trivial code is never without errors.  This
                file likely has some problems, since it has only
                been tested by the author.  It is expected with most
                source code that there is a period of 'burn-in' when
                problems are identified and corrected.  That being
                said, it is possible to have 'reasonably correct'
                code by following a regime of unit test that covers
                the most likely cases and regression testing prior
                to release.  This has been done with this code and
                it has a good probability of performing as expected.

                Unit Test Cases:

                case 0:empty file:
                    CASE0.DAT  ->  ->
                    (Zero length target file created
                    on both encode and decode.)

                case 1:One input character:
                    CASE1.DAT A -> QQ== -> A

                case 2:Two input characters:
                    CASE2.DAT AB -> QUJD -> AB

                case 3:Three input characters:
                    CASE3.DAT ABC -> QUJD -> ABC

                case 4:Four input characters:
                    case4.dat ABCD -> QUJDRA== -> ABCD

                case 5:All chars from 0 to ff, linesize set to 50:

                    AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj
                    JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH
                    SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr
                    bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P
                    kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz
                    tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX
                    2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7
                    /P3+/w==

                case 6:Mime Block from e-mail:
                    (Data same as test case 5)

                case 7: Large files:
                    Tested 28 MB file in/out.

                case 8: Random Binary Integrity:
                    This binary program (b64.exe) was encoded to base64,
                    back to binary and then executed.

                case 9 Stress:
                    All files in a working directory encoded/decoded
                    and compared with file comparison utility to
                    ensure that multiple runs do not cause problems
                    such as exhausting file handles, tmp storage, etc.

                -------------

                Syntax, operation and failure:
                    All options/switches tested.  Performs as
                    expected.

                case 10:
                    No Args -- Shows Usage Screen
                    Return Code 1 (Invalid Syntax)
                case 11:
                    One Arg (invalid) -- Shows Usage Screen
                    Return Code 1 (Invalid Syntax)
                case 12:
                    One Arg Help (-?) -- Shows detailed Usage Screen.
                    Return Code 0 (Success -- help request is valid).
                case 13:
                    One Arg Help (-h) -- Shows detailed Usage Screen.
                    Return Code 0 (Success -- help request is valid).
                case 14:
                    One Arg (valid) -- Uses stdin/stdout (filter)
                    Return Code 0 (Sucess)
                case 15:
                    Two Args (invalid file) -- shows system error.
                    Return Code 2 (File Error)
                case 16:
                    Encode non-existent file -- shows system error.
                    Return Code 2 (File Error)
                case 17:
                    Out of disk space -- shows system error.
                    Return Code 3 (File I/O Error)

                -------------

                Compile/Regression test:
                    gcc compiled binary under Cygwin
                    Microsoft Visual Studio under Windows 2000
                    Microsoft Version 6.0 C under Windows 2000

....... (too long - cut it off (太長了 只好縮減)

*/

#include <stdio.h>
#include <stdlib.h>

/*
** Translation Table as described in RFC1113
*/
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/*
** Translation Table to decode (created by author)
*/
static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[//]^_`abcdefghijklmnopq";

/*
** encodeblock
**
** encode 3 8-bit binary bytes as 4 '6-bit' characters
*/
void encodeblock( unsigned char in[3], unsigned char out[4], int len )
{
    out[0] = cb64[ in[0] >> 2 ];
    out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
    out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
    out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}

/*
** encode
**
** base64 encode a stream adding padding and line breaks as per spec.
*/
void encode( FILE *infile, FILE *outfile, int linesize )
{
    unsigned char in[3], out[4];
    int i, len, blocksout = 0;

    while( !feof( infile ) ) {
        len = 0;
        for( i = 0; i < 3; i++ ) {
            in[i] = (unsigned char) getc( infile );
            if( !feof( infile ) ) {
                len++;
            }
            else {
                in[i] = 0;
            }
        }
        if( len ) {
            encodeblock( in, out, len );
            for( i = 0; i < 4; i++ ) {
                putc( out[i], outfile );
            }
            blocksout++;
        }
        if( blocksout >= (linesize/4) || feof( infile ) ) {
            if( blocksout ) {
                fprintf( outfile, "/r/n" );
            }
            blocksout = 0;
        }
    }
}

/*
** decodeblock
**
** decode 4 '6-bit' characters into 3 8-bit binary bytes
*/
void decodeblock( unsigned char in[4], unsigned char out[3] )
{
    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
}

/*
** decode
**
** decode a base64 encoded stream discarding padding, line breaks and noise
*/
void decode( FILE *infile, FILE *outfile )
{
    unsigned char in[4], out[3], v;
    int i, len;

    while( !feof( infile ) ) {
        for( len = 0, i = 0; i < 4 && !feof( infile ); i++ ) {
            v = 0;
            while( !feof( infile ) && v == 0 ) {
                v = (unsigned char) getc( infile );
                v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
                if( v ) {
                    v = (unsigned char) ((v == '$') ? 0 : v - 61);
                }
            }
            if( !feof( infile ) ) {
                len++;
                if( v ) {
                    in[ i ] = (unsigned char) (v - 1);
                }
            }
            else {
                in[i] = 0;
            }
        }
        if( len ) {
            decodeblock( in, out );
            for( i = 0; i < len - 1; i++ ) {
                putc( out[i], outfile );
            }
        }
    }
}

/*
** returnable errors
**
** Error codes returned to the operating system.
**
*/
#define B64_SYNTAX_ERROR        1
#define B64_FILE_ERROR          2
#define B64_FILE_IO_ERROR       3
#define B64_ERROR_OUT_CLOSE     4
#define B64_LINE_SIZE_TO_MIN    5

/*
** b64_message
**
** Gather text messages in one place.
**
*/
char *b64_message( int errcode )
{
    #define B64_MAX_MESSAGES 6
    char *msgs[ B64_MAX_MESSAGES ] = {
            "b64:000:Invalid Message Code.",
            "b64:001:Syntax Error -- check help for usage.",
            "b64:002:File Error Opening/Creating Files.",
            "b64:003:File I/O Error -- Note: output file not removed.",
            "b64:004:Error on output file close.",
            "b64:004:linesize set to minimum."
    };
    char *msg = msgs[ 0 ];

    if( errcode > 0 && errcode < B64_MAX_MESSAGES ) {
        msg = msgs[ errcode ];
    }

    return( msg );
}

/*
** b64
**
** 'engine' that opens streams and calls encode/decode
*/

int b64( int opt, char *infilename, char *outfilename, int linesize )
{
    FILE *infile;
    int retcode = B64_FILE_ERROR;

    if( !infilename ) {
        infile = stdin;
    }
    else {
        infile = fopen( infilename, "rb" );
    }
    if( !infile ) {
        perror( infilename );
    }
    else {
        FILE *outfile;
        if( !outfilename ) {
            outfile = stdout;
        }
        else {
            outfile = fopen( outfilename, "wb" );
        }
        if( !outfile ) {
            perror( outfilename );
        }
        else {
            if( opt == 'e' ) {
                encode( infile, outfile, linesize );
            }
            else {
                decode( infile, outfile );
            }
            if (ferror( infile ) || ferror( outfile )) {
                retcode = B64_FILE_IO_ERROR;
            }
            else {
                 retcode = 0;
            }
            if( outfile != stdout ) {
                if( fclose( outfile ) != 0 ) {
                    perror( b64_message( B64_ERROR_OUT_CLOSE ) );
                    retcode = B64_FILE_IO_ERROR;
                }
            }
        }
        if( infile != stdin ) {
            fclose( infile );
        }
    }

    return( retcode );
}

/*
** showuse
**
** display usage information, help, version info
*/
void showuse( int morehelp )
{
    {
        printf( "/n" );
        printf( "  b64      (Base64 Encode/Decode)      Bob Trower 08/03/01 /n" );
        printf( "           (C) Copr Bob Trower 1986-01.      Version 0.00B /n" );
        printf( "  Usage:   b64 -option  [ -l num ] [<FileIn> [<FileOut>]]  /n" );
        printf( "  Purpose: This program is a simple utility that implements/n" );
        printf( "           Base64 Content-Transfer-Encoding (RFC1113).     /n" );
    }
    if( !morehelp ) {
        printf( "           Use -h option for additional help.              /n" );
    }
    else {
        printf( "  Options: -e  encode to Base64   -h  This help text.      /n" );
        printf( "           -d  decode from Base64 -?  This help text.      /n" );
        printf( "  Note:    -l  use to change line size (from 72 characters)/n" );
        printf( "  Returns: 0 = success.  Non-zero is an error code.        /n" );
        printf( "  ErrCode: 1 = Bad Syntax, 2 = File Open, 3 = File I/O     /n" );
        printf( "  Example: b64 -e binfile b64file     <- Encode to b64     /n" );
        printf( "           b64 -d b64file binfile     <- Decode from b64   /n" );
        printf( "           b64 -e -l40 infile outfile <- Line Length of 40 /n" );
        printf( "  Note:    Will act as a filter, but this should only be   /n" );
        printf( "           used on text files due to translations made by  /n" );
        printf( "           operating systems.                              /n" );
        printf( "  Release: 0.00.00, Tue Aug 7   2:00:00 2001, ANSI-SOURCE C/n" );
    }
}

#define B64_DEF_LINE_SIZE   72
#define B64_MIN_LINE_SIZE    4

#define THIS_OPT(ac, av) (ac > 1 ? av[1][0] == '-' ? av[1][1] : 0 : 0)

/*
** main
**
** parse and validate arguments and call b64 engine or help
*/
int main( int argc, char **argv )
{
    int opt = 0;
    int retcode = 0;
    int linesize = B64_DEF_LINE_SIZE;
    char *infilename = NULL, *outfilename = NULL;

    while( THIS_OPT( argc, argv ) ) {
        switch( THIS_OPT(argc, argv) ) {
            case 'l':
                    linesize = atoi( &(argv[1][2]) );
                    if( linesize < B64_MIN_LINE_SIZE ) {
                        linesize = B64_MIN_LINE_SIZE;
                        printf( "%s/n", b64_message( B64_LINE_SIZE_TO_MIN ) );
                    }
                    break;
            case '?':
            case 'h':
                    opt = 'h';
                    break;
            case 'e':
            case 'd':
                    opt = THIS_OPT(argc, argv);
                    break;
             default:
                    opt = 0;
                    break;
        }
        argv++;
        argc--;
    }
    switch( opt ) {
        case 'e':
        case 'd':
            infilename = argc > 1 ? argv[1] : NULL;
            outfilename = argc > 2 ? argv[2] : NULL;
            retcode = b64( opt, infilename, outfilename, linesize );
            break;
        case 0:
            retcode = B64_SYNTAX_ERROR;
        case 'h':
            showuse( opt );
            break;

    }
    if( retcode ) {
        printf( "%s/n", b64_message( retcode ) );
    }

    return( retcode );
}


 ............................to be continued (沒完沒了)

 

原创粉丝点击