mutt stable branch with some hacks
at jcs 151 lines 4.2 kB view raw
1/* 2 * This program is free software; you can redistribute it 3 * and/or modify it under the terms of the GNU General Public 4 * License as published by the Free Software Foundation; either 5 * version 2 of the License, or (at your option) any later 6 * version. 7 * 8 * This program is distributed in the hope that it will be 9 * useful, but WITHOUT ANY WARRANTY; without even the implied 10 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 11 * PURPOSE. See the GNU General Public License for more 12 * details. 13 * 14 * You should have received a copy of the GNU General Public 15 * License along with this program; if not, write to the Free 16 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21/* 22 * Base64 handling elsewhere in mutt should be modified to call 23 * these routines. These routines were written because IMAP's 24 * AUTHENTICATE protocol required them, and base64 handling 25 * elsewhere wasn't sufficiently generic. 26 * 27 */ 28 29/* 30 * This code is heavily modified from fetchmail (also GPL'd, of 31 * course) by Brendan Cully <brendan@kublai.com>. 32 * 33 * Original copyright notice: 34 * 35 * The code in the fetchmail distribution is Copyright 1997 by Eric 36 * S. Raymond. Portions are also copyrighted by Carl Harris, 1993 37 * and 1995. Copyright retained for the purpose of protecting free 38 * redistribution of source. 39 * 40 */ 41 42#if HAVE_CONFIG_H 43# include "config.h" 44#endif 45 46#include "mutt.h" 47#include "mime.h" 48 49#define BAD -1 50 51void mutt_buffer_to_base64 (BUFFER *out, const unsigned char *in, size_t len) 52{ 53 mutt_buffer_increase_size (out, 54 ((len * 2) > LONG_STRING) ? (len * 2) : LONG_STRING); 55 mutt_to_base64 ((unsigned char *)out->data, in, len, out->dsize); 56 mutt_buffer_fix_dptr (out); 57} 58 59/* raw bytes to null-terminated base 64 string */ 60void mutt_to_base64 (unsigned char *out, const unsigned char *in, size_t len, 61 size_t olen) 62{ 63 while (len >= 3 && olen > 10) 64 { 65 *out++ = B64Chars[in[0] >> 2]; 66 *out++ = B64Chars[((in[0] << 4) & 0x30) | (in[1] >> 4)]; 67 *out++ = B64Chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; 68 *out++ = B64Chars[in[2] & 0x3f]; 69 olen -= 4; 70 len -= 3; 71 in += 3; 72 } 73 74 /* clean up remainder */ 75 if (len > 0 && olen > 4) 76 { 77 unsigned char fragment; 78 79 *out++ = B64Chars[in[0] >> 2]; 80 fragment = (in[0] << 4) & 0x30; 81 if (len > 1) 82 fragment |= in[1] >> 4; 83 *out++ = B64Chars[fragment]; 84 *out++ = (len < 2) ? '=' : B64Chars[(in[1] << 2) & 0x3c]; 85 *out++ = '='; 86 } 87 *out = '\0'; 88} 89 90int mutt_buffer_from_base64 (BUFFER *out, const char *in) 91{ 92 int olen; 93 94 mutt_buffer_increase_size (out, mutt_strlen (in)); 95 olen = mutt_from_base64 (out->data, in, out->dsize); 96 /* mutt_from_base64 returns raw bytes, so don't terminate the buffer either */ 97 if (olen > 0) 98 out->dptr = out->data + olen; 99 else 100 out->dptr = out->data; 101 102 return olen; 103} 104 105/* Convert '\0'-terminated base 64 string to raw bytes. 106 * Returns length of returned buffer, or -1 on error */ 107int mutt_from_base64 (char *out, const char *in, size_t olen) 108{ 109 int len = 0; 110 register unsigned char digit1, digit2, digit3, digit4; 111 112 do 113 { 114 digit1 = in[0]; 115 if (digit1 > 127 || base64val (digit1) == BAD) 116 return -1; 117 digit2 = in[1]; 118 if (digit2 > 127 || base64val (digit2) == BAD) 119 return -1; 120 digit3 = in[2]; 121 if (digit3 > 127 || ((digit3 != '=') && (base64val (digit3) == BAD))) 122 return -1; 123 digit4 = in[3]; 124 if (digit4 > 127 || ((digit4 != '=') && (base64val (digit4) == BAD))) 125 return -1; 126 in += 4; 127 128 /* digits are already sanity-checked */ 129 if (len == olen) 130 return len; 131 *out++ = (base64val(digit1) << 2) | (base64val(digit2) >> 4); 132 len++; 133 if (digit3 != '=') 134 { 135 if (len == olen) 136 return len; 137 *out++ = ((base64val(digit2) << 4) & 0xf0) | (base64val(digit3) >> 2); 138 len++; 139 if (digit4 != '=') 140 { 141 if (len == olen) 142 return len; 143 *out++ = ((base64val(digit3) << 6) & 0xc0) | base64val(digit4); 144 len++; 145 } 146 } 147 } 148 while (*in && digit4 != '='); 149 150 return len; 151}