Botan
1.11.15
|
00001 /* 00002 * Various string utils and parsing functions 00003 * (C) 1999-2007,2013,2014 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/parsing.h> 00009 #include <botan/exceptn.h> 00010 #include <botan/charset.h> 00011 #include <botan/get_byte.h> 00012 #include <set> 00013 #include <stdexcept> 00014 00015 namespace Botan { 00016 00017 u32bit to_u32bit(const std::string& str) 00018 { 00019 try 00020 { 00021 return std::stoul(str, nullptr); 00022 } 00023 catch(std::exception&) 00024 { 00025 throw std::runtime_error("Could not read '" + str + "' as decimal string"); 00026 } 00027 } 00028 00029 /* 00030 * Convert a string into a time duration 00031 */ 00032 u32bit timespec_to_u32bit(const std::string& timespec) 00033 { 00034 if(timespec == "") 00035 return 0; 00036 00037 const char suffix = timespec[timespec.size()-1]; 00038 std::string value = timespec.substr(0, timespec.size()-1); 00039 00040 u32bit scale = 1; 00041 00042 if(Charset::is_digit(suffix)) 00043 value += suffix; 00044 else if(suffix == 's') 00045 scale = 1; 00046 else if(suffix == 'm') 00047 scale = 60; 00048 else if(suffix == 'h') 00049 scale = 60 * 60; 00050 else if(suffix == 'd') 00051 scale = 24 * 60 * 60; 00052 else if(suffix == 'y') 00053 scale = 365 * 24 * 60 * 60; 00054 else 00055 throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec); 00056 00057 return scale * to_u32bit(value); 00058 } 00059 00060 /* 00061 * Parse a SCAN-style algorithm name 00062 */ 00063 std::vector<std::string> parse_algorithm_name(const std::string& namex) 00064 { 00065 if(namex.find('(') == std::string::npos && 00066 namex.find(')') == std::string::npos) 00067 return std::vector<std::string>(1, namex); 00068 00069 std::string name = namex, substring; 00070 std::vector<std::string> elems; 00071 size_t level = 0; 00072 00073 elems.push_back(name.substr(0, name.find('('))); 00074 name = name.substr(name.find('(')); 00075 00076 for(auto i = name.begin(); i != name.end(); ++i) 00077 { 00078 char c = *i; 00079 00080 if(c == '(') 00081 ++level; 00082 if(c == ')') 00083 { 00084 if(level == 1 && i == name.end() - 1) 00085 { 00086 if(elems.size() == 1) 00087 elems.push_back(substring.substr(1)); 00088 else 00089 elems.push_back(substring); 00090 return elems; 00091 } 00092 00093 if(level == 0 || (level == 1 && i != name.end() - 1)) 00094 throw Invalid_Algorithm_Name(namex); 00095 --level; 00096 } 00097 00098 if(c == ',' && level == 1) 00099 { 00100 if(elems.size() == 1) 00101 elems.push_back(substring.substr(1)); 00102 else 00103 elems.push_back(substring); 00104 substring.clear(); 00105 } 00106 else 00107 substring += c; 00108 } 00109 00110 if(substring != "") 00111 throw Invalid_Algorithm_Name(namex); 00112 00113 return elems; 00114 } 00115 00116 std::vector<std::string> split_on(const std::string& str, char delim) 00117 { 00118 return split_on_pred(str, [delim](char c) { return c == delim; }); 00119 } 00120 00121 std::vector<std::string> split_on_pred(const std::string& str, 00122 std::function<bool (char)> pred) 00123 { 00124 std::vector<std::string> elems; 00125 if(str == "") return elems; 00126 00127 std::string substr; 00128 for(auto i = str.begin(); i != str.end(); ++i) 00129 { 00130 if(pred(*i)) 00131 { 00132 if(substr != "") 00133 elems.push_back(substr); 00134 substr.clear(); 00135 } 00136 else 00137 substr += *i; 00138 } 00139 00140 if(substr == "") 00141 throw Invalid_Argument("Unable to split string: " + str); 00142 elems.push_back(substr); 00143 00144 return elems; 00145 } 00146 00147 /* 00148 * Join a string 00149 */ 00150 std::string string_join(const std::vector<std::string>& strs, char delim) 00151 { 00152 std::string out = ""; 00153 00154 for(size_t i = 0; i != strs.size(); ++i) 00155 { 00156 if(i != 0) 00157 out += delim; 00158 out += strs[i]; 00159 } 00160 00161 return out; 00162 } 00163 00164 /* 00165 * Parse an ASN.1 OID string 00166 */ 00167 std::vector<u32bit> parse_asn1_oid(const std::string& oid) 00168 { 00169 std::string substring; 00170 std::vector<u32bit> oid_elems; 00171 00172 for(auto i = oid.begin(); i != oid.end(); ++i) 00173 { 00174 char c = *i; 00175 00176 if(c == '.') 00177 { 00178 if(substring == "") 00179 throw Invalid_OID(oid); 00180 oid_elems.push_back(to_u32bit(substring)); 00181 substring.clear(); 00182 } 00183 else 00184 substring += c; 00185 } 00186 00187 if(substring == "") 00188 throw Invalid_OID(oid); 00189 oid_elems.push_back(to_u32bit(substring)); 00190 00191 if(oid_elems.size() < 2) 00192 throw Invalid_OID(oid); 00193 00194 return oid_elems; 00195 } 00196 00197 /* 00198 * X.500 String Comparison 00199 */ 00200 bool x500_name_cmp(const std::string& name1, const std::string& name2) 00201 { 00202 auto p1 = name1.begin(); 00203 auto p2 = name2.begin(); 00204 00205 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; 00206 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; 00207 00208 while(p1 != name1.end() && p2 != name2.end()) 00209 { 00210 if(Charset::is_space(*p1)) 00211 { 00212 if(!Charset::is_space(*p2)) 00213 return false; 00214 00215 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; 00216 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; 00217 00218 if(p1 == name1.end() && p2 == name2.end()) 00219 return true; 00220 } 00221 00222 if(!Charset::caseless_cmp(*p1, *p2)) 00223 return false; 00224 ++p1; 00225 ++p2; 00226 } 00227 00228 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; 00229 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; 00230 00231 if((p1 != name1.end()) || (p2 != name2.end())) 00232 return false; 00233 return true; 00234 } 00235 00236 /* 00237 * Convert a decimal-dotted string to binary IP 00238 */ 00239 u32bit string_to_ipv4(const std::string& str) 00240 { 00241 std::vector<std::string> parts = split_on(str, '.'); 00242 00243 if(parts.size() != 4) 00244 throw Decoding_Error("Invalid IP string " + str); 00245 00246 u32bit ip = 0; 00247 00248 for(auto part = parts.begin(); part != parts.end(); ++part) 00249 { 00250 u32bit octet = to_u32bit(*part); 00251 00252 if(octet > 255) 00253 throw Decoding_Error("Invalid IP string " + str); 00254 00255 ip = (ip << 8) | (octet & 0xFF); 00256 } 00257 00258 return ip; 00259 } 00260 00261 /* 00262 * Convert an IP address to decimal-dotted string 00263 */ 00264 std::string ipv4_to_string(u32bit ip) 00265 { 00266 std::string str; 00267 00268 for(size_t i = 0; i != sizeof(ip); ++i) 00269 { 00270 if(i) 00271 str += "."; 00272 str += std::to_string(get_byte(i, ip)); 00273 } 00274 00275 return str; 00276 } 00277 00278 std::string erase_chars(const std::string& str, const std::set<char>& chars) 00279 { 00280 std::string out; 00281 00282 for(auto c: str) 00283 if(chars.count(c) == 0) 00284 out += c; 00285 00286 return out; 00287 } 00288 00289 std::string replace_chars(const std::string& str, 00290 const std::set<char>& chars, 00291 char to_char) 00292 { 00293 std::string out = str; 00294 00295 for(size_t i = 0; i != out.size(); ++i) 00296 if(chars.count(out[i])) 00297 out[i] = to_char; 00298 00299 return out; 00300 } 00301 00302 std::string replace_char(const std::string& str, char from_char, char to_char) 00303 { 00304 std::string out = str; 00305 00306 for(size_t i = 0; i != out.size(); ++i) 00307 if(out[i] == from_char) 00308 out[i] = to_char; 00309 00310 return out; 00311 } 00312 00313 }