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