gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 begin : Thu May 06 2004 00003 copyright : (C) 2004 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Lesser General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public * 00019 * License along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 * * 00023 ***************************************************************************/ 00024 00025 00026 #ifdef HAVE_CONFIG_H 00027 # include <config.h> 00028 #endif 00029 00030 #define DISABLE_DEBUGLOG 00031 00032 00033 #include "base64.h" 00034 #include <gwenhywfar/misc.h> 00035 #include <gwenhywfar/debug.h> 00036 #include <gwenhywfar/text.h> 00037 #include <string.h> 00038 00039 00040 static const char GWEN_Base64_Alphabet[]= 00041 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 00042 00043 00044 int GWEN_Base64_Encode(const unsigned char *src, unsigned int size, 00045 GWEN_BUFFER *dst, 00046 unsigned int maxLineLength) { 00047 unsigned int by3; 00048 unsigned int i; 00049 unsigned int l; 00050 uint32_t triplet; 00051 unsigned char c1, c2, c3, c4; 00052 00053 if (maxLineLength) { 00054 if (maxLineLength<4) { 00055 DBG_ERROR(GWEN_LOGDOMAIN, "I need at least 4 bytes per line"); 00056 return -1; 00057 } 00058 } 00059 00060 by3=size/3; 00061 /* first encode full triplets */ 00062 l=0; 00063 for (i=0; i<by3; i++) { 00064 triplet=(src[0]<<16)+(src[1]<<8)+src[2]; 00065 src+=3; 00066 c4=triplet & 0x3f; 00067 triplet>>=6; 00068 c3=triplet & 0x3f; 00069 triplet>>=6; 00070 c2=triplet & 0x3f; 00071 triplet>>=6; 00072 c1=triplet & 0x3f; 00073 if (maxLineLength) { 00074 if (l+4>maxLineLength) { 00075 GWEN_Buffer_AppendByte(dst, '\n'); 00076 l=0; 00077 } 00078 l+=4; 00079 } 00080 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]); 00081 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]); 00082 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c3]); 00083 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c4]); 00084 } 00085 if (maxLineLength) { 00086 if (l+4>=maxLineLength) { 00087 GWEN_Buffer_AppendByte(dst, '\n'); 00088 l=0; 00089 } 00090 } 00091 00092 /* then encode remainder */ 00093 switch(size % 3) { 00094 case 0: 00095 /* no remainder */ 00096 break; 00097 00098 case 1: 00099 /* 1 remainder, leads to two trailing "=" */ 00100 triplet=(src[0]<<4); 00101 c2=triplet & 0x3f; 00102 triplet>>=6; 00103 c1=triplet & 0x3f; 00104 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]); 00105 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]); 00106 GWEN_Buffer_AppendString(dst, "=="); 00107 break; 00108 00109 case 2: 00110 /* 2 remainders, leads to one trailing "=" */ 00111 triplet=(src[0]<<10)+(src[1]<<2); 00112 c3=triplet & 0x3f; 00113 triplet>>=6; 00114 c2=triplet & 0x3f; 00115 triplet>>=6; 00116 c1=triplet & 0x3f; 00117 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]); 00118 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]); 00119 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c3]); 00120 GWEN_Buffer_AppendByte(dst, '='); 00121 break; 00122 00123 default: 00124 break; 00125 } 00126 00127 return 0; 00128 } 00129 00130 00131 00132 int GWEN_Base64_Decode(const unsigned char *src, unsigned int size, 00133 GWEN_BUFFER *dst) { 00134 unsigned int i; 00135 const char *p = "0"; 00136 uint32_t v; 00137 int lastWasEq; 00138 int sizeGiven; 00139 00140 /* first decode full triplets */ 00141 sizeGiven=(size!=0); 00142 lastWasEq=0; 00143 for (;;) { 00144 if ((sizeGiven && size==0) || lastWasEq || !*src) 00145 break; 00146 v=0; 00147 00148 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0)) 00149 src++; 00150 if (!*src) 00151 break; 00152 for (i=0; i<4; i++) { 00153 /* get next valid character */ 00154 if (lastWasEq) { 00155 while (*src && *src!='=') 00156 src++; 00157 } 00158 else { 00159 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0)) 00160 src++; 00161 } 00162 if (!*src) { 00163 if (i==0 && !sizeGiven) { 00164 return 0; 00165 } 00166 else { 00167 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end reached (%d)", i); 00168 return -1; 00169 } 00170 } 00171 if (*src=='=') 00172 lastWasEq++; 00173 v<<=6; 00174 v+=(p-GWEN_Base64_Alphabet) & 0x3f; 00175 src++; 00176 } /* for */ 00177 00178 /* now we have a triplet */ 00179 if (sizeGiven) { 00180 switch(size) { 00181 case 1: 00182 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff); 00183 size--; 00184 break; 00185 case 2: 00186 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff); 00187 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff); 00188 size-=2; 00189 break; 00190 default: 00191 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff); 00192 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff); 00193 GWEN_Buffer_AppendByte(dst, v & 0xff); 00194 size-=3; 00195 break; 00196 } /* switch */ 00197 } 00198 else { 00199 int bytes; 00200 00201 bytes=(24-(lastWasEq*6))/8; 00202 if (bytes) { 00203 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff); 00204 if (bytes>1) { 00205 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff); 00206 if (bytes>2) 00207 GWEN_Buffer_AppendByte(dst, v & 0xff); 00208 } 00209 } 00210 } 00211 } /* for full quadruplets */ 00212 00213 return 0; 00214 } 00215 00216 00217 00218 00219