1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2010 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * mime base64 encode/decode 25 * 26 * Glenn Fowler 27 * David Korn 28 * AT&T Research 29 */ 30 31 #include <ast.h> 32 33 #define PAD '=' 34 35 #define B64_UC 3 36 #define B64_EC 4 37 #define B64_CHUNK 15 38 #define B64_PAD 64 39 #define B64_SPC 65 40 #define B64_IGN 66 41 42 static unsigned char map[UCHAR_MAX+1]; 43 44 static const char alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 45 46 /* 47 * mime base64 encode 48 */ 49 50 ssize_t 51 base64encode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn) 52 { 53 register unsigned char* fp; 54 register unsigned char* tp; 55 register unsigned char* fe; 56 register unsigned char* te; 57 register unsigned char* tc; 58 register unsigned char* m; 59 register unsigned long b; 60 size_t n; 61 unsigned char tmp[B64_EC * B64_CHUNK]; 62 63 m = (unsigned char*)alp; 64 fp = fe = (unsigned char*)fb; 65 if (fz >= 3) 66 { 67 n = fz % 3; 68 fe += fz - n; 69 fz = n; 70 } 71 if (tp = (unsigned char*)tb) 72 { 73 te = tp + tz - B64_EC + 1; 74 n = 0; 75 } 76 else 77 { 78 if (fn) 79 *fn = fp; 80 if (tn) 81 *tn = 0; 82 tp = tmp; 83 te = tp + sizeof(tmp) - B64_EC + 1; 84 n = 1; 85 } 86 for (;;) 87 { 88 tc = tp + B64_EC * B64_CHUNK; 89 do 90 { 91 if (fp >= fe) 92 goto done; 93 if (tp >= te) 94 { 95 if (fn) 96 *fn = fp; 97 if (tn) 98 *tn = tp; 99 n = tp - (unsigned char*)tb + 1; 100 tp = tmp; 101 te = tp + sizeof(tmp) - B64_EC + 1; 102 } 103 b = *fp++ << 16; 104 b |= *fp++ << 8; 105 b |= *fp++; 106 *tp++ = m[b >> 18]; 107 *tp++ = m[(b >> 12) & 077]; 108 *tp++ = m[(b >> 6) & 077]; 109 *tp++ = m[b & 077]; 110 } while (tp < tc); 111 if (n) 112 { 113 n += tp - tmp + (fp < fe); 114 tp = tmp; 115 } 116 else 117 *tp++ = '\n'; 118 } 119 done: 120 if (fz) 121 { 122 if (tp >= te) 123 { 124 if (fn) 125 *fn = fp; 126 if (tn) 127 *tn = tp; 128 n = tp - (unsigned char*)tb + 1; 129 tp = tmp; 130 te = tp + sizeof(tmp) - B64_EC + 1; 131 } 132 b = *fp++ << 16; 133 if (fz == 2) 134 b |= *fp++ << 8; 135 *tp++ = m[b >> 18]; 136 *tp++ = m[(b >> 12) & 077]; 137 *tp++ = (fz == 2) ? m[(b >> 6) & 077] : PAD; 138 *tp++ = PAD; 139 } 140 if (n) 141 n += (tp - tmp) - 1; 142 else 143 { 144 if (tp > (unsigned char*)tb && *(tp - 1) == '\n') 145 tp--; 146 if (tp < te) 147 *tp = 0; 148 n = tp - (unsigned char*)tb; 149 if (tn) 150 *tn = tp; 151 if (fn) 152 *fn = fp; 153 } 154 return n; 155 } 156 157 /* 158 * mime base64 decode 159 */ 160 161 ssize_t 162 base64decode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn) 163 { 164 register unsigned char* fp; 165 register unsigned char* tp; 166 register unsigned char* fe; 167 register unsigned char* te; 168 register unsigned char* tx; 169 register unsigned char* m; 170 register int c; 171 register int state; 172 register unsigned long v; 173 unsigned char* fc; 174 ssize_t n; 175 176 if (!(m = map)[0]) 177 { 178 memset(m, B64_IGN, sizeof(map)); 179 for (tp = (unsigned char*)alp; c = *tp; tp++) 180 m[c] = tp - (unsigned char*)alp; 181 m[PAD] = B64_PAD; 182 m[' '] = m['\t'] = m['\n'] = B64_SPC; 183 } 184 fp = (unsigned char*)fb; 185 fe = fp + fz; 186 if (tp = (unsigned char*)tb) 187 { 188 te = tp + tz; 189 if (tz > 2) 190 tz = 2; 191 tx = te - tz; 192 n = 0; 193 } 194 else 195 { 196 te = tx = tp; 197 n = 1; 198 } 199 for (;;) 200 { 201 fc = fp; 202 state = 0; 203 v = 0; 204 while (fp < fe) 205 { 206 if ((c = m[*fp++]) < 64) 207 { 208 v = (v << 6) | c; 209 if (++state == 4) 210 { 211 if (tp >= tx) 212 { 213 if (n) 214 n += 3; 215 else 216 { 217 n = tp - (unsigned char*)tb + 4; 218 if (tp < te) 219 { 220 *tp++ = (v >> 16); 221 if (tp < te) 222 { 223 *tp++ = (v >> 8); 224 if (tp < te) 225 *tp++ = (v); 226 } 227 } 228 if (tn) 229 *tn = tp; 230 if (fn) 231 *fn = fc; 232 } 233 } 234 else 235 { 236 *tp++ = (v >> 16); 237 *tp++ = (v >> 8); 238 *tp++ = (v); 239 } 240 fc = fp; 241 state = 0; 242 v = 0; 243 } 244 } 245 else if (c == B64_PAD) 246 break; 247 } 248 switch (state) 249 { 250 case 0: 251 goto done; 252 case 2: 253 if (tp < te) 254 *tp++ = v >> 4; 255 else if (n) 256 n++; 257 else 258 { 259 n = tp - (unsigned char*)tb + 2; 260 if (tn) 261 *tn = tp; 262 if (fn) 263 *fn = fc; 264 } 265 break; 266 case 3: 267 if (tp < te) 268 { 269 *tp++ = v >> 10; 270 if (tp < te) 271 *tp++ = v >> 2; 272 else 273 { 274 n = tp - (unsigned char*)tb + 2; 275 if (tn) 276 *tn = tp; 277 if (fn) 278 *fn = fc; 279 } 280 } 281 else if (n) 282 n += 2; 283 else 284 { 285 n = tp - (unsigned char*)tb + 3; 286 if (tn) 287 *tn = tp; 288 if (fn) 289 *fn = fc; 290 } 291 break; 292 } 293 while (fp < fe && ((c = m[*fp++]) == B64_PAD || c == B64_SPC)); 294 if (fp >= fe || c >= 64) 295 break; 296 fp--; 297 } 298 done: 299 if (n) 300 n--; 301 else 302 { 303 if (tp < te) 304 *tp = 0; 305 n = tp - (unsigned char*)tb; 306 if (fn) 307 *fn = fp; 308 if (tn) 309 *tn = tp; 310 } 311 return n; 312 } 313