anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
base64.cpp (5053B)
1 /* base64 routines. 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "anope.h" 14 15 static const Anope::string Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 16 static const char Pad64 = '='; 17 18 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 19 The following encoding technique is taken from RFC 1521 by Borenstein 20 and Freed. It is reproduced here in a slightly edited form for 21 convenience. 22 23 A 65-character subset of US-ASCII is used, enabling 6 bits to be 24 represented per printable character. (The extra 65th character, "=", 25 is used to signify a special processing function.) 26 27 The encoding process represents 24-bit groups of input bits as output 28 strings of 4 encoded characters. Proceeding from left to right, a 29 24-bit input group is formed by concatenating 3 8-bit input groups. 30 These 24 bits are then treated as 4 concatenated 6-bit groups, each 31 of which is translated into a single digit in the base64 alphabet. 32 33 Each 6-bit group is used as an index into an array of 64 printable 34 characters. The character referenced by the index is placed in the 35 output string. 36 37 Table 1: The Base64 Alphabet 38 39 Value Encoding Value Encoding Value Encoding Value Encoding 40 0 A 17 R 34 i 51 z 41 1 B 18 S 35 j 52 0 42 2 C 19 T 36 k 53 1 43 3 D 20 U 37 l 54 2 44 4 E 21 V 38 m 55 3 45 5 F 22 W 39 n 56 4 46 6 G 23 X 40 o 57 5 47 7 H 24 Y 41 p 58 6 48 8 I 25 Z 42 q 59 7 49 9 J 26 a 43 r 60 8 50 10 K 27 b 44 s 61 9 51 11 L 28 c 45 t 62 + 52 12 M 29 d 46 u 63 / 53 13 N 30 e 47 v 54 14 O 31 f 48 w (pad) = 55 15 P 32 g 49 x 56 16 Q 33 h 50 y 57 58 Special processing is performed if fewer than 24 bits are available 59 at the end of the data being encoded. A full encoding quantum is 60 always completed at the end of a quantity. When fewer than 24 input 61 bits are available in an input group, zero bits are added (on the 62 right) to form an integral number of 6-bit groups. Padding at the 63 end of the data is performed using the '=' character. 64 65 Since all base64 input is an integral number of octets, only the 66 ------------------------------------------------- 67 following cases can arise: 68 69 (1) the final quantum of encoding input is an integral 70 multiple of 24 bits; here, the final unit of encoded 71 output will be an integral multiple of 4 characters 72 with no "=" padding, 73 (2) the final quantum of encoding input is exactly 8 bits; 74 here, the final unit of encoded output will be two 75 characters followed by two "=" padding characters, or 76 (3) the final quantum of encoding input is exactly 16 bits; 77 here, the final unit of encoded output will be three 78 characters followed by one "=" padding character. 79 */ 80 81 void Anope::B64Encode(const Anope::string &src, Anope::string &target) 82 { 83 size_t src_pos = 0, src_len = src.length(); 84 unsigned char input[3] = { '\0', '\0', '\0' }; 85 86 target.clear(); 87 88 while (src_len - src_pos > 2) 89 { 90 input[0] = src[src_pos++]; 91 input[1] = src[src_pos++]; 92 input[2] = src[src_pos++]; 93 94 target += Base64[input[0] >> 2]; 95 target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 96 target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 97 target += Base64[input[2] & 0x3f]; 98 } 99 100 /* Now we worry about padding */ 101 if (src_pos != src_len) 102 { 103 input[0] = input[1] = input[2] = 0; 104 for (size_t i = 0; i < src_len - src_pos; ++i) 105 input[i] = src[src_pos + i]; 106 107 target += Base64[input[0] >> 2]; 108 target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 109 if (src_pos == src_len - 1) 110 target += Pad64; 111 else 112 target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 113 target += Pad64; 114 } 115 } 116 117 /* skips all whitespace anywhere. 118 converts characters, four at a time, starting at (or after) 119 src from base - 64 numbers into three 8 bit bytes in the target area. 120 */ 121 122 void Anope::B64Decode(const Anope::string &src, Anope::string &target) 123 { 124 target.clear(); 125 126 unsigned state = 0; 127 Anope::string::const_iterator ch = src.begin(), end = src.end(); 128 for (; ch != end; ++ch) 129 { 130 if (isspace(*ch)) /* Skip whitespace anywhere */ 131 continue; 132 133 if (*ch == Pad64) 134 break; 135 136 size_t pos = Base64.find(*ch); 137 if (pos == Anope::string::npos) /* A non-base64 character */ 138 return; 139 140 switch (state) 141 { 142 case 0: 143 target += pos << 2; 144 state = 1; 145 break; 146 case 1: 147 target[target.length() - 1] |= pos >> 4; 148 target += (pos & 0x0f) << 4; 149 state = 2; 150 break; 151 case 2: 152 target[target.length() - 1] |= pos >> 2; 153 target += (pos & 0x03) << 6; 154 state = 3; 155 break; 156 case 3: 157 target[target.length() - 1] |= pos; 158 state = 0; 159 } 160 } 161 if (!target.empty() && !target[target.length() - 1]) 162 target.erase(target.length() - 1); 163 }