Go to the documentation of this file.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 #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
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 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
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
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 }
00177
00178
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 }
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 }
00212
00213 return 0;
00214 }
00215
00216
00217
00218
00219