Botan 1.10.17
parsing.cpp
Go to the documentation of this file.
1/*
2* Parser Functions
3* (C) 1999-2007 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/parsing.h>
9#include <botan/exceptn.h>
10#include <botan/charset.h>
11#include <botan/get_byte.h>
12
13namespace Botan {
14
15/*
16* Convert a string into an integer
17*/
18u32bit to_u32bit(const std::string& number)
19 {
20 u32bit n = 0;
21
22 for(std::string::const_iterator i = number.begin(); i != number.end(); ++i)
23 {
24 const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10;
25
26 if(*i == ' ')
27 continue;
28
29 byte digit = Charset::char2digit(*i);
30
31 if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5))
32 throw Decoding_Error("to_u32bit: Integer overflow");
33 n *= 10;
34 n += digit;
35 }
36 return n;
37 }
38
39/*
40* Convert an integer into a string
41*/
42std::string to_string(u64bit n, size_t min_len)
43 {
44 std::string lenstr;
45 if(n)
46 {
47 while(n > 0)
48 {
49 lenstr = Charset::digit2char(n % 10) + lenstr;
50 n /= 10;
51 }
52 }
53 else
54 lenstr = "0";
55
56 while(lenstr.size() < min_len)
57 lenstr = "0" + lenstr;
58
59 return lenstr;
60 }
61
62/*
63* Convert a string into a time duration
64*/
65u32bit timespec_to_u32bit(const std::string& timespec)
66 {
67 if(timespec == "")
68 return 0;
69
70 const char suffix = timespec[timespec.size()-1];
71 std::string value = timespec.substr(0, timespec.size()-1);
72
73 u32bit scale = 1;
74
75 if(Charset::is_digit(suffix))
76 value += suffix;
77 else if(suffix == 's')
78 scale = 1;
79 else if(suffix == 'm')
80 scale = 60;
81 else if(suffix == 'h')
82 scale = 60 * 60;
83 else if(suffix == 'd')
84 scale = 24 * 60 * 60;
85 else if(suffix == 'y')
86 scale = 365 * 24 * 60 * 60;
87 else
88 throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec);
89
90 return scale * to_u32bit(value);
91 }
92
93/*
94* Parse a SCAN-style algorithm name
95*/
96std::vector<std::string> parse_algorithm_name(const std::string& namex)
97 {
98 if(namex.find('(') == std::string::npos &&
99 namex.find(')') == std::string::npos)
100 return std::vector<std::string>(1, namex);
101
102 std::string name = namex, substring;
103 std::vector<std::string> elems;
104 size_t level = 0;
105
106 elems.push_back(name.substr(0, name.find('(')));
107 name = name.substr(name.find('('));
108
109 for(std::string::const_iterator i = name.begin(); i != name.end(); ++i)
110 {
111 char c = *i;
112
113 if(c == '(')
114 ++level;
115 if(c == ')')
116 {
117 if(level == 1 && i == name.end() - 1)
118 {
119 if(elems.size() == 1)
120 elems.push_back(substring.substr(1));
121 else
122 elems.push_back(substring);
123 return elems;
124 }
125
126 if(level == 0 || (level == 1 && i != name.end() - 1))
127 throw Invalid_Algorithm_Name(namex);
128 --level;
129 }
130
131 if(c == ',' && level == 1)
132 {
133 if(elems.size() == 1)
134 elems.push_back(substring.substr(1));
135 else
136 elems.push_back(substring);
137 substring.clear();
138 }
139 else
140 substring += c;
141 }
142
143 if(substring != "")
144 throw Invalid_Algorithm_Name(namex);
145
146 return elems;
147 }
148
149/*
150* Split the string on slashes
151*/
152std::vector<std::string> split_on(const std::string& str, char delim)
153 {
154 std::vector<std::string> elems;
155 if(str == "") return elems;
156
157 std::string substr;
158 for(std::string::const_iterator i = str.begin(); i != str.end(); ++i)
159 {
160 if(*i == delim)
161 {
162 if(substr != "")
163 elems.push_back(substr);
164 substr.clear();
165 }
166 else
167 substr += *i;
168 }
169
170 if(substr == "")
171 throw Invalid_Argument("Unable to split string: " + str);
172 elems.push_back(substr);
173
174 return elems;
175 }
176
177/*
178* Parse an ASN.1 OID string
179*/
180std::vector<u32bit> parse_asn1_oid(const std::string& oid)
181 {
182 std::string substring;
183 std::vector<u32bit> oid_elems;
184
185 for(std::string::const_iterator i = oid.begin(); i != oid.end(); ++i)
186 {
187 char c = *i;
188
189 if(c == '.')
190 {
191 if(substring == "")
192 throw Invalid_OID(oid);
193 oid_elems.push_back(to_u32bit(substring));
194 substring.clear();
195 }
196 else
197 substring += c;
198 }
199
200 if(substring == "")
201 throw Invalid_OID(oid);
202 oid_elems.push_back(to_u32bit(substring));
203
204 if(oid_elems.size() < 2)
205 throw Invalid_OID(oid);
206
207 return oid_elems;
208 }
209
210/*
211* X.500 String Comparison
212*/
213bool x500_name_cmp(const std::string& name1, const std::string& name2)
214 {
215 std::string::const_iterator p1 = name1.begin();
216 std::string::const_iterator p2 = name2.begin();
217
218 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
219 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
220
221 while(p1 != name1.end() && p2 != name2.end())
222 {
223 if(Charset::is_space(*p1))
224 {
225 if(!Charset::is_space(*p2))
226 return false;
227
228 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
229 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
230
231 if(p1 == name1.end() && p2 == name2.end())
232 return true;
233 if(p1 == name1.end() || p2 == name2.end())
234 return false;
235 }
236
237 if(!Charset::caseless_cmp(*p1, *p2))
238 return false;
239 ++p1;
240 ++p2;
241 }
242
243 while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
244 while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
245
246 if((p1 != name1.end()) || (p2 != name2.end()))
247 return false;
248 return true;
249 }
250
251/*
252* Convert a decimal-dotted string to binary IP
253*/
254u32bit string_to_ipv4(const std::string& str)
255 {
256 std::vector<std::string> parts = split_on(str, '.');
257
258 if(parts.size() != 4)
259 throw Decoding_Error("Invalid IP string " + str);
260
261 u32bit ip = 0;
262
263 for(size_t i = 0; i != parts.size(); ++i)
264 {
265 u32bit octet = to_u32bit(parts[i]);
266
267 if(octet > 255)
268 throw Decoding_Error("Invalid IP string " + str);
269
270 ip = (ip << 8) | (octet & 0xFF);
271 }
272
273 return ip;
274 }
275
276/*
277* Convert an IP address to decimal-dotted string
278*/
279std::string ipv4_to_string(u32bit ip)
280 {
281 std::string str;
282
283 for(size_t i = 0; i != sizeof(ip); ++i)
284 {
285 if(i)
286 str += ".";
287 str += to_string(get_byte(i, ip));
288 }
289
290 return str;
291 }
292
293}
bool is_space(char c)
Definition charset.cpp:139
byte char2digit(char c)
Definition charset.cpp:149
bool caseless_cmp(char a, char b)
Definition charset.cpp:193
char digit2char(byte b)
Definition charset.cpp:171
bool is_digit(char c)
Definition charset.cpp:128
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition parsing.cpp:96
std::vector< u32bit > parse_asn1_oid(const std::string &oid)
Definition parsing.cpp:180
std::string ipv4_to_string(u32bit ip)
Definition parsing.cpp:279
byte get_byte(size_t byte_num, T input)
Definition get_byte.h:21
u32bit string_to_ipv4(const std::string &str)
Definition parsing.cpp:254
unsigned long long u64bit
Definition types.h:49
std::string to_string(u64bit n, size_t min_len)
Definition parsing.cpp:42
u32bit to_u32bit(const std::string &number)
Definition parsing.cpp:18
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
bool x500_name_cmp(const std::string &name1, const std::string &name2)
Definition parsing.cpp:213
unsigned int u32bit
Definition types.h:32
u32bit timespec_to_u32bit(const std::string &timespec)
Definition parsing.cpp:65
std::vector< std::string > split_on(const std::string &str, char delim)
Definition parsing.cpp:152
Decoding_Error(const std::string &name)
Definition exceptn.h:140
Invalid_Algorithm_Name(const std::string &name)
Definition exceptn.h:121
Invalid_OID(const std::string &oid)
Definition exceptn.h:158