1 #include "b64.h"
2 #include "chunk.h"
3 #include <assert.h>
4 #include "mrt/exception.h"
5
6 /* M-runtime for c++
7 * Copyright (C) 2005-2008 Vladimir Menshakov
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 using namespace mrt;
25
encode(std::string & dst,const mrt::Chunk & src,int linesize)26 void Base64::encode(std::string &dst, const mrt::Chunk &src, int linesize) {
27 const unsigned char * p_src = (const unsigned char *)src.get_ptr();
28 size_t size = src.get_size();
29 dst.clear();
30 int lost = 0;
31 while(size) {
32 //process next 3 bytes.
33 static const char *zoo = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
34 unsigned int src24 = 0;
35 for(int i = 0; i < 3; ++i) {
36 src24 <<= 8;
37 if (size) {
38 src24 |= *p_src++;
39 --size;
40 } else ++lost;
41 }
42 assert(lost < 3);
43 //LOG_DEBUG(("encode %08x [%d]", src24, lost));
44 dst += zoo[(src24 & 0xfc0000) >> 18];
45 dst += zoo[(src24 & 0x03f000) >> 12];
46 dst += lost > 1 ? '=': zoo[(src24 & 0x000fc0) >> 6 ];
47 dst += lost > 0 ? '=': zoo[(src24 & 0x00003f)];
48 }
49 }
50
decode(mrt::Chunk & dst,const std::string & src)51 void Base64::decode(mrt::Chunk &dst, const std::string &src) {
52 dst.set_size(3 * src.size() / 4);
53
54 unsigned char * p_dst = (unsigned char *)dst.get_ptr();
55 unsigned int p_idx = 0;
56
57 size_t size = src.size(), dst_size = dst.get_size();
58
59 unsigned int dst24 = 0;
60 int got = 0, padded = 0;
61 for(size_t i = 0; i < size; ++i) {
62 if (got < 4) {
63 //decode next char
64 char c = src[i];
65 //ABCDE FGHIJ KLMNO PQRST UVWXY Zabcd efghi jklmn opqrs tuvwx yz012 34567 89+/
66 if (c >= 'A' && c <= 'Z') {
67 dst24 = (dst24 << 6) | (c - 'A');
68 ++got;
69 } else if (c >= 'a' && c <= 'z') {
70 dst24 = (dst24 << 6) | (c - 'a' + 26);
71 ++got;
72 } else if (c >= '0' && c <= '9') {
73 dst24 = (dst24 << 6) | (c - '0' + 52);
74 ++got;
75 } else if (c == '+') {
76 dst24 = (dst24 << 6) | 62;
77 ++got;
78 } else if (c == '/') {
79 dst24 = (dst24 << 6) | 63;
80 ++got;
81 } else if (c == '=') {
82 dst24 <<= 6;
83 ++got;
84 ++padded;
85 }
86 if (got < 4)
87 continue;
88 }
89 //LOG_DEBUG(("storing %08x", dst24));
90 if (padded > 2)
91 throw_ex(("invalid padding used (%d)", padded));
92
93 assert(p_idx < dst_size);
94 p_dst[p_idx++] = dst24 >> 16;
95
96 if (padded < 2) {
97 assert(p_idx < dst_size);
98 p_dst[p_idx++] = (dst24 >> 8) & 0xff;
99 }
100
101 if (padded < 1) {
102 assert(p_idx < dst_size);
103 p_dst[p_idx++] = dst24 & 0xff;
104 }
105 dst24 = 0;
106 got = 0;
107
108 if (padded)
109 break;
110 }
111 dst.set_size(p_idx);
112 }
113