1/* 2 * Copyright 2011, Haiku, Inc. All rights reserved. 3 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. 4 */ 5 6 7#include <ctype.h> 8#include <string.h> 9 10#include <mail_encoding.h> 11#include <SupportDefs.h> 12 13static const char kBase64Alphabet[64] = { 14 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 15 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 16 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 17 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 18 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 19 '+', 20 '/' 21 }; 22 23static const char kHexAlphabet[16] = {'0', '1', '2', '3', '4', '5', '6', '7', 24 '8','9','A','B','C','D','E','F'}; 25 26 27ssize_t 28encode_base64(char *out, const char *in, off_t length, bool packed) 29{ 30 uint32 concat; 31 int i = 0; 32 int k = 0; 33 34 while (i < length) { 35 concat = ((in[i] & 0xff) << 16); 36 37 if ((i+1) < length) 38 concat |= ((in[i+1] & 0xff) << 8); 39 if ((i+2) < length) 40 concat |= (in[i+2] & 0xff); 41 42 i += 3; 43 44 out[k++] = kBase64Alphabet[(concat >> 18) & 63]; 45 out[k++] = kBase64Alphabet[(concat >> 12) & 63]; 46 if ((i+1) < length) 47 out[k++] = kBase64Alphabet[(concat >> 6) & 63]; 48 else if (!packed) 49 out[k++] = '='; 50 if ((i+2) < length) 51 out[k++] = kBase64Alphabet[concat & 63]; 52 else if (!packed) 53 out[k++] = '='; 54 } 55 56 return k; 57} 58 59 60ssize_t 61decode_base64(char *out, const char *in, off_t length) 62{ 63 uint32 concat, value; 64 int lastOutLine = 0; 65 int i, j; 66 int outIndex = 0; 67 68 for (i = 0; i < length; i += 4) { 69 concat = 0; 70 71 for (j = 0; j < 4 && (i + j) < length; j++) { 72 value = in[i + j]; 73 74 if (value == '\n' || value == '\r') { 75 // jump over line breaks 76 lastOutLine = outIndex; 77 i++; 78 j--; 79 continue; 80 } 81 82 if ((value >= 'A') && (value <= 'Z')) 83 value -= 'A'; 84 else if ((value >= 'a') && (value <= 'z')) 85 value = value - 'a' + 26; 86 else if ((value >= '0') && (value <= '9')) 87 value = value - '0' + 52; 88 else if (value == '+') 89 value = 62; 90 else if (value == '/') 91 value = 63; 92 else if (value == '=') 93 break; 94 else { 95 // there is an invalid character in this line - we will 96 // ignore the whole line and go to the next 97 outIndex = lastOutLine; 98 while (i < length && in[i] != '\n' && in[i] != '\r') 99 i++; 100 concat = 0; 101 } 102 103 value = value << ((3-j)*6); 104 105 concat |= value; 106 } 107 108 if (j > 1) 109 out[outIndex++] = (concat & 0x00ff0000) >> 16; 110 if (j > 2) 111 out[outIndex++] = (concat & 0x0000ff00) >> 8; 112 if (j > 3) 113 out[outIndex++] = (concat & 0x000000ff); 114 } 115 116 return outIndex; 117} 118 119 120