]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/base32.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "namespaces.hh"
34 /* based on freebsd:src/contrib/opie/libopie/btoe.c extract: get bit ranges from a char* */
35 /* NOTE: length should not exceed 8; all callers inside PowerDNS only pass length=5 though */
36 unsigned char extract_bits(const char *s
, int start
, int length
)
45 if(start
/ 8 < (start
+ length
-1)/8)
46 cc
= s
[start
/ 8 + 1];
50 x
= (uint16_t) (cl
<< 8 | cc
);
51 x
= x
>> (16 - (length
+ (start
% 8)));
52 x
= (x
& (0xffff >> (16 - length
)));
56 /* same, set bit ranges in a char* */
57 static void set_bits(char* s
, int x
, int start
, int length
)
59 unsigned char cl
, cc
, cr
;
63 shift
= ((8 - ((start
+ length
) % 8)) % 8);
64 y
= (uint32_t) x
<< shift
;
65 cl
= (y
>> 16) & 0xff;
68 if (shift
+ length
> 16) {
70 s
[start
/ 8 + 1] |= cc
;
71 s
[start
/ 8 + 2] |= cr
;
74 if (shift
+ length
> 8) {
76 s
[start
/ 8 + 1] |= cr
;
83 /* convert a base32 hex character to its decoded equivalent */
84 static int unbase32hex(char c
)
86 if(c
>= '0' && c
<='9')
88 if(c
>= 'a' && c
<='z')
90 if(c
>= 'A' && c
<='Z')
97 /* convert a binary string to base32hex */
98 string
toBase32Hex(const std::string
& input
)
100 static const char base32hex
[] = "0123456789abcdefghijklmnopqrstuv=";
102 ret
.reserve(4+ 8*input
.length()/5); // optimization
103 // process input in groups of 5 8-bit chunks, emit 8 5-bit chunks
104 for(string::size_type offset
= 0 ; offset
< input
.length(); offset
+=5) {
105 int todo
= input
.length() - offset
;
106 int stuffing
; // how much '=' to add at the end
117 default: // -> 0 or more than 5, no stuffing
121 for(int n
=0; n
< 8 - stuffing
; ++n
)
122 ret
.append(1, base32hex
[extract_bits(input
.c_str()+offset
, n
*5, 5)]);
123 ret
.append(stuffing
, '=');
129 // convert base32hex encoded string to normal string
130 string
fromBase32Hex(const std::string
& input
)
133 char block
[5]={0,0,0,0,0}; // we process 5 8-bit chunks at a time
134 string::size_type n
, toWrite
=0;
135 for(n
= 0; n
< input
.length(); ++n
) {
136 int c
=unbase32hex(input
[n
]);
137 if(c
== '=' || c
< 0) // stop at stuffing or error
139 set_bits(block
, c
, (n
% 8) * 5, 5);
141 ret
.append(block
, sizeof(block
));
142 memset(block
, 0, sizeof(block
));
146 ret
.append(block
, (toWrite
*5)/8);
152 int main(int argc
, char **argv
)
154 if(argc
!=3 || (argc
==3 && strcmp(argv
[1],"from") && strcmp(argv
[1],"to"))) {
155 printf("syntax: base32 from|to string\n");
158 if(!strcmp(argv
[1],"to")) {
159 printf("input: '%s'\noutput: '%s'\n",
161 toBase32Hex(argv
[2]).c_str());
164 cout
<<"input: '"<<argv
[2]<<"'\noutput: '"<<fromBase32Hex(argv
[2])<<"'\n";