bincimap

Log | Files | Refs | LICENSE

base64.cc (3662B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    base64.cc
      5  *  
      6  *  Description:
      7  *    Implementation of base64 Utilities
      8  *
      9  *  Authors:
     10  *    Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
     11  *
     12  *  Bugs:
     13  *
     14  *  ChangeLog:
     15  *
     16  *  --------------------------------------------------------------------
     17  *  Copyright 2002-2005 Andreas Aardal Hanssen
     18  *
     19  *  This program is free software; you can redistribute it and/or modify
     20  *  it under the terms of the GNU General Public License as published by
     21  *  the Free Software Foundation; either version 2 of the License, or
     22  *  (at your option) any later version.
     23  *
     24  *  This program is distributed in the hope that it will be useful,
     25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     27  *  GNU General Public License for more details.
     28  *
     29  *  You should have received a copy of the GNU General Public License
     30  *  along with this program; if not, write to the Free Software
     31  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
     32  *  --------------------------------------------------------------------
     33  */
     34 #ifdef HAVE_CONFIG_H
     35 #include <config.h>
     36 #endif
     37 
     38 #include "base64.h"
     39 #include <string>
     40 #include <iostream>
     41 
     42 using ::std::string;
     43 
     44 typedef unsigned char byte;	      /* Byte type */
     45 
     46 #define TRUE  1
     47 #define FALSE 0
     48 
     49 #define LINELEN 72		      /* Encoded line length (max 76) */
     50 
     51 static byte dtable[256];
     52 
     53 string Binc::base64encode(const string &s_in)
     54 {
     55   int i;
     56   string result;
     57 
     58   /*	Fill dtable with character encodings.  */
     59 
     60   for (i = 0; i < 26; i++) {
     61     dtable[i] = 'A' + i;
     62     dtable[26 + i] = 'a' + i;
     63   }
     64   for (i = 0; i < 10; i++) {
     65     dtable[52 + i] = '0' + i;
     66   }
     67   dtable[62] = '+';
     68   dtable[63] = '/';
     69 
     70   string::const_iterator s_i = s_in.begin();
     71   while (s_i != s_in.end()) {
     72 
     73     byte igroup[3], ogroup[4];
     74     int c, n;
     75 
     76     igroup[0] = igroup[1] = igroup[2] = 0;
     77     for (n = 0; n < 3 && s_i != s_in.end(); n++) {
     78       c = *s_i++;
     79       igroup[n] = (byte) c;
     80     }
     81     if (n > 0) {
     82       ogroup[0] = dtable[igroup[0] >> 2];
     83       ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
     84       ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
     85       ogroup[3] = dtable[igroup[2] & 0x3F];
     86 
     87       /* Replace characters in output stream with "=" pad
     88 	 characters if fewer than three characters were
     89 	 read from the end of the input stream. */
     90 
     91       if (n < 3) {
     92 	ogroup[3] = '=';
     93 	if (n < 2) {
     94 	  ogroup[2] = '=';
     95 	}
     96       }
     97 
     98       for (i = 0; i < 4; i++)
     99 	result += ogroup[i];
    100     }
    101   }
    102 
    103   return result;
    104 }
    105 
    106 string Binc::base64decode(const string &s_in)
    107 {
    108   string result;
    109   int i;
    110 
    111   for (i = 0; i < 255; i++) {
    112     dtable[i] = 0x80;
    113   }
    114   for (i = 'A'; i <= 'Z'; i++) {
    115     dtable[i] = 0 + (i - 'A');
    116   }
    117   for (i = 'a'; i <= 'z'; i++) {
    118     dtable[i] = 26 + (i - 'a');
    119   }
    120   for (i = '0'; i <= '9'; i++) {
    121     dtable[i] = 52 + (i - '0');
    122   }
    123   dtable[(int) '+'] = 62;
    124   dtable[(int) '/'] = 63;
    125   dtable[(int) '='] = 0;
    126 
    127   /*CONSTANTCONDITION*/
    128   string::const_iterator s_i = s_in.begin();
    129   while (s_i != s_in.end()) {
    130     byte a[4], b[4], o[3];
    131 
    132     for (i = 0; i < 4 && s_i != s_in.end(); i++) {
    133       int c = *s_i++;
    134 
    135       if (dtable[c] & 0x80)
    136 	return result;
    137 
    138       a[i] = (byte) c;
    139       b[i] = (byte) dtable[c];
    140     }
    141 
    142     o[0] = (b[0] << 2) | (b[1] >> 4);
    143     o[1] = (b[1] << 4) | (b[2] >> 2);
    144     o[2] = (b[2] << 6) | b[3];
    145 
    146     i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
    147 
    148     for (int j = 0; j < i; ++j)
    149       result += o[j];
    150 
    151     if (i < 3)
    152       break;
    153   }
    154 
    155   return result;
    156 }