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
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