base64.c
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
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 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