1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 b = *fp++ << 16; 123 if (fz == 2) 124 b |= *fp++ << 8; 125 *tp++ = m[b >> 18]; 126 *tp++ = m[(b >> 12) & 077]; 127 *tp++ = (fz == 2) ? m[(b >> 6) & 077] : PAD; 128 *tp++ = PAD; 129 } 130 if (n) 131 n += (tp - tmp) - 1; 132 else 133 { 134 if (tp > (unsigned char*)tb && *(tp - 1) == '\n') 135 tp--; 136 if (tp < te) 137 *tp = 0; 138 n = tp - (unsigned char*)tb; 139 if (tn) 140 *tn = tp; 141 if (fn) 142 *fn = fp; 143 } 144 return n; 145 } 146 147 /* 148 * mime base64 decode 149 */ 150 151 ssize_t 152 base64decode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn) 153 { 154 register unsigned char* fp; 155 register unsigned char* tp; 156 register unsigned char* fe; 157 register unsigned char* te; 158 register unsigned char* tx; 159 register unsigned char* m; 160 register int c; 161 register int state; 162 register unsigned long v; 163 unsigned char* fc; 164 ssize_t n; 165 166 if (!(m = map)[0]) 167 { 168 memset(m, B64_IGN, sizeof(map)); 169 for (tp = (unsigned char*)alp; c = *tp; tp++) 170 m[c] = tp - (unsigned char*)alp; 171 m[PAD] = B64_PAD; 172 m[' '] = m['\t'] = m['\n'] = B64_SPC; 173 } 174 fp = (unsigned char*)fb; 175 fe = fp + fz; 176 if (tp = (unsigned char*)tb) 177 { 178 te = tp + tz; 179 if (tz > 2) 180 tz = 2; 181 tx = te - tz; 182 n = 0; 183 } 184 else 185 { 186 te = tx = tp; 187 n = 1; 188 } 189 for (;;) 190 { 191 fc = fp; 192 state = 0; 193 v = 0; 194 while (fp < fe) 195 { 196 if ((c = m[*fp++]) < 64) 197 { 198 v = (v << 6) | c; 199 if (++state == 4) 200 { 201 if (tp >= tx) 202 { 203 if (n) 204 n += 3; 205 else 206 { 207 n = tp - (unsigned char*)tb + 4; 208 if (tp < te) 209 { 210 *tp++ = (v >> 16); 211 if (tp < te) 212 { 213 *tp++ = (v >> 8); 214 if (tp < te) 215 *tp++ = (v); 216 } 217 } 218 if (tn) 219 *tn = tp; 220 if (fn) 221 *fn = fc; 222 } 223 } 224 else 225 { 226 *tp++ = (v >> 16); 227 *tp++ = (v >> 8); 228 *tp++ = (v); 229 } 230 fc = fp; 231 state = 0; 232 v = 0; 233 } 234 } 235 else if (c == B64_PAD) 236 break; 237 } 238 switch (state) 239 { 240 case 0: 241 goto done; 242 case 2: 243 if (tp < te) 244 *tp++ = v >> 4; 245 else if (n) 246 n++; 247 else 248 { 249 n = tp - (unsigned char*)tb + 2; 250 if (tn) 251 *tn = tp; 252 if (fn) 253 *fn = fc; 254 } 255 break; 256 case 3: 257 if (tp < te) 258 { 259 *tp++ = v >> 10; 260 if (tp < te) 261 *tp++ = v >> 2; 262 else 263 { 264 n = tp - (unsigned char*)tb + 2; 265 if (tn) 266 *tn = tp; 267 if (fn) 268 *fn = fc; 269 } 270 } 271 else if (n) 272 n += 2; 273 else 274 { 275 n = tp - (unsigned char*)tb + 3; 276 if (tn) 277 *tn = tp; 278 if (fn) 279 *fn = fc; 280 } 281 break; 282 } 283 while (fp < fe && ((c = m[*fp++]) == B64_PAD || c == B64_SPC)); 284 if (fp >= fe || c >= 64) 285 break; 286 fp--; 287 } 288 done: 289 if (n) 290 n--; 291 else 292 { 293 if (tp < te) 294 *tp = 0; 295 n = tp - (unsigned char*)tb; 296 if (fn) 297 *fn = fp; 298 if (tn) 299 *tn = tp; 300 } 301 return n; 302 } 303