1 | /* |
2 | Copyright (C) 1999-2007 The Botan Project. All rights reserved. |
3 | |
4 | Redistribution and use in source and binary forms, for any use, with or without |
5 | modification, is permitted provided that the following conditions are met: |
6 | |
7 | 1. Redistributions of source code must retain the above copyright notice, this |
8 | list of conditions, and the following disclaimer. |
9 | |
10 | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | this list of conditions, and the following disclaimer in the documentation |
12 | and/or other materials provided with the distribution. |
13 | |
14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED |
15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. |
17 | |
18 | IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, |
19 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
20 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
23 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | // LICENSEHEADER_END |
27 | namespace QCA { // WRAPNS_LINE |
28 | /************************************************* |
29 | * Parser Functions Source File * |
30 | * (C) 1999-2007 The Botan Project * |
31 | *************************************************/ |
32 | |
33 | } // WRAPNS_LINE |
34 | #include <botan/parsing.h> |
35 | namespace QCA { // WRAPNS_LINE |
36 | } // WRAPNS_LINE |
37 | #include <botan/exceptn.h> |
38 | namespace QCA { // WRAPNS_LINE |
39 | } // WRAPNS_LINE |
40 | #include <botan/charset.h> |
41 | namespace QCA { // WRAPNS_LINE |
42 | |
43 | namespace Botan { |
44 | |
45 | /************************************************* |
46 | * Convert a string into an integer * |
47 | *************************************************/ |
48 | #ifndef BOTAN_TOOLS_ONLY |
49 | u32bit to_u32bit(const std::string &number) |
50 | { |
51 | u32bit n = 0; |
52 | |
53 | for (std::string::const_iterator j = number.begin(); j != number.end(); ++j) { |
54 | const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10; |
55 | |
56 | byte digit = Charset::char2digit(*j); |
57 | |
58 | if ((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5)) |
59 | throw Decoding_Error("to_u32bit: Integer overflow" ); |
60 | n *= 10; |
61 | n += digit; |
62 | } |
63 | return n; |
64 | } |
65 | #endif |
66 | |
67 | /************************************************* |
68 | * Convert an integer into a string * |
69 | *************************************************/ |
70 | std::string to_string(u64bit n, u32bit min_len) |
71 | { |
72 | std::string lenstr; |
73 | if (n) { |
74 | while (n > 0) { |
75 | lenstr = Charset::digit2char(n % 10) + lenstr; // NOLINT(performance-inefficient-string-concatenation) |
76 | n /= 10; |
77 | } |
78 | } else |
79 | lenstr = "0" ; |
80 | |
81 | while (lenstr.size() < min_len) |
82 | lenstr = "0" + lenstr; // NOLINT(performance-inefficient-string-concatenation) |
83 | |
84 | return lenstr; |
85 | } |
86 | |
87 | #ifndef BOTAN_TOOLS_ONLY |
88 | /************************************************* |
89 | * Parse a SCAN-style algorithm name * |
90 | *************************************************/ |
91 | std::vector<std::string> parse_algorithm_name(const std::string &namex) |
92 | { |
93 | if (namex.find('(') == std::string::npos && namex.find(')') == std::string::npos) |
94 | return std::vector<std::string>(1, namex); |
95 | |
96 | std::string name = namex, substring; |
97 | std::vector<std::string> elems; |
98 | u32bit level = 0; |
99 | |
100 | elems.push_back(name.substr(0, name.find('('))); |
101 | name = name.substr(name.find('(')); |
102 | |
103 | for (std::string::const_iterator j = name.begin(); j != name.end(); ++j) { |
104 | char c = *j; |
105 | |
106 | if (c == '(') |
107 | ++level; |
108 | if (c == ')') { |
109 | if (level == 1 && j == name.end() - 1) { |
110 | if (elems.size() == 1) |
111 | elems.push_back(substring.substr(1)); |
112 | else |
113 | elems.push_back(substring); |
114 | return elems; |
115 | } |
116 | |
117 | if (level == 0 || (level == 1 && j != name.end() - 1)) |
118 | throw Invalid_Algorithm_Name(namex); |
119 | --level; |
120 | } |
121 | |
122 | if (c == ',' && level == 1) { |
123 | if (elems.size() == 1) |
124 | elems.push_back(substring.substr(1)); |
125 | else |
126 | elems.push_back(substring); |
127 | substring.clear(); |
128 | } else |
129 | substring += c; |
130 | } |
131 | |
132 | if (substring != "" ) |
133 | throw Invalid_Algorithm_Name(namex); |
134 | |
135 | return elems; |
136 | } |
137 | |
138 | /************************************************* |
139 | * Split the string on slashes * |
140 | *************************************************/ |
141 | std::vector<std::string> split_on(const std::string &str, char delim) |
142 | { |
143 | std::vector<std::string> elems; |
144 | if (str == "" ) |
145 | return elems; |
146 | |
147 | std::string substr; |
148 | for (std::string::const_iterator j = str.begin(); j != str.end(); ++j) { |
149 | if (*j == delim) { |
150 | if (substr != "" ) |
151 | elems.push_back(substr); |
152 | substr.clear(); |
153 | } else |
154 | substr += *j; |
155 | } |
156 | |
157 | if (substr == "" ) |
158 | throw Format_Error("Unable to split string: " + str); |
159 | elems.push_back(substr); |
160 | |
161 | return elems; |
162 | } |
163 | |
164 | /************************************************* |
165 | * Parse an ASN.1 OID string * |
166 | *************************************************/ |
167 | std::vector<u32bit> parse_asn1_oid(const std::string &oid) |
168 | { |
169 | std::string substring; |
170 | std::vector<u32bit> oid_elems; |
171 | |
172 | for (std::string::const_iterator j = oid.begin(); j != oid.end(); ++j) { |
173 | char c = *j; |
174 | |
175 | if (c == '.') { |
176 | if (substring == "" ) |
177 | throw Invalid_OID(oid); |
178 | oid_elems.push_back(to_u32bit(substring)); |
179 | substring.clear(); |
180 | } else |
181 | substring += c; |
182 | } |
183 | |
184 | if (substring == "" ) |
185 | throw Invalid_OID(oid); |
186 | oid_elems.push_back(to_u32bit(substring)); |
187 | |
188 | if (oid_elems.size() < 2) |
189 | throw Invalid_OID(oid); |
190 | |
191 | return oid_elems; |
192 | } |
193 | |
194 | /************************************************* |
195 | * X.500 String Comparison * |
196 | *************************************************/ |
197 | bool x500_name_cmp(const std::string &name1, const std::string &name2) |
198 | { |
199 | std::string::const_iterator p1 = name1.begin(); |
200 | std::string::const_iterator p2 = name2.begin(); |
201 | |
202 | while ((p1 != name1.end()) && Charset::is_space(*p1)) |
203 | ++p1; |
204 | while ((p2 != name2.end()) && Charset::is_space(*p2)) |
205 | ++p2; |
206 | |
207 | while (p1 != name1.end() && p2 != name2.end()) { |
208 | if (Charset::is_space(*p1)) { |
209 | if (!Charset::is_space(*p2)) |
210 | return false; |
211 | |
212 | while ((p1 != name1.end()) && Charset::is_space(*p1)) |
213 | ++p1; |
214 | while ((p2 != name2.end()) && Charset::is_space(*p2)) |
215 | ++p2; |
216 | |
217 | if (p1 == name1.end() && p2 == name2.end()) |
218 | return true; |
219 | } |
220 | |
221 | if (!Charset::caseless_cmp(*p1, *p2)) |
222 | return false; |
223 | ++p1; |
224 | ++p2; |
225 | } |
226 | |
227 | while ((p1 != name1.end()) && Charset::is_space(*p1)) |
228 | ++p1; |
229 | while ((p2 != name2.end()) && Charset::is_space(*p2)) |
230 | ++p2; |
231 | |
232 | if ((p1 != name1.end()) || (p2 != name2.end())) |
233 | return false; |
234 | return true; |
235 | } |
236 | |
237 | /************************************************* |
238 | * Parse and compute an arithmetic expression * |
239 | *************************************************/ |
240 | u32bit parse_expr(const std::string &expr) |
241 | { |
242 | const bool have_add = (expr.find('+') != std::string::npos); |
243 | const bool have_mul = (expr.find('*') != std::string::npos); |
244 | |
245 | if (have_add) { |
246 | std::vector<std::string> sub_expr = split_on(expr, '+'); |
247 | u32bit result = 0; |
248 | for (u32bit j = 0; j != sub_expr.size(); ++j) |
249 | result += parse_expr(sub_expr[j]); |
250 | return result; |
251 | } else if (have_mul) { |
252 | std::vector<std::string> sub_expr = split_on(expr, '*'); |
253 | u32bit result = 1; |
254 | for (u32bit j = 0; j != sub_expr.size(); ++j) |
255 | result *= parse_expr(sub_expr[j]); |
256 | return result; |
257 | } else |
258 | return to_u32bit(expr); |
259 | } |
260 | #endif |
261 | |
262 | } |
263 | } // WRAPNS_LINE |
264 | |