E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gbase64.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gbase64.cpp
19 //
20
21 #include "gdef.h"
22 #include "gbase64.h"
23 #include "gassert.h"
24 #include "gstr.h"
25 #include <cstring>
26
27 namespace imp
28 {
29 const char * character_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
30 char pad = '=' ;
31
32 std::string encode( const std::string & s , const std::string & eol ) ;
33 std::string decode( const std::string & s , bool & error ) ;
34 bool valid( const std::string & ) ;
35
36 g_uint32_t numeric( char c ) ;
37 void accumulate_8( g_uint32_t & n , std::string::const_iterator & , std::string::const_iterator , int & ) ;
38 size_t hi_6( g_uint32_t n ) ;
39 void generate_6( g_uint32_t & n , int & i , std::string & result ) ;
40 char to_char( g_uint32_t n ) ;
41 size_t index( char c , bool & error ) ;
42 void accumulate_6( g_uint32_t & n , const std::string & , size_t & , size_t & , bool & error ) ;
43 g_uint32_t hi_8( g_uint32_t n ) ;
44 void generate_8( g_uint32_t & n , size_t & i , std::string & result , bool & error ) ;
45 }
46
47 std::string G::Base64::encode( const std::string & s_in )
48 {
49 return encode( s_in , "\015\012" ) ;
50 }
51
52 std::string G::Base64::encode( const std::string & s_in , const std::string & eol )
53 {
54 return imp::encode( s_in , eol ) ;
55 }
56
57 std::string G::Base64::decode( const std::string & s , bool strict )
58 {
59 bool error = false ;
60 std::string result = imp::decode( s , error ) ;
61 if( strict && error )
62 throw Error() ;
63 return result ;
64 }
65
66 bool G::Base64::valid( const std::string & s )
67 {
68 return imp::valid( s ) ;
69 }
70
71 // ==
72
73 g_uint32_t imp::numeric( char c )
74 {
75 return static_cast<g_uint32_t>( static_cast<unsigned char>(c) ) ;
76 }
77
78 void imp::accumulate_8( g_uint32_t & n , std::string::const_iterator & p ,
79 std::string::const_iterator end , int & i )
80 {
81 char c = p == end ? '\0' : *p ;
82 n <<= 8U ;
83 n |= numeric(c) ;
84 if( p != end )
85 {
86 ++p ;
87 ++i ;
88 }
89 }
90
91 size_t imp::hi_6( g_uint32_t n )
92 {
93 return (n >> 18U) & 0x3F ;
94 }
95
96 void imp::generate_6( g_uint32_t & n , int & i , std::string & result )
97 {
98 char c = i-- >= 0 ? character_map[hi_6(n)] : pad ;
99 result.append( 1U , c ) ;
100 n <<= 6U ;
101 }
102
103 std::string imp::encode( const std::string & s_in , const std::string & eol )
104 {
105 std::string result ;
106 size_t blocks = 0U ;
107 for( std::string::const_iterator p = s_in.begin() ; p != s_in.end() ; blocks++ )
108 {
109 if( blocks && (blocks % 19U) == 0U )
110 result.append( eol ) ;
111
112 g_uint32_t n = 0UL ;
113 int i = 0 ;
114 accumulate_8( n , p , s_in.end() , i ) ;
115 accumulate_8( n , p , s_in.end() , i ) ;
116 accumulate_8( n , p , s_in.end() , i ) ;
117 generate_6( n , i , result ) ;
118 generate_6( n , i , result ) ;
119 generate_6( n , i , result ) ;
120 generate_6( n , i , result ) ;
121 }
122
123 return result ;
124 }
125
126 char imp::to_char( g_uint32_t n )
127 {
128 return static_cast<char>(static_cast<unsigned char>(n)) ;
129 }
130
131 size_t imp::index( char c , bool & error )
132 {
133 const char * p = std::strchr( character_map , c ) ;
134 error = error || !c || !p ;
135 if( p == nullptr )
136 return 0U ;
137 else
138 return static_cast<size_t>( p - character_map ) ;
139 }
140
141 void imp::accumulate_6( g_uint32_t & n , const std::string & s , size_t & i , size_t & bits , bool & error )
142 {
143 n <<= 6U ;
144 if( i == s.length() )
145 {
146 }
147 else if( s.at(i) == pad )
148 {
149 i++ ;
150 }
151 else
152 {
153 n |= index( s.at(i++) , error ) ;
154 bits += 6U ;
155 }
156 }
157
158 g_uint32_t imp::hi_8( g_uint32_t n )
159 {
160 return (n >> 16U) & 0xff ;
161 }
162
163 void imp::generate_8( g_uint32_t & n , size_t & bits , std::string & result , bool & error )
164 {
165 if( bits >= 8U )
166 {
167 bits -= 8U ;
168 result.append( 1U , to_char(hi_8(n)) ) ;
169 n <<= 8U ;
170 }
171 else if( hi_8(n) )
172 {
173 error = true ;
174 }
175 }
176
177 std::string imp::decode( const std::string & s , bool & error )
178 {
179 std::string result ;
180 size_t i = 0U ;
181 for( const char * p = s.c_str() ; p[i] ; )
182 {
183 if( *p == '\r' || *p == '\n' )
184 {
185 p++ ;
186 continue ;
187 }
188
189 // four input characters encode 4*6 bits, so three output bytes
190 g_uint32_t n = 0UL ; // up to 24 bits
191 size_t bits = 0U ;
192 accumulate_6( n , s , i , bits , error ) ;
193 accumulate_6( n , s , i , bits , error ) ;
194 accumulate_6( n , s , i , bits , error ) ;
195 accumulate_6( n , s , i , bits , error ) ;
196 if( bits < 8U ) error = true ; // 6 bits cannot make a byte
197 generate_8( n , bits , result , error ) ;
198 generate_8( n , bits , result , error ) ;
199 generate_8( n , bits , result , error ) ;
200 }
201 return result ;
202 }
203
204 bool imp::valid( const std::string & s )
205 {
206 bool error = false ;
207 std::string result = decode( s , error ) ;
208 G_IGNORE_VARIABLE(result) ;
209 return !error ;
210 }
211
212 /// \file gbase64.cpp
G::Base64::valid
static bool valid(const std::string &)
Returns true if the string can be decoded without any strict errors.
Definition: gbase64.cpp:66
G::Base64::decode
static std::string decode(const std::string &, bool strict=false)
Decodes the given string.
Definition: gbase64.cpp:57
gstr.h
gassert.h
imp
Definition: gbase64.cpp:27
gbase64.h
G::Base64::encode
static std::string encode(const std::string &s, const std::string &line_break)
Encodes the given string.
Definition: gbase64.cpp:52