diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llcommon/llbase32.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llbase32.cpp b/linden/indra/llcommon/llbase32.cpp new file mode 100644 index 0000000..711ba63 --- /dev/null +++ b/linden/indra/llcommon/llbase32.cpp | |||
@@ -0,0 +1,214 @@ | |||
1 | /** | ||
2 | * @file llbase32.cpp | ||
3 | * @brief base32 encoding that returns a std::string | ||
4 | * @author James Cook | ||
5 | * | ||
6 | * Based on code from bitter | ||
7 | * http://ghostwhitecrab.com/bitter/ | ||
8 | * | ||
9 | * Copyright (c) 2006 Christian Biere <christianbiere@gmx.de> | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * | ||
16 | * 1. Redistributions of source code must retain the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer. | ||
18 | * 2. Redistributions in binary form must reproduce the above copyright | ||
19 | * notice, this list of conditions and the following disclaimer in the | ||
20 | * documentation and/or other materials provided with the distribution. | ||
21 | * 3. Neither the name of the authors nor the names of its contributors | ||
22 | * may be used to endorse or promote products derived from this software | ||
23 | * without specific prior written permission. | ||
24 | * | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | ||
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
35 | * SUCH DAMAGE. | ||
36 | */ | ||
37 | |||
38 | #include "linden_common.h" | ||
39 | |||
40 | #include "llbase32.h" | ||
41 | |||
42 | #include <string> | ||
43 | |||
44 | // bitter - base32.c starts here | ||
45 | |||
46 | /* | ||
47 | * See RFC 3548 for details about Base 32 encoding: | ||
48 | * http://www.faqs.org/rfcs/rfc3548.html | ||
49 | */ | ||
50 | |||
51 | static const char base32_alphabet[32] = { | ||
52 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | ||
53 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | ||
54 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | ||
55 | 'Y', 'Z', '2', '3', '4', '5', '6', '7' | ||
56 | }; | ||
57 | |||
58 | size_t | ||
59 | base32_encode(char *dst, size_t size, const void *data, size_t len) | ||
60 | { | ||
61 | size_t i = 0; | ||
62 | const U8 *p = (const U8*)data; | ||
63 | const char *end = &dst[size]; | ||
64 | char *q = dst; | ||
65 | |||
66 | do { | ||
67 | size_t j, k; | ||
68 | U8 x[5]; | ||
69 | char s[8]; | ||
70 | |||
71 | switch (len - i) { | ||
72 | case 4: k = 7; break; | ||
73 | case 3: k = 5; break; | ||
74 | case 2: k = 3; break; | ||
75 | case 1: k = 2; break; | ||
76 | default: | ||
77 | k = 8; | ||
78 | } | ||
79 | |||
80 | for (j = 0; j < 5; j++) | ||
81 | x[j] = i < len ? p[i++] : 0; | ||
82 | |||
83 | /* | ||
84 | +-------+-----------+--------+ | ||
85 | | target| source | source | | ||
86 | | byte | bits | byte | | ||
87 | +-------+-----------+--------+ | ||
88 | | 0 | 7 6 5 4 3 | 0 | | ||
89 | | 1 | 2 1 0 7 6 | 0-1 | | ||
90 | | 2 | 5 4 3 2 1 | 1 | | ||
91 | | 3 | 0 7 6 5 4 | 1-2 | | ||
92 | | 4 | 3 2 1 0 7 | 2-3 | | ||
93 | | 5 | 6 5 4 3 2 | 3 | | ||
94 | | 6 | 1 0 7 6 5 | 3-4 | | ||
95 | | 7 | 4 3 2 1 0 | 4 | | ||
96 | +-------+-----------+--------+ | ||
97 | |||
98 | */ | ||
99 | |||
100 | s[0] = (x[0] >> 3); | ||
101 | s[1] = ((x[0] & 0x07) << 2) | (x[1] >> 6); | ||
102 | s[2] = (x[1] >> 1) & 0x1f; | ||
103 | s[3] = ((x[1] & 0x01) << 4) | (x[2] >> 4); | ||
104 | s[4] = ((x[2] & 0x0f) << 1) | (x[3] >> 7); | ||
105 | s[5] = (x[3] >> 2) & 0x1f; | ||
106 | s[6] = ((x[3] & 0x03) << 3) | (x[4] >> 5); | ||
107 | s[7] = x[4] & 0x1f; | ||
108 | |||
109 | for (j = 0; j < k && q != end; j++) | ||
110 | *q++ = base32_alphabet[(U8) s[j]]; | ||
111 | |||
112 | } while (i < len); | ||
113 | |||
114 | return q - dst; | ||
115 | } | ||
116 | |||
117 | /* *TODO: Implement base32 encode. | ||
118 | |||
119 | #define ARRAY_LEN(a) (sizeof (a) / sizeof((a)[0])) | ||
120 | |||
121 | static inline int | ||
122 | ascii_toupper(int c) | ||
123 | { | ||
124 | return c >= 97 && c <= 122 ? c - 32 : c; | ||
125 | } | ||
126 | |||
127 | static inline int | ||
128 | ascii_tolower(int c) | ||
129 | { | ||
130 | return c >= 65 && c <= 90 ? c + 32 : c; | ||
131 | } | ||
132 | |||
133 | |||
134 | static char base32_map[(unsigned char) -1]; | ||
135 | |||
136 | size_t | ||
137 | base32_decode(char *dst, size_t size, const void *data, size_t len) | ||
138 | { | ||
139 | const char *end = &dst[size]; | ||
140 | const unsigned char *p = data; | ||
141 | char *q = dst; | ||
142 | size_t i; | ||
143 | unsigned max_pad = 3; | ||
144 | |||
145 | if (0 == base32_map[0]) { | ||
146 | for (i = 0; i < ARRAY_LEN(base32_map); i++) { | ||
147 | const char *x; | ||
148 | |||
149 | x = memchr(base32_alphabet, ascii_toupper(i), sizeof base32_alphabet); | ||
150 | base32_map[i] = x ? (x - base32_alphabet) : (unsigned char) -1; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | for (i = 0; i < len && max_pad > 0; i++) { | ||
155 | unsigned char c; | ||
156 | char s[8]; | ||
157 | size_t j; | ||
158 | |||
159 | c = p[i]; | ||
160 | if ('=' == c) { | ||
161 | max_pad--; | ||
162 | c = 0; | ||
163 | } else { | ||
164 | c = base32_map[c]; | ||
165 | if ((unsigned char) -1 == c) { | ||
166 | return -1; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | j = i % ARRAY_LEN(s); | ||
171 | s[j] = c; | ||
172 | |||
173 | if (7 == j) { | ||
174 | char b[5]; | ||
175 | |||
176 | b[0] = ((s[0] << 3) & 0xf8) | ((s[1] >> 2) & 0x07); | ||
177 | b[1] = ((s[1] & 0x03) << 6) | ((s[2] & 0x1f) << 1) | ((s[3] >> 4) & 1); | ||
178 | b[2] = ((s[3] & 0x0f) << 4) | ((s[4] >> 1) & 0x0f); | ||
179 | b[3] = ((s[4] & 1) << 7) | ((s[5] & 0x1f) << 2) | ((s[6] >> 3) & 0x03); | ||
180 | b[4] = ((s[6] & 0x07) << 5) | (s[7] & 0x1f); | ||
181 | |||
182 | for (j = 0; j < ARRAY_LEN(b); j++) { | ||
183 | if (q != end) | ||
184 | *q = b[j]; | ||
185 | q++; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return q - dst; | ||
191 | } | ||
192 | */ | ||
193 | |||
194 | |||
195 | // static | ||
196 | std::string LLBase32::encode(const U8* input, size_t input_size) | ||
197 | { | ||
198 | std::string output; | ||
199 | if (input) | ||
200 | { | ||
201 | // Each 5 byte chunk of input is represented by an | ||
202 | // 8 byte chunk of output. | ||
203 | size_t input_chunks = (input_size + 4) / 5; | ||
204 | size_t output_size = input_chunks * 8; | ||
205 | |||
206 | output.resize(output_size); | ||
207 | |||
208 | size_t encoded = base32_encode(&output[0], output_size, input, input_size); | ||
209 | |||
210 | llinfos << "encoded " << encoded << " into buffer of size " << output_size | ||
211 | << llendl; | ||
212 | } | ||
213 | return output; | ||
214 | } | ||