]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
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. | |
8 | * | |
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. | |
12 | * | |
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. | |
17 | * | |
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. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
64c7e76f | 25 | #include "base64.hh" |
bc712818 | 26 | #include <stdexcept> |
5fdd91db | 27 | #include <boost/scoped_array.hpp> |
f89adb9d CH |
28 | #include <openssl/bio.h> |
29 | #include <openssl/evp.h> | |
64c7e76f | 30 | |
65077d4d | 31 | template<typename Container> int B64Decode(const std::string& src, Container& dst) |
64c7e76f | 32 | { |
48836055 KM |
33 | if (src.empty() ) { |
34 | dst.clear(); | |
35 | return 0; | |
36 | } | |
bc712818 CH |
37 | int dlen = ( src.length() * 6 + 7 ) / 8 ; |
38 | ssize_t olen = 0; | |
65077d4d | 39 | dst.resize(dlen); |
f89adb9d CH |
40 | BIO *bio, *b64; |
41 | bio = BIO_new(BIO_s_mem()); | |
42 | BIO_write(bio, src.c_str(), src.length()); | |
43 | b64 = BIO_new(BIO_f_base64()); | |
44 | bio = BIO_push(b64, bio); | |
45 | BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); | |
65077d4d | 46 | olen = BIO_read(b64, &dst.at(0), dlen); |
bc712818 CH |
47 | if ((olen == 0 || olen == -1) && BIO_should_retry(bio)) { |
48 | BIO_free_all(bio); | |
49 | throw std::runtime_error("BIO_read failed to read all data from memory buffer"); | |
50 | } | |
f89adb9d CH |
51 | BIO_free_all(bio); |
52 | if (olen > 0) { | |
65077d4d | 53 | dst.resize(olen); |
48836055 KM |
54 | return 0; |
55 | } | |
56 | return -1; | |
64c7e76f BH |
57 | } |
58 | ||
65077d4d RG |
59 | template int B64Decode<std::string>(const std::string& strInput, std::string& strOutput); |
60 | ||
bc712818 | 61 | std::string Base64Encode(const std::string& src) |
64c7e76f | 62 | { |
48836055 | 63 | if (!src.empty()) { |
3dd164ab | 64 | size_t olen = 0; |
f89adb9d CH |
65 | BIO *bio, *b64; |
66 | b64 = BIO_new(BIO_f_base64()); | |
67 | bio = BIO_new(BIO_s_mem()); | |
68 | bio = BIO_push(b64, bio); | |
69 | BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); | |
bcc3fcf9 PL |
70 | int bioWriteRet = BIO_write(bio, src.c_str(), src.length()); |
71 | if (bioWriteRet < 0 || (size_t) bioWriteRet != src.length()) { | |
bc712818 CH |
72 | BIO_free_all(bio); |
73 | throw std::runtime_error("BIO_write failed to write all data to memory buffer"); | |
74 | } | |
75 | (void)BIO_flush(bio); | |
f89adb9d CH |
76 | char* pp; |
77 | std::string out; | |
78 | olen = BIO_get_mem_data(bio, &pp); | |
79 | if (olen > 0) { | |
80 | out = std::string(pp, olen); | |
81 | } | |
82 | BIO_free_all(bio); | |
83 | return out; | |
48836055 KM |
84 | } |
85 | return ""; | |
64c7e76f | 86 | } |
f89adb9d CH |
87 | |
88 | #if 0 | |
89 | #include <iostream> | |
90 | int main() { | |
91 | std::string in = "PowerDNS Test String 1"; | |
92 | std::string out = Base64Encode(in); | |
93 | std::cout << out << std::endl; | |
94 | if (out != "UG93ZXJETlMgVGVzdCBTdHJpbmcgMQ==") { | |
95 | std::cerr << "output did not match expected data" << std::endl; | |
96 | } | |
97 | std::string roundtrip; | |
98 | B64Decode(out, roundtrip); | |
99 | std::cout << roundtrip << std::endl; | |
100 | if (roundtrip != in) { | |
101 | std::cerr << "roundtripped data did not match input data" << std::endl; | |
102 | } | |
103 | return 0; | |
104 | } | |
105 | #endif |