pion-net
4.0.9
|
00001 // ----------------------------------------------------------------------- 00002 // pion-common: a collection of common libraries used by the Pion Platform 00003 // ----------------------------------------------------------------------- 00004 // Copyright (C) 2007-2011 Atomic Labs, Inc. (http://www.atomiclabs.com) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #include <cstdlib> 00011 #include <cstdio> 00012 #include <pion/PionAlgorithms.hpp> 00013 #include <boost/assert.hpp> 00014 00015 namespace pion { // begin namespace pion 00016 00017 00018 bool algo::base64_decode(const std::string &input, std::string &output) 00019 { 00020 static const char nop = -1; 00021 static const char decoding_data[] = { 00022 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00023 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00024 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop, 62, nop,nop,nop, 63, 00025 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,nop,nop, nop,nop,nop,nop, 00026 nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 00027 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,nop, nop,nop,nop,nop, 00028 nop,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 00029 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,nop, nop,nop,nop,nop, 00030 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00031 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00032 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00033 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00034 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00035 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00036 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, 00037 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop 00038 }; 00039 00040 unsigned int input_length=input.size(); 00041 const char * input_ptr = input.data(); 00042 00043 // allocate space for output string 00044 output.clear(); 00045 output.reserve(((input_length+2)/3)*4); 00046 00047 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by droping first two bits 00048 // and regenerate into 3 8-bits sequence 00049 00050 for (unsigned int i=0; i<input_length;i++) { 00051 char base64code0; 00052 char base64code1; 00053 char base64code2 = 0; // initialized to 0 to suppress warnings 00054 char base64code3; 00055 00056 base64code0 = decoding_data[static_cast<int>(input_ptr[i])]; 00057 if(base64code0==nop) // non base64 character 00058 return false; 00059 if(!(++i<input_length)) // we need at least two input bytes for first byte output 00060 return false; 00061 base64code1 = decoding_data[static_cast<int>(input_ptr[i])]; 00062 if(base64code1==nop) // non base64 character 00063 return false; 00064 00065 output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); 00066 00067 if(++i<input_length) { 00068 char c = input_ptr[i]; 00069 if(c =='=') { // padding , end of input 00070 BOOST_ASSERT( (base64code1 & 0x0f)==0); 00071 return true; 00072 } 00073 base64code2 = decoding_data[static_cast<int>(input_ptr[i])]; 00074 if(base64code2==nop) // non base64 character 00075 return false; 00076 00077 output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f); 00078 } 00079 00080 if(++i<input_length) { 00081 char c = input_ptr[i]; 00082 if(c =='=') { // padding , end of input 00083 BOOST_ASSERT( (base64code2 & 0x03)==0); 00084 return true; 00085 } 00086 base64code3 = decoding_data[static_cast<int>(input_ptr[i])]; 00087 if(base64code3==nop) // non base64 character 00088 return false; 00089 00090 output += (((base64code2 << 6) & 0xc0) | base64code3 ); 00091 } 00092 00093 } 00094 00095 return true; 00096 } 00097 00098 bool algo::base64_encode(const std::string &input, std::string &output) 00099 { 00100 static const char encoding_data[] = 00101 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00102 00103 unsigned int input_length=input.size(); 00104 const char * input_ptr = input.data(); 00105 00106 // allocate space for output string 00107 output.clear(); 00108 output.reserve(((input_length+2)/3)*4); 00109 00110 // for each 3-bytes sequence from the input, extract 4 6-bits sequences and encode using 00111 // encoding_data lookup table. 00112 // if input do not contains enough chars to complete 3-byte sequence,use pad char '=' 00113 for (unsigned int i=0; i<input_length;i++) { 00114 int base64code0=0; 00115 int base64code1=0; 00116 int base64code2=0; 00117 int base64code3=0; 00118 00119 base64code0 = (input_ptr[i] >> 2) & 0x3f; // 1-byte 6 bits 00120 output += encoding_data[base64code0]; 00121 base64code1 = (input_ptr[i] << 4 ) & 0x3f; // 1-byte 2 bits + 00122 00123 if (++i < input_length) { 00124 base64code1 |= (input_ptr[i] >> 4) & 0x0f; // 2-byte 4 bits 00125 output += encoding_data[base64code1]; 00126 base64code2 = (input_ptr[i] << 2) & 0x3f; // 2-byte 4 bits + 00127 00128 if (++i < input_length) { 00129 base64code2 |= (input_ptr[i] >> 6) & 0x03; // 3-byte 2 bits 00130 base64code3 = input_ptr[i] & 0x3f; // 3-byte 6 bits 00131 output += encoding_data[base64code2]; 00132 output += encoding_data[base64code3]; 00133 } else { 00134 output += encoding_data[base64code2]; 00135 output += '='; 00136 } 00137 } else { 00138 output += encoding_data[base64code1]; 00139 output += '='; 00140 output += '='; 00141 } 00142 } 00143 00144 return true; 00145 } 00146 00147 std::string algo::url_decode(const std::string& str) 00148 { 00149 char decode_buf[3]; 00150 std::string result; 00151 result.reserve(str.size()); 00152 00153 for (std::string::size_type pos = 0; pos < str.size(); ++pos) { 00154 switch(str[pos]) { 00155 case '+': 00156 // convert to space character 00157 result += ' '; 00158 break; 00159 case '%': 00160 // decode hexidecimal value 00161 if (pos + 2 < str.size()) { 00162 decode_buf[0] = str[++pos]; 00163 decode_buf[1] = str[++pos]; 00164 decode_buf[2] = '\0'; 00165 result += static_cast<char>( strtol(decode_buf, 0, 16) ); 00166 } else { 00167 // recover from error by not decoding character 00168 result += '%'; 00169 } 00170 break; 00171 default: 00172 // character does not need to be escaped 00173 result += str[pos]; 00174 } 00175 }; 00176 00177 return result; 00178 } 00179 00180 std::string algo::url_encode(const std::string& str) 00181 { 00182 char encode_buf[4]; 00183 std::string result; 00184 encode_buf[0] = '%'; 00185 result.reserve(str.size()); 00186 00187 // character selection for this algorithm is based on the following url: 00188 // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm 00189 00190 for (std::string::size_type pos = 0; pos < str.size(); ++pos) { 00191 switch(str[pos]) { 00192 default: 00193 if (str[pos] > 32 && str[pos] < 127) { 00194 // character does not need to be escaped 00195 result += str[pos]; 00196 break; 00197 } 00198 // else pass through to next case 00199 case ' ': 00200 case '$': case '&': case '+': case ',': case '/': case ':': 00201 case ';': case '=': case '?': case '@': case '"': case '<': 00202 case '>': case '#': case '%': case '{': case '}': case '|': 00203 case '\\': case '^': case '~': case '[': case ']': case '`': 00204 // the character needs to be encoded 00205 sprintf(encode_buf+1, "%.2X", (unsigned char)(str[pos])); 00206 result += encode_buf; 00207 break; 00208 } 00209 }; 00210 00211 return result; 00212 } 00213 00214 } // end namespace pion