Botan  1.10.9
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 
13 namespace Botan {
14 
15 /*
16 * Convert a string into an integer
17 */
18 u32bit 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 */
42 std::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 */
65 u32bit 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 */
96 std::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 */
152 std::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 */
180 std::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 */
213 bool 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  }
234 
235  if(!Charset::caseless_cmp(*p1, *p2))
236  return false;
237  ++p1;
238  ++p2;
239  }
240 
241  while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
242  while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
243 
244  if((p1 != name1.end()) || (p2 != name2.end()))
245  return false;
246  return true;
247  }
248 
249 /*
250 * Convert a decimal-dotted string to binary IP
251 */
252 u32bit string_to_ipv4(const std::string& str)
253  {
254  std::vector<std::string> parts = split_on(str, '.');
255 
256  if(parts.size() != 4)
257  throw Decoding_Error("Invalid IP string " + str);
258 
259  u32bit ip = 0;
260 
261  for(size_t i = 0; i != parts.size(); ++i)
262  {
263  u32bit octet = to_u32bit(parts[i]);
264 
265  if(octet > 255)
266  throw Decoding_Error("Invalid IP string " + str);
267 
268  ip = (ip << 8) | (octet & 0xFF);
269  }
270 
271  return ip;
272  }
273 
274 /*
275 * Convert an IP address to decimal-dotted string
276 */
277 std::string ipv4_to_string(u32bit ip)
278  {
279  std::string str;
280 
281  for(size_t i = 0; i != sizeof(ip); ++i)
282  {
283  if(i)
284  str += ".";
285  str += to_string(get_byte(i, ip));
286  }
287 
288  return str;
289  }
290 
291 }
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:96
bool x500_name_cmp(const std::string &name1, const std::string &name2)
Definition: parsing.cpp:213
bool caseless_cmp(char a, char b)
Definition: charset.cpp:193
BigInt n
Definition: numthry.cpp:26
std::string ipv4_to_string(u32bit ip)
Definition: parsing.cpp:277
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
unsigned char byte
Definition: types.h:22
unsigned long long u64bit
Definition: types.h:49
byte char2digit(char c)
Definition: charset.cpp:149
bool is_digit(char c)
Definition: charset.cpp:128
bool is_space(char c)
Definition: charset.cpp:139
u32bit timespec_to_u32bit(const std::string &timespec)
Definition: parsing.cpp:65
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
char digit2char(byte b)
Definition: charset.cpp:171
u32bit to_u32bit(const std::string &number)
Definition: parsing.cpp:18
unsigned int u32bit
Definition: types.h:32
OID oid
Definition: x509_ext.cpp:446
std::vector< u32bit > parse_asn1_oid(const std::string &oid)
Definition: parsing.cpp:180
u32bit string_to_ipv4(const std::string &str)
Definition: parsing.cpp:252