Logo Search packages:      
Sourcecode: ksh version File versions  Download package

base64.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1985-2005 AT&T Corp.                  *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                            by AT&T Corp.                             *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                   Phong Vo <kpv@research.att.com>                    *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * mime base64 encode/decode
 *
 * Glenn Fowler
 * David Korn
 * AT&T Research
 */

#include <ast.h>

#define PAD       '='

#define B64_UC          3
#define B64_EC          4
#define B64_CHUNK 15
#define B64_PAD         64
#define B64_SPC         65
#define B64_IGN         66

static unsigned char    map[UCHAR_MAX+1];

static const char alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/*
 * mime base64 encode
 */

ssize_t
base64encode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
{
      register unsigned char* fp;
      register unsigned char* tp;
      register unsigned char* fe;
      register unsigned char* te;
      register unsigned char* tc;
      register unsigned char* m;
      register unsigned long  b;
      size_t                  n;
      unsigned char           tmp[B64_EC * B64_CHUNK];

      m = (unsigned char*)alp;
      fp = fe = (unsigned char*)fb;
      if (fz >= 3)
      {
            n = fz % 3;
            fe += fz - n;
            fz = n;
      }
      if (tp = (unsigned char*)tb)
      {
            te = tp + tz - B64_EC + 1;
            n = 0;
      }
      else
      {
            if (fn)
                  *fn = fp;
            if (tn)
                  *tn = 0;
            tp = tmp;
            te = tp + sizeof(tmp) - B64_EC + 1;
            n = 1;
      }
      for (;;)
      {
            tc = tp + B64_EC * B64_CHUNK;
            do
            {
                  if (fp >= fe)
                        goto done;
                  if (tp >= te)
                  {
                        if (fn)
                              *fn = fp;
                        if (tn)
                              *tn = tp;
                        n = tp - (unsigned char*)tb + 1;
                        tp = tmp;
                        te = tp + sizeof(tmp) - B64_EC + 1;
                  }
                  b = *fp++ << 16;
                  b |= *fp++ << 8;
                  b |= *fp++;
                  *tp++ = m[b >> 18];
                  *tp++ = m[(b >> 12) & 077];
                  *tp++ = m[(b >> 6) & 077];
                  *tp++ = m[b & 077];
            } while (tp < tc);
            if (n)
            {
                  n += tp - tmp + (fp < fe);
                  tp = tmp;
            }
            else
                  *tp++ = '\n';
      }
 done:
      if (fz)
      {
            b = *fp++ << 16;
            if (fz == 2)
                  b |= *fp++ << 8;
            *tp++ = m[b >> 18];
            *tp++ = m[(b >> 12) & 077];
            *tp++ = (fz == 2) ? m[(b >> 6) & 077] : PAD;
            *tp++ = PAD;
      }
      if (n)
            n += (tp - tmp) - 1;
      else
      {
            if (tp > (unsigned char*)tb && *(tp - 1) == '\n')
                  tp--;
            if (tp < te)
                  *tp = 0;
            n = tp - (unsigned char*)tb;
            if (tn)
                  *tn = tp;
            if (fn)
                  *fn = fp;
      }
      return n;
}

/*
 * mime base64 decode
 */

ssize_t
base64decode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
{
      register unsigned char* fp;
      register unsigned char* tp;
      register unsigned char* fe;
      register unsigned char* te;
      register unsigned char* tx;
      register unsigned char* m;
      register int            c;
      register int            state;
      register unsigned long  v;
      unsigned char*          fc;
      ssize_t                 n;

      if (!(m = map)[0])
      {
            memset(m, B64_IGN, sizeof(map));
            for (tp = (unsigned char*)alp; c = *tp; tp++)
                  m[c] =  tp - (unsigned char*)alp;
            m[PAD] = B64_PAD;
            m[' '] = m['\t'] = m['\n'] = B64_SPC;
      }
      fp = (unsigned char*)fb;
      fe = fp + fz;
      if (tp = (unsigned char*)tb)
      {
            te = tp + tz;
            if (tz > 2)
                  tz = 2;
            tx = te - tz;
            n = 0;
      }
      else
      {
            te = tx = tp;
            n = 1;
      }
      for (;;)
      {
            fc = fp;
            state = 0;
            v = 0;
            while (fp < fe)
            {
                  if ((c = m[*fp++]) < 64)
                  {
                        v = (v << 6) | c;
                        if (++state == 4)
                        {
                              if (tp >= tx)
                              {
                                    if (n)
                                          n += 3;
                                    else
                                    {
                                          n = tp - (unsigned char*)tb + 4;
                                          if (tp < te)
                                          {
                                                *tp++ = (v >> 16);
                                                if (tp < te)
                                                {
                                                      *tp++ = (v >> 8);
                                                      if (tp < te)
                                                            *tp++ = (v);
                                                }
                                          }
                                          if (tn)
                                                *tn = tp;
                                          if (fn)
                                                *fn = fc;
                                    }
                              }
                              else
                              {
                                    *tp++ = (v >> 16);
                                    *tp++ = (v >> 8);
                                    *tp++ = (v);
                              }
                              fc = fp;
                              state = 0;
                              v = 0;
                        }
                  }
                  else if (c == B64_PAD)
                        break;
            }
            switch (state)
            {
            case 0:
                  goto done;
            case 2:
                  if (tp < te)
                        *tp++ = v >> 4;
                  else if (n)
                        n++;
                  else
                  {
                        n = tp - (unsigned char*)tb + 2;
                        if (tn)
                              *tn = tp;
                        if (fn)
                              *fn = fc;
                  }
                  break;
            case 3:
                  if (tp < te)
                  {
                        *tp++ = v >> 10;
                        if (tp < te)
                              *tp++ = v >> 2;
                        else
                        {
                              n = tp - (unsigned char*)tb + 2;
                              if (tn)
                                    *tn = tp;
                              if (fn)
                                    *fn = fc;
                        }
                  }
                  else if (n)
                        n += 2;
                  else
                  {
                        n = tp - (unsigned char*)tb + 3;
                        if (tn)
                              *tn = tp;
                        if (fn)
                              *fn = fc;
                  }
                  break;
            }
            while (fp < fe && ((c = m[*fp++]) == B64_PAD || c == B64_SPC));
            if (fp >= fe || c >= 64)
                  break;
            fp--;
      }
 done:
      if (n)
            n--;
      else
      {
            if (tp < te)
                  *tp = 0;
            n = tp - (unsigned char*)tb;
            if (fn)
                  *fn = fp;
            if (tn)
                  *tn = tp;
      }
      return n;
}

Generated by  Doxygen 1.6.0   Back to index