1 | // |
2 | // Base64Encoder.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Streams |
6 | // Module: Base64 |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Base64Encoder.h" |
16 | |
17 | |
18 | namespace Poco { |
19 | |
20 | |
21 | const unsigned char Base64EncoderBuf::OUT_ENCODING[64] = |
22 | { |
23 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
24 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', |
25 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
26 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', |
27 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', |
28 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
29 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', |
30 | '4', '5', '6', '7', '8', '9', '+', '/' |
31 | }; |
32 | |
33 | |
34 | const unsigned char Base64EncoderBuf::OUT_ENCODING_URL[64] = |
35 | { |
36 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
37 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', |
38 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
39 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', |
40 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', |
41 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
42 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', |
43 | '4', '5', '6', '7', '8', '9', '-', '_' |
44 | }; |
45 | |
46 | |
47 | Base64EncoderBuf::Base64EncoderBuf(std::ostream& ostr, int options): |
48 | _options(options), |
49 | _groupLength(0), |
50 | _pos(0), |
51 | _lineLength((options & BASE64_URL_ENCODING) ? 0 : 72), |
52 | _buf(*ostr.rdbuf()), |
53 | _pOutEncoding((options & BASE64_URL_ENCODING) ? OUT_ENCODING_URL : OUT_ENCODING) |
54 | { |
55 | } |
56 | |
57 | |
58 | Base64EncoderBuf::~Base64EncoderBuf() |
59 | { |
60 | try |
61 | { |
62 | close(); |
63 | } |
64 | catch (...) |
65 | { |
66 | } |
67 | } |
68 | |
69 | |
70 | void Base64EncoderBuf::setLineLength(int lineLength) |
71 | { |
72 | _lineLength = lineLength; |
73 | } |
74 | |
75 | |
76 | int Base64EncoderBuf::getLineLength() const |
77 | { |
78 | return _lineLength; |
79 | } |
80 | |
81 | |
82 | int Base64EncoderBuf::writeToDevice(char c) |
83 | { |
84 | static const int eof = std::char_traits<char>::eof(); |
85 | |
86 | _group[_groupLength++] = (unsigned char) c; |
87 | if (_groupLength == 3) |
88 | { |
89 | unsigned char idx; |
90 | idx = _group[0] >> 2; |
91 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
92 | idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); |
93 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
94 | idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); |
95 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
96 | idx = _group[2] & 0x3F; |
97 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
98 | _pos += 4; |
99 | if (_lineLength > 0 && _pos >= _lineLength) |
100 | { |
101 | if (_buf.sputc('\r') == eof) return eof; |
102 | if (_buf.sputc('\n') == eof) return eof; |
103 | _pos = 0; |
104 | } |
105 | _groupLength = 0; |
106 | } |
107 | return charToInt(c); |
108 | } |
109 | |
110 | |
111 | int Base64EncoderBuf::close() |
112 | { |
113 | static const int eof = std::char_traits<char>::eof(); |
114 | |
115 | if (sync() == eof) return eof; |
116 | if (_groupLength == 1) |
117 | { |
118 | _group[1] = 0; |
119 | unsigned char idx; |
120 | idx = _group[0] >> 2; |
121 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
122 | idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); |
123 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
124 | if (!(_options & BASE64_NO_PADDING)) |
125 | { |
126 | if (_buf.sputc('=') == eof) return eof; |
127 | if (_buf.sputc('=') == eof) return eof; |
128 | } |
129 | } |
130 | else if (_groupLength == 2) |
131 | { |
132 | _group[2] = 0; |
133 | unsigned char idx; |
134 | idx = _group[0] >> 2; |
135 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
136 | idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); |
137 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
138 | idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); |
139 | if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; |
140 | if (!(_options & BASE64_NO_PADDING)) |
141 | { |
142 | if (_buf.sputc('=') == eof) return eof; |
143 | } |
144 | } |
145 | _groupLength = 0; |
146 | return _buf.pubsync(); |
147 | } |
148 | |
149 | |
150 | Base64EncoderIOS::Base64EncoderIOS(std::ostream& ostr, int options): _buf(ostr, options) |
151 | { |
152 | poco_ios_init(&_buf); |
153 | } |
154 | |
155 | |
156 | Base64EncoderIOS::~Base64EncoderIOS() |
157 | { |
158 | } |
159 | |
160 | |
161 | int Base64EncoderIOS::close() |
162 | { |
163 | return _buf.close(); |
164 | } |
165 | |
166 | |
167 | Base64EncoderBuf* Base64EncoderIOS::rdbuf() |
168 | { |
169 | return &_buf; |
170 | } |
171 | |
172 | |
173 | Base64Encoder::Base64Encoder(std::ostream& ostr, int options): Base64EncoderIOS(ostr, options), std::ostream(&_buf) |
174 | { |
175 | } |
176 | |
177 | |
178 | Base64Encoder::~Base64Encoder() |
179 | { |
180 | } |
181 | |
182 | |
183 | } // namespace Poco |
184 | |