1 /*
2 * Copyright (C) 2009 by Dr. Marc Boris Duerner
3 * Copyright (C) 2009 by Tommi Meakitalo
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * As a special exception, you may use this file as part of a free
11 * software library without restriction. Specifically, if other files
12 * instantiate templates or use macros or inline functions from this
13 * file, or you compile this file and link it with other files to
14 * produce an executable, this file does not by itself cause the
15 * resulting executable to be covered by the GNU General Public
16 * License. This exception does not however invalidate any other
17 * reasons why the executable file might be covered by the GNU Library
18 * General Public License.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29 #include <cxxtools/xmlrpc/scanner.h>
30 #include <cxxtools/xml/startelement.h>
31 #include <cxxtools/xml/endelement.h>
32 #include <cxxtools/xml/characters.h>
33 #include <cxxtools/serializationinfo.h>
34 #include <cxxtools/serializationerror.h>
35 #include <cxxtools/deserializerbase.h>
36 #include <cxxtools/composer.h>
37
38 namespace cxxtools
39 {
40
41 namespace xmlrpc
42 {
43
44 namespace
45 {
throwSerializationError(const char * msg="invalid XML-RPC parameter")46 void throwSerializationError(const char* msg = "invalid XML-RPC parameter")
47 {
48 SerializationError::doThrow(msg);
49 }
50 }
51
begin(DeserializerBase & handler,IComposer & composer)52 void Scanner::begin(DeserializerBase& handler, IComposer& composer)
53 {
54 _state = OnParam;
55 _deserializer = &handler;
56 _composer = &composer;
57 _deserializer->begin();
58 }
59
advance(const cxxtools::xml::Node & node)60 bool Scanner::advance(const cxxtools::xml::Node& node)
61 {
62 switch(_state)
63 {
64 case OnParam:
65 {
66 if(node.type() == xml::Node::StartElement) // value
67 {
68 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
69
70 if(se.name() != L"value")
71 throwSerializationError();
72
73 _state = OnValueBegin;
74 }
75 else if(node.type() == xml::Node::EndElement)
76 {
77 throwSerializationError();
78 }
79
80 break;
81 }
82
83 case OnValueBegin:
84 {
85 if(node.type() == xml::Node::StartElement) // i4, struct, array...
86 {
87 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
88
89 if(se.name() == L"struct")
90 {
91 _state = OnStructBegin;
92 }
93 else if(se.name() == L"array")
94 {
95 _state = OnArrayBegin;
96 }
97 else
98 {
99 _state = OnScalarBegin;
100 }
101
102 _value.clear();
103 _type = se.name();
104 }
105 else if(node.type() == xml::Node::Characters)
106 {
107 // maybe <value>...<type>...</type>...</value> (case 1)
108 // or <value>...</value> (case 2)
109 const xml::Characters& chars = static_cast<const xml::Characters&>(node);
110 _value = chars.content();
111 }
112 else if(node.type() == xml::Node::EndElement)
113 {
114 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
115 if(ee.name() != L"value")
116 throwSerializationError();
117
118 // is always type string
119 _deserializer->setValue( _value );
120 _value.clear();
121
122 _state = OnValueEnd;
123 }
124 else
125 {
126 throwSerializationError();
127 }
128
129 break;
130 }
131
132 case OnValueEnd:
133 {
134 if(node.type() == xml::Node::EndElement)
135 {
136 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
137
138 if(ee.name() == L"member")
139 {
140 _deserializer->leaveMember();
141 _state = OnStructBegin;
142 }
143 else if(ee.name() == L"data")
144 {
145 _deserializer->leaveMember();
146 _state = OnDataEnd;
147 }
148 else if(ee.name() == L"param")
149 {
150 _composer->fixup(*_deserializer->si());
151 _state = OnValueEnd;
152 return true;
153 }
154 else if(ee.name() == L"fault")
155 {
156 _composer->fixup(*_deserializer->si());
157 _state = OnValueEnd;
158 return true;
159 }
160 else
161 {
162 throwSerializationError();
163 }
164 }
165 else if(node.type() == xml::Node::StartElement)
166 {
167 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
168 if(se.name() == L"value")
169 {
170 _deserializer->leaveMember();
171 _deserializer->beginMember(std::string(), _type.narrow(), SerializationInfo::Value);
172 _state = OnValueBegin;
173 }
174 else
175 {
176 throwSerializationError();
177 }
178 }
179
180 break;
181 }
182
183 case OnStructBegin:
184 {
185 if(node.type() == xml::Node::StartElement) // <member>
186 {
187 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
188
189 if(se.name() != L"member")
190 throwSerializationError();
191
192 _state = OnMemberBegin;
193 }
194 else if(node.type() == xml::Node::EndElement) // </struct>
195 {
196 _state = OnStructEnd;
197 }
198 break;
199 }
200
201 case OnStructEnd:
202 {
203 if(node.type() == xml::Node::EndElement) // </value>
204 {
205 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
206
207 if(ee.name() != L"value")
208 throwSerializationError();
209
210 _state = OnValueEnd;
211 }
212 else if(node.type() == xml::Node::StartElement)
213 {
214 throwSerializationError();
215 }
216
217 break;
218 }
219
220 case OnMemberBegin:
221 {
222 if(node.type() == xml::Node::StartElement) // name
223 {
224 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
225
226 if(se.name() != L"name")
227 throwSerializationError();
228
229 _state = OnNameBegin;
230 }
231 else if(node.type() == xml::Node::EndElement)
232 {
233 throwSerializationError();
234 }
235
236 break;
237 }
238
239 case OnNameBegin:
240 {
241 if(node.type() == xml::Node::Characters) // member-name
242 {
243 const xml::Characters& chars = static_cast<const xml::Characters&>(node);
244 const std::string& name = chars.content().narrow();
245
246 _deserializer->beginMember(name, std::string(), SerializationInfo::Object);
247
248 _state = OnName;
249 }
250 else
251 {
252 throwSerializationError();
253 }
254
255 break;
256 }
257
258 case OnName:
259 {
260 if(node.type() == xml::Node::EndElement) // </name>
261 {
262 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
263
264 if(ee.name() != L"name")
265 throwSerializationError();
266
267 _state = OnNameEnd;
268 }
269 else if(node.type() == xml::Node::StartElement)
270 {
271 throwSerializationError();
272 }
273
274 break;
275 }
276
277 case OnNameEnd:
278 {
279 if(node.type() == xml::Node::StartElement) // <value>
280 {
281 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
282
283 if(se.name() != L"value")
284 throwSerializationError();
285
286 _state = OnValueBegin;
287 }
288 else if(node.type() == xml::Node::EndElement)
289 {
290 throwSerializationError();
291 }
292
293 break;
294 }
295
296 case OnScalarBegin:
297 {
298 if(node.type() == xml::Node::Characters)
299 {
300 const xml::Characters& chars = static_cast<const xml::Characters&>(node);
301 _state = OnScalar;
302
303 _deserializer->setValue( chars.content() );
304 }
305 else if(node.type() == xml::Node::EndElement) // no content, for example empty strings
306 {
307
308 _deserializer->setValue( cxxtools::String() );
309 _state = OnScalarEnd;
310 }
311 else
312 {
313 throwSerializationError();
314 }
315
316 break;
317 }
318
319 case OnScalar:
320 {
321 if(node.type() == xml::Node::EndElement) // </int>, boolean ...
322 {
323 _state = OnScalarEnd;
324 }
325 else if(node.type() == xml::Node::StartElement)
326 {
327 throwSerializationError();
328 }
329
330 break;
331 }
332
333 case OnScalarEnd:
334 {
335 if(node.type() == xml::Node::EndElement) // </value>
336 {
337 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
338
339 if(ee.name() != L"value")
340 throwSerializationError();
341
342 _state = OnValueEnd;
343 }
344 else if(node.type() == xml::Node::StartElement)
345 {
346 throwSerializationError();
347 }
348
349 break;
350 }
351
352 case OnArrayBegin:
353 {
354 if(node.type() == xml::Node::StartElement) // <data>
355 {
356 const xml::StartElement& se = static_cast<const xml::StartElement&>(node);
357
358 if(se.name() != L"data")
359 throwSerializationError();
360
361 _state = OnDataBegin;
362 }
363 else if(node.type() == xml::Node::EndElement)
364 {
365 throwSerializationError();
366 }
367
368 break;
369 }
370
371 case OnDataBegin:
372 {
373 if(node.type() == xml::Node::StartElement) // value
374 {
375 _deserializer->beginMember(std::string(), std::string(), SerializationInfo::Array);
376 _state = OnValueBegin;
377 }
378 else if(node.type() == xml::Node::EndElement) // empty array
379 {
380 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
381 if(ee.name() != L"data")
382 throwSerializationError();
383
384 _state = OnDataEnd;
385 }
386
387 break;
388 }
389
390 case OnDataEnd:
391 {
392 if(node.type() == xml::Node::EndElement) // </array>
393 {
394 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
395
396 if(ee.name() != L"array")
397 throwSerializationError();
398
399 _state = OnArrayEnd;
400 }
401 else if(node.type() == xml::Node::StartElement)
402 {
403 throwSerializationError();
404 }
405
406 break;
407 }
408
409 case OnArrayEnd:
410 {
411 if(node.type() == xml::Node::EndElement) // </value>
412 {
413 const xml::EndElement& ee = static_cast<const xml::EndElement&>(node);
414
415 if(ee.name() != L"value")
416 throwSerializationError();
417
418 _state = OnValueEnd;
419 }
420 else if(node.type() == xml::Node::StartElement)
421 {
422 throwSerializationError();
423 }
424
425 break;
426 }
427 }
428
429 return false;
430 }
431
432 }
433
434 }
435