00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
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
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
00093 switch(size % 3) {
00094 case 0:
00095
00096 break;
00097
00098 case 1:
00099
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
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
00124 return 0;
00125 }
00126
00127
00128
00129 int GWEN_Base64_Decode(const unsigned char *src, unsigned int size,
00130 GWEN_BUFFER *dst) {
00131 unsigned int i;
00132 const char *p = "0";
00133 uint32_t v;
00134 int lastWasEq;
00135 int sizeGiven;
00136
00137
00138 sizeGiven=(size!=0);
00139 lastWasEq=0;
00140 for (;;) {
00141 if ((sizeGiven && size==0) || lastWasEq || !*src)
00142 break;
00143 v=0;
00144
00145 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
00146 src++;
00147 if (!*src)
00148 break;
00149 for (i=0; i<4; i++) {
00150
00151 if (lastWasEq) {
00152 while (*src && *src!='=')
00153 src++;
00154 }
00155 else {
00156 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
00157 src++;
00158 }
00159 if (!*src) {
00160 if (i==0 && !sizeGiven) {
00161 return 0;
00162 }
00163 else {
00164 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end reached (%d)", i);
00165 return -1;
00166 }
00167 }
00168 if (*src=='=')
00169 lastWasEq++;
00170 v<<=6;
00171 v+=(p-GWEN_Base64_Alphabet) & 0x3f;
00172 src++;
00173 }
00174
00175
00176 if (sizeGiven) {
00177 switch(size) {
00178 case 1:
00179 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
00180 size--;
00181 break;
00182 case 2:
00183 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
00184 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
00185 size-=2;
00186 break;
00187 default:
00188 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
00189 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
00190 GWEN_Buffer_AppendByte(dst, v & 0xff);
00191 size-=3;
00192 break;
00193 }
00194 }
00195 else {
00196 int bytes;
00197
00198 bytes=(24-(lastWasEq*6))/8;
00199 if (bytes) {
00200 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
00201 if (bytes>1) {
00202 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
00203 if (bytes>2)
00204 GWEN_Buffer_AppendByte(dst, v & 0xff);
00205 }
00206 }
00207 }
00208 }
00209
00210 return 0;
00211 }
00212
00213
00214
00215
00216