1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of a Qt Solutions component.
8 **
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Solutions Commercial License Agreement provided
12 ** with the Software or, alternatively, in accordance with the terms
13 ** contained in a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file.  Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file.  Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** Please note Third Party Software included with Qt Solutions may impose
37 ** additional restrictions and it is the user's responsibility to ensure
38 ** that they have met the licensing requirements of the GPL, LGPL, or Qt
39 ** Solutions Commercial license and the relevant license of the Third
40 ** Party Software they are using.
41 **
42 ** If you are unsure which license is appropriate for your use, please
43 ** contact Nokia at qt-info@nokia.com.
44 **
45 ****************************************************************************/
46 
47 #include "qtsoap.h"
48 #include <QtCore/QSet>
49 #include <QtNetwork/QNetworkRequest>
50 #include <QtNetwork/QNetworkReply>
51 
52 /*! \page qtsoap-overview.html
53 
54     \title Qt SOAP component
55 
56     \tableofcontents
57 
58     \target overview
59     \section1 Overview of the SOAP support in the QtSoap classes
60 
61     QtSoapMessage provides an interface for creating, inspecting and
62     modifying SOAP messages. It has convenience functions for
63     generating method requests and inspecting method response
64     messages, and also functions that provide easy access to SOAP
65     Fault messages.
66 
67     The QtSoapType class allows you to inspect SOAP messages with no
68     knowledge of XML or DOM. Header and body items are all derived
69     from QtSoapType, and through easy accessors and iterators, this
70     class and its derivatives make it easy to build arrays
71     (QtSoapArray), structs (QtSoapStruct) and simple types like
72     String, Integer and Boolean (QtSoapSimpleType).
73 
74     Finally, QtSoapHttpTransport provides a convenient way to submit
75     SOAP messages to a host via the HTTP protocol.
76 
77     \target classes
78     \section1 The SOAP classes
79 
80     \table
81     \header \i Class \i Short description
82     \row    \i \l QtSoapMessage
83 	    \i Represents a SOAP message
84     \row    \i \l QtSoapQName
85 	    \i Represents qualified names (QNames)
86     \row    \i \l QtSoapType
87 	    \i A superclass for all data constructs in a SOAP message.
88     \row    \i \l QtSoapArray
89 	    \i Represents a SOAP array
90     \row    \i \l QtSoapArrayIterator
91 	    \i Lets you iterate over all the values in a SOAP array
92     \row    \i \l QtSoapStruct
93 	    \i Represents a SOAP struct
94     \row    \i \l QtSoapStructIterator
95 	    \i Lets you iterate over all the values in a SOAP array
96     \row    \i \l QtSoapSimpleType
97 	    \i Represents simple SOAP types such as String, Integer and Boolean.
98     \row    \i \l QtSoapHttpTransport
99 	    \i Provides a method for transmitting SOAP messages to an
100 	    HTTP server and for getting the SOAP reply.
101     \endtable
102 
103     \target partial
104     \section1 Status of the SOAP component
105 
106     This is a partial implementation of the SOAP v1.1 protocol.
107 
108     \list
109     \i Server side SOAP is not supported.
110     \i References to values (id and href attributes) are not supported.
111     \i Only arrays with less than 5 dimensions are supported.
112     \i Namespaces for types are not checked. Only the type names are used.
113     \i The encodingStyle attribute is ignored. The serialization and
114        encoding rules from section 5 in the SOAP v1.1 specification are
115        assumed regardless of the value of the encodingStyle attribute.
116     \i QtSoapType does not have accessors for attributes, which means
117        for example that actor, mustUnderstand and so on are not
118        accessible in headers.
119     \i The SOAP root attribute is not supported.
120     \endlist
121 */
122 
123 namespace {
localName(const QString & tagName)124     QString localName(const QString &tagName)
125     {
126 	int pos;
127 	if ((pos = tagName.indexOf(':')))
128 	    return tagName.right(tagName.length() - pos - 1);
129 
130 	return tagName;
131     }
132 
prefix(const QString & tagName)133     QString prefix(const QString &tagName)
134     {
135 	int pos;
136 	if ((pos = tagName.indexOf(':')))
137 	    return tagName.left(pos);
138 
139 	return tagName;
140     }
141 
142 }
143 
144 /*! \class QtSoapQName qtsoap.h
145 
146     \brief The QtSoapQName class provides a wrapper for QNames (names with
147     namespaces).
148 
149     This class is used extensively in QtSoap to define and identify
150     header and body elements, including method and argument names.
151 
152     The QtSoapQName consists of a name and a URI. The URI is used as
153     the name's namespace, i.e. the name is qualified (hence 'Q'-Name)
154     by the URI. The name() and uri() functions return the QNames's
155     name and URI.
156 
157     The QtSoapQName can be empty. It can also have just a name with no
158     URI. Special handling is often applied to a QtSoapQName that has
159     no URI. Typically, if a QName with no namespace is used in an
160     element in a SOAP document that already has a default namespace
161     defined, then that namespace will be applied to the QName.
162 
163     \code
164     QtSoapMessage message;
165 
166     message.setMethod(QtSoapQName("sendMessage", "http://messenging.example.com/"));
167     message.addMethodArgument(QtSoapSimpleType(QtSoapQName("a"), 15));
168     \endcode
169 */
170 
171 
172 /*!
173     Constructs a QName. Sets the QName name to \a name and the URI to
174     \a uri.
175 */
QtSoapQName(const QString & name,const QString & uri)176 QtSoapQName::QtSoapQName(const QString &name, const QString &uri)
177     : n(name), nuri(uri)
178 {
179 }
180 
181 /*!
182     Destructs the QtSoapQName.
183 */
~QtSoapQName()184 QtSoapQName::~QtSoapQName()
185 {
186 }
187 
188 /*!
189     Returns QName's name.
190 */
name() const191 QString QtSoapQName::name() const
192 {
193     return n;
194 }
195 
196 /*!
197     Returns the QName's URI.
198 */
uri() const199 QString QtSoapQName::uri() const
200 {
201     return nuri;
202 }
203 
204 /*!
205     Sets the QName's name to \a s, and sets the URI to an empty string.
206 */
operator =(const QString & s)207 QtSoapQName &QtSoapQName::operator =(const QString &s)
208 {
209     n = s;
210     nuri = "";
211 
212     return *this;
213 }
214 
215 /*!
216     \fn bool operator==(const QtSoapQName &s1, const QtSoapQName &s2)
217 
218     \relates QtSoapQName
219 
220     If \a s2 has a non-empty URI, this function returns true if the
221     merge of the URI and the name of \a s1 is equal to that of \a s2;
222     otherwise it returns false.
223 
224     If \a s2 has an empty URI, this function returns true if the name
225     of \a s1 is equal to the name of \a s2; otherwise it returns false.
226 
227     The comparison is case-insensitive.
228 */
operator ==(const QtSoapQName & s1,const QtSoapQName & s2)229 bool operator ==(const QtSoapQName &s1, const QtSoapQName &s2)
230 {
231     if (s2.uri() == "")
232 	return s1.name().toLower() == s2.name().toLower();
233 
234     return s1.name().toLower() == s2.name().toLower()
235 	  && s1.uri().toLower() == s2.uri().toLower();
236 }
237 
238 /*!
239     \fn bool operator<(const QtSoapQName &s1, const QtSoapQName &s2)
240 
241     \relates QtSoapQName
242 
243     If \a s2 has a non-empty URI, this function returns true if the
244     merge of the URI and the name of \a s1 is lexically less than that
245     of \a s2; otherwise it returns false.
246 
247     If \a s2 has an empty URI, this function returns true if the name
248     of \a s1 is lexically less than the name of \a s2; otherwise
249     it returns false.
250 
251     The comparison is case-insensitive.
252 */
operator <(const QtSoapQName & s1,const QtSoapQName & s2)253 bool operator <(const QtSoapQName &s1, const QtSoapQName &s2)
254 {
255     if (s2.uri() == "")
256 	return s1.name().toLower() < s2.name().toLower();
257 
258     return (s1.uri().toLower()+s1.name().toLower()) < (s2.uri().toLower()+s2.name().toLower());
259 }
260 
261 /*! \class QtSoapType qtsoap.h
262     \brief The QtSoapType class is the base class for all SOAP types
263     in QtSoap.
264 
265     Although it is not used to create data types, a QtSoapType
266     reference can be conveniently used to inspect a tree of QtSoapType
267     subclasses. Accessors from this base class, such as operator[](),
268     allow safe navigation.
269 
270     \code
271     const QtSoapType &root = message.returnValue();
272     if (root["fault"].isValid()) {
273 	qWarning("Warning: %s", root["fault"]["faultstring"].toString().toLatin1().constData());
274     }
275     \endcode
276 
277     This class holds the name(), type(), id() and href() of all its
278     derived types.
279 
280     If a QtSoapType reference or pointer points to a QtSoapStruct, a
281     QtSoapArray or a QtSoapSimpleType, isValid() returns true.
282 
283     \sa QtSoapStruct, QtSoapArray, QtSoapSimpleType
284 */
285 
286 /*!
287     \class QtSoapStruct qtsoap.h
288     \brief The QtSoapStruct class is an implementation of the SOAP
289     struct type.
290 
291     A SOAP struct is a dictionary of QtSoapTypes where entries are
292     looked up by name. Entries in a struct can be of any QtSoapType
293     type, such as QtSoapArray, QtSoapStruct or QtSoapSimpleType.
294 
295     The struct can be created in several ways. parse() generates a
296     struct by analyzing a QDomNode. insert() is used to add items
297     manually.
298 
299     \code
300     QtSoapStruct myStruct(QtSoapQName("myStruct"));
301 
302     myStruct.insert(new QtSoapSimpleType(QtSoapQName("item1"), 5));
303     myStruct.insert(new QtSoapSimpleType(QtSoapQName("item2"), "hello"));
304     myStruct.insert(new QtSoapSimpleType(QtSoapQName("item3"), true));
305     \endcode
306 
307     Use the operator[]() or at() when looking up entries in a struct
308     by name. If the names are unknown, QtSoapStructIterator lets you
309     iterate through all the items.
310 
311     \code
312     QtSoapType &helloItem = myStruct["Hello"];
313     \endcode
314 
315     toDomElement() converts the QtSoapStruct to a DomElement.
316 
317     \sa QtSoapStructIterator, QtSoapType, QtSoapArray, QtSoapSimpleType
318 */
319 
320 /*! \class QtSoapStructIterator
321     \brief The QtSoapStructIterator class provides an iterator for
322     traversing the items in a QtSoapStruct.
323 
324     The iterator is created by passing a QtSoapStruct to the
325     constructor. It it not defined which item the iterator initially
326     will point to. Neither is the order in which the items are
327     processed.
328 
329     key() returns the name of the current item. data() and current()
330     return a pointer to the current item, or 0 if there is none.
331     operator++() navigates to the next item in the struct.
332 
333     \code
334     for (QtSoapStructIterator it(myStruct); it.current(); ++it) {
335 	QtSoapType *item = it.data();
336 	// process item
337     }
338     \endcode
339 
340     \sa QtSoapArrayIterator
341 */
342 
343 /*! \class QtSoapArray qtsoap.h
344     \brief The QtSoapArray class is an implementation of the SOAP
345     array type.
346 
347     A SOAP array is a sequence of QtSoapType objects such as
348     QtSoapArrays, QtSoapStructs or QtSoapSimpleTypes, and they are
349     accessible through their ordinal position. An array can be
350     consecutive (0, 1, 2, 3, ...) or sparse (1, 5, 6, 10, ...) and
351     they can be multidimensional ((0, 0), (0, 1), ...). QtSoapArray
352     supports arrays of up to 5 dimensions. The size and dimensions of
353     the array are set in the constructor. The default constructor
354     produces a one dimensional array, with an unset size, meaning that
355     the array can grow as required.
356 
357     All elements in a SOAP array must be of the same type. Inserting
358     different types will result in a run time error.
359 
360     The parse() function builds the array by analyzing a QDomNode from
361     a SOAP document. count() returns the number of items in the array.
362 
363     Retrieve items in the array with at() or operator[](). Note that
364     operator[]() only works with one dimensional arrays, but there are
365     at() functions for arrays of up to 5 dimensions.
366     QtSoapArrayIterator lets you iterate through all items in an
367     array.
368 
369     Use insert() or append() to insert items into an array manually.
370     append() only works with one dimensional arrays.
371 
372     toDomElement() returns a QDomElement representation of the SOAP
373     array.
374 
375     \code
376     QtSoapArray array;
377 
378     array.insert(0, new QtSoapSimpleType(QtSoapQName("Peter"), "peter"));
379     array.insert(1, new QtSoapSimpleType(QtSoapQName("Lisa"), "lisa"));
380     array.insert(2, new QtSoapSimpleType(QtSoapQName("Paul"), "paul"));
381     array.insert(3, new QtSoapSimpleType(QtSoapQName("Heather"), "heather"));
382     \endcode
383 
384     \sa QtSoapType, QtSoapStruct, QtSoapSimpleType
385 */
386 
387 /*! \class QtSoapArrayIterator qtsoap.h
388     \brief The QtSoapArrayIterator class provides an iterator for
389     traversing the items in a QtSoapArray.
390 
391     The items are traversed in ascending order of index position,
392     depth first.
393 
394     \code
395     // Construct a 2x2 array of Strings.
396     QtSoapArray array("Array of strings", String, 2, 2);
397     array.insert(0, 0, new QtSoapSimpleType(Q4SoapQName("top left"), "top left");
398     array.insert(0, 1, new QtSoapSimpleType(Q4SoapQName("top right"), "top right");
399     array.insert(1, 0, new QtSoapSimpleType(Q4SoapQName("bottom left"), "bottom left");
400     array.insert(1, 1, new QtSoapSimpleType(Q4SoapQName("bottom right"), "bottom right");
401 
402     // Traverse all items.
403     QtSoapArrayIterator it(array);
404     while (!it.current()) {
405 
406       // Find the position of the current element.
407       int pos1, pos2;
408       it.pos(&pos1, &pos2);
409 
410       qDebug() << "Position (" << pos1 << ", " << pos2 << ") is "
411                << "the " << it.current()->toString() << " coordinate of the grid." << endl;
412 
413       ++it;
414     }
415     \endcode
416 */
417 
418 /*! \class QtSoapSimpleType qtsoap.h
419     \brief The QtSoapSimpleType class provides a container for all
420     simple SOAP types, such as strings, integers and booleans.
421 
422 
423 
424     \sa QtSoapType, QtSoapStruct, QtSoapArray
425 */
426 
427 /*! \enum QtSoapType::Type
428 
429     SOAP supports the types described in XML Schema Part 2: Datatypes
430     listed at \l http://www.w3.org/TR/xmlschema-2/. The following
431     values are represented using QtSoapSimpleType, except where noted.
432 
433     \value AnyURI
434     \value Array Represented by QtSoapArray
435     \value Base64Binary
436     \value Boolean
437     \value Byte
438     \value Date
439     \value DateTime
440     \value Decimal
441     \value Double
442     \value Duration
443     \value ENTITY
444     \value Float
445     \value GDay
446     \value GMonth
447     \value GMonthDay
448     \value GYear
449     \value GYearMonth
450     \value HexBinary
451     \value ID
452     \value IDREF
453     \value Int
454     \value Integer
455     \value Language
456     \value Long
457     \value NCName
458     \value NMTOKEN
459     \value NOTATION
460     \value Name
461     \value NegativeInteger
462     \value NonNegativeInteger
463     \value NonPositiveInteger
464     \value NormalizedString
465     \value Other
466     \value PositiveInteger
467     \value QName
468     \value Short
469     \value String
470     \value Struct Represented by QtSoapStruct
471     \value Time
472     \value Token
473     \value UnsignedByte
474     \value UnsignedInt
475     \value UnsignedLong
476     \value UnsignedShort
477 */
478 
479 /*!
480     Constructs a QtSoapType.
481 */
QtSoapType()482 QtSoapType::QtSoapType()
483 {
484     t = Other;
485     errorStr = "Unknown error";
486 }
487 
488 /*!
489     Constructs a QtSoapType whose name is \a name and type is \a type.
490     This contructor is usually only called by constructors in
491     subclasses.
492 */
QtSoapType(const QtSoapQName & name,Type type)493 QtSoapType::QtSoapType(const QtSoapQName &name, Type type)
494     : t(type), n(name)
495 {
496     errorStr = "Unknown error";
497 }
498 
499 /*!
500     Creates a QtSoapType copy of \a copy.
501 */
QtSoapType(const QtSoapType & copy)502 QtSoapType::QtSoapType(const QtSoapType &copy)
503     : t(copy.t), errorStr(copy.errorStr), i(copy.i),
504       n(copy.n), u(copy.u), h(copy.h)
505 {
506 }
507 
508 /*!
509     Destructs a QtSoapType.
510 */
~QtSoapType()511 QtSoapType::~QtSoapType()
512 {
513 }
514 
515 /*!
516     Clears any contents. In this base implementation, clear() does
517     nothing.
518 */
clear()519 void QtSoapType::clear()
520 {
521 }
522 
523 /*!
524     Makes this QtSoapType equal to \a copy.
525 */
operator =(const QtSoapType & copy)526 QtSoapType &QtSoapType::operator =(const QtSoapType &copy)
527 {
528     t = copy.t;
529     errorStr = copy.errorStr;
530     i = copy.i;
531     n = copy.n;
532     u = copy.u;
533     h = copy.h;
534     return *this;
535 }
536 
537 /*!
538     Returns true if this object is of type QtSoapStruct, QtSoapArray
539     or QtSoapSimpletype; otherwise returns false.
540 */
isValid() const541 bool QtSoapType::isValid() const
542 {
543     return false;
544 }
545 
546 /*!
547     Returns the QString equivalent of type \a t.
548 */
typeToName(QtSoapType::Type t)549 QString QtSoapType::typeToName(QtSoapType::Type t)
550 {
551     switch (t) {
552     case Duration: return "duration";
553     case DateTime: return "dateTime";
554     case Time: return "time";
555     case Date: return "date";
556     case GYearMonth: return "gYearMonth";
557     case GYear: return "gYear";
558     case GMonthDay: return "gMonthDay";
559     case GDay: return "gDay";
560     case GMonth: return "gMonth";
561     case Boolean: return "boolean";
562     case Base64Binary: return "base64Binary";
563     case HexBinary: return "hexBinary";
564     case Float: return "float";
565     case Double: return "double";
566     case AnyURI: return "anyURI";
567     case QName: return "QName";
568     case NOTATION: return "NOTATION";
569     case String: return "string";
570     case NormalizedString: return "normalizedString";
571     case Token: return "token";
572     case Language: return "language";
573     case Name: return "name";
574     case NMTOKEN: return "NMToken";
575     case NCName: return "NCName";
576     case ID: return "ID";
577     case IDREF: return "IDREF";
578     case ENTITY: return "ENTITY";
579     case Decimal: return "decimal";
580     case Integer: return "integer";
581     case NonPositiveInteger: return "nonPositiveInteger";
582     case NegativeInteger: return "negativeInteger";
583     case Long: return "long";
584     case Int: return "int";
585     case Short: return "short";
586     case Byte: return "byte";
587     case NonNegativeInteger: return "nonNegativeInteger";
588     case UnsignedLong: return "unsignedLong";
589     case PositiveInteger: return "positiveInteger";
590     case UnsignedInt: return "unsignedInt";
591     case UnsignedShort: return "unsignedShort";
592     case UnsignedByte: return "unsignedByte";
593     case Array: return "array";
594     case Struct: return "struct";
595     default: return "other";
596     }
597 }
598 
599 /*!
600     Returns the QtSoapType::Type called \a name.
601 */
nameToType(const QString & name)602 QtSoapType::Type QtSoapType::nameToType(const QString &name)
603 {
604     const QString type = name.trimmed().toLower();
605 
606     if (type == "string")
607 	return String;
608     else if (type == "normalizedstring")
609 	return NormalizedString;
610     else if (type == "token")
611 	return Token;
612     else if (type == "language")
613 	return Language;
614     else if (type == "name")
615 	return Name;
616     else if (type == "ncname")
617 	return NCName;
618     else if (type == "nmtoken")
619 	return NMTOKEN;
620     else if (type == "id")
621 	return ID;
622     else if (type == "idref")
623 	return IDREF;
624     else if (type == "entity")
625 	return ENTITY;
626     else if (type == "base64binary")
627 	return Base64Binary;
628     else if (type == "hexBinary")
629 	return HexBinary;
630     else if (type == "anyuri")
631 	return AnyURI;
632     else if (type == "qname")
633 	return QName;
634     else if (type == "notation")
635 	return NOTATION;
636     else if (type == "duration")
637 	return Duration;
638     else if (type == "datetime")
639 	return DateTime;
640     else if (type == "time")
641 	return Time;
642     else if (type == "date")
643 	return Date;
644     else if (type == "gyearmonth")
645 	return GYearMonth;
646     else if (type == "gyear")
647 	return GYear;
648     else if (type == "gmonthday")
649 	return GMonthDay;
650     else if (type == "gday")
651 	return GDay;
652     else if (type == "gmonth")
653 	return GMonth;
654     else if (type == "decimal")
655 	return Decimal;
656     else if (type == "integer")
657 	return Integer;
658     else if (type == "nonPositiveinteger")
659 	return NonPositiveInteger;
660     else if (type == "negativeinteger")
661 	return NegativeInteger;
662     else if (type == "long")
663 	return Long;
664     else if (type == "int")
665 	return Int;
666     else if (type == "short")
667 	return Short;
668     else if (type == "byte")
669 	return Byte;
670     else if (type == "nonnegativeinteger")
671 	return NonNegativeInteger;
672     else if (type == "unsignedlong")
673 	return UnsignedLong;
674     else if (type == "unsignedint")
675 	return UnsignedInt;
676     else if (type == "unsignedshort")
677 	return UnsignedShort;
678     else if (type == "unsignedbyte")
679 	return UnsignedByte;
680     else if (type == "positiveinteger")
681 	return PositiveInteger;
682     else if (type == "float")
683 	return Float;
684     else if (type == "double")
685 	return Double;
686     else if (type == "boolean")
687 	return Boolean;
688     else
689 	return Other;
690 }
691 
692 /*!
693     Returns QString::null.
694 */
toString() const695 QString QtSoapType::toString() const
696 {
697     return QString::null;
698 }
699 
700 /*!
701     Returns 0.
702 */
toInt() const703 int QtSoapType::toInt() const
704 {
705     return 0;
706 }
707 
708 /*!
709     Returns false.
710 */
toBool() const711 bool QtSoapType::toBool() const
712 {
713     return false;
714 }
715 
716 /*!
717     Returns the QDomElement representation of this QtSoapType
718     as a child of \a document.
719 */
toDomElement(QDomDocument document) const720 QDomElement QtSoapType::toDomElement(QDomDocument document) const
721 {
722     Q_UNUSED(document);
723     return QDomElement();
724 }
725 
726 /*!
727     Returns the QString representation of this QtSoapType's type.
728 */
typeName() const729 QString QtSoapType::typeName() const
730 {
731     return QtSoapType::typeToName(type());
732 }
733 
734 /*!
735     Returns the type as a QtSoapType::Type.
736 */
type() const737 QtSoapType::Type QtSoapType::type() const
738 {
739     return t;
740 }
741 
742 /*!
743     Returns the QName (qualified name) of this QtSoapType.
744 */
name() const745 QtSoapQName QtSoapType::name() const
746 {
747     return n;
748 }
749 
750 /*!
751     Returns the ID of this QtSoapType.
752 */
id() const753 QString QtSoapType::id() const
754 {
755     return i;
756 }
757 
758 /*!
759     Returns the href attribute of this QtSoapType.
760 */
href() const761 QString QtSoapType::href() const
762 {
763     return h;
764 }
765 
766 /*!
767     Sets the QName (qualified name) of this QtSoapType to \a name.
768 */
setName(const QtSoapQName & name)769 void QtSoapType::setName(const QtSoapQName &name)
770 {
771     this->n = name;
772 }
773 
774 /*!
775     Sets the ID of this QtSoapType to \a i.
776 */
setId(const QString & i)777 void QtSoapType::setId(const QString &i)
778 {
779     this->i = i;
780 }
781 
782 /*!
783     Sets the href attribute of this QtSoapType to \a h.
784 */
setHref(const QString & h)785 void QtSoapType::setHref(const QString &h)
786 {
787     this->h = h;
788 }
789 
790 /*!
791     Returns the value of this QtSoapType. In the base implementation,
792     an invalid QVariant() is returned.
793 */
value() const794 QVariant QtSoapType::value() const
795 {
796     return QVariant();
797 }
798 
799 /*!
800     Returns a human readable explanation of the most recent error.
801 */
errorString() const802 QString QtSoapType::errorString() const
803 {
804     return errorStr;
805 }
806 
807 /*!
808     Returns the number of child items in this QtSoapType. In the base
809     implementation, this returns 0.
810 */
count() const811 int QtSoapType::count() const
812 {
813     return 0;
814 }
815 
816 /*!
817     Returns a reference to the child item at ordinal position \a pos.
818     If no item exists at this position, returns an empty QtSoapType.
819 */
operator [](int)820 QtSoapType &QtSoapType::operator [](int /* pos */ )
821 {
822     static QtSoapType NIL;
823     return NIL;
824 }
825 
826 /*!
827     \overload
828 
829     Returns a reference to the child item whose QName (qualified name)
830     is \a key. If no item exists with this key an empty QtSoapType is
831     returned.
832 */
operator [](const QtSoapQName &)833 QtSoapType &QtSoapType::operator [](const QtSoapQName & /* key */)
834 {
835     static QtSoapType NIL;
836     return NIL;
837 }
838 
839 /*!
840     \overload
841 
842     Returns a reference to the child item whose QName (qualified name)
843     is \a key, regardless of the qualified name's URI. If no item
844     exists with this key, an empty QtSoapType is returned.
845 */
operator [](const QString &)846 QtSoapType &QtSoapType::operator [](const QString & /* key */)
847 {
848     static QtSoapType NIL;
849     return NIL;
850 }
851 
852 /*!
853     \overload
854 
855     Returns a reference to the child item at ordinal position \a pos.
856     If no item exists at this position, returns an empty QtSoapType.
857 */
operator [](int) const858 const QtSoapType &QtSoapType::operator [](int /* pos */) const
859 {
860     static QtSoapType NIL;
861     return NIL;
862 }
863 
864 /*!
865     \overload
866 
867     Returns a reference to the child item whose QName (qualified name)
868     is \a key. If no item exists with this key, returns an empty
869     QtSoapType.
870 */
operator [](const QtSoapQName &) const871 const QtSoapType &QtSoapType::operator [](const QtSoapQName & /* key */) const
872 {
873     static QtSoapType NIL;
874     return NIL;
875 }
876 
877 /*!
878     \overload
879 
880     Returns a reference to the child item whose QName (qualified name)
881     is \a key, regardless of the qualified name's URI. If no item
882     exists with this key, returns an empty QtSoapType.
883 */
operator [](const QString &) const884 const QtSoapType &QtSoapType::operator [](const QString & /* key */) const
885 {
886     static QtSoapType NIL;
887     return NIL;
888 }
889 
890 /*!
891     Attempts to interpret \a node as a QtSoapType, and returns true if
892     successful. This base implementation always returns false.
893 */
parse(QDomNode)894 bool QtSoapType::parse(QDomNode /* node */)
895 {
896     return false;
897 }
898 
899 /*!
900     \overload
901 
902     Constructs an empty one dimensional QtSoapArray whose element type
903     is undefined. The first insert will decide what type of elements
904     the array can contain.
905 */
QtSoapArray()906 QtSoapArray::QtSoapArray()
907     : QtSoapType(QtSoapQName(), Array), arrayType(Other), order(1)
908 {
909     lastIndex = 0;
910     siz0 = 0;
911     siz1 = 0;
912     siz2 = 0;
913     siz3 = 0;
914     siz4 = 0;
915 }
916 
917 /*!
918     Constructs an empty QtSoapArray whose QName (qualified name) is \a
919     name, that contains elements of type \a type, and whose dimensions
920     are given by \a size0, \a size1, \a size2, \a size3 and \a size4.
921 
922     To construct a one dimensional array of size 5, set \a size0 = 5. To
923     create a two dimensional array of size 5x10, set \a size0 = 5 and \a
924     size1 = 10. The maximum dimension of a QtSoapArray is 5.
925 */
QtSoapArray(const QtSoapQName & name,QtSoapType::Type type,int size0,int size1,int size2,int size3,int size4)926 QtSoapArray::QtSoapArray(const QtSoapQName &name, QtSoapType::Type type, int size0,
927 			 int size1, int size2, int size3, int size4)
928     : QtSoapType(name, Array), lastIndex(0), arrayType(type),
929       siz0(size0), siz1(size1), siz2(size2), siz3(size3),
930       siz4(size4)
931 {
932     if (size4 != -1) order = 5;
933     else if (size3 != -1) order = 4;
934     else if (size2 != -1) order = 3;
935     else if (size1 != -1) order = 2;
936     else order = 1;
937 }
938 
939 /*!
940     Create a QtSoapArray that is a copy of \a copy.
941 */
QtSoapArray(const QtSoapArray & copy)942 QtSoapArray::QtSoapArray(const QtSoapArray &copy)
943     : QtSoapType(copy)
944 {
945     *this = copy;
946 }
947 
948 /*!
949     Destructs the QtSoapArray.
950 */
~QtSoapArray()951 QtSoapArray::~QtSoapArray()
952 {
953 }
954 
955 /*!
956     Clears the contents, and the dimensions of the QtSoapArray.
957 */
clear()958 void QtSoapArray::clear()
959 {
960     array.clear();
961     lastIndex = 0;
962     arrayType = Other;
963     siz0 = siz1 = siz2 = siz3 = siz4 = 0;
964     order = -1;
965 }
966 
967 /*!
968     Makes this QtSoapArray a copy of \a copy.
969 */
operator =(const QtSoapArray & copy)970 QtSoapArray &QtSoapArray::operator = (const QtSoapArray &copy)
971 {
972     if (this == &copy)
973         return *this;
974     t = copy.t;
975     errorStr = copy.errorStr;
976     i = copy.i;
977     n = copy.n;
978     u = copy.u;
979     h = copy.h;
980     lastIndex = copy.lastIndex;
981     order = copy.order;
982     siz0 = copy.siz0;
983     siz1 = copy.siz1;
984     siz2 = copy.siz2;
985     siz3 = copy.siz3;
986     siz4 = copy.siz4;
987     array = copy.array;
988 
989     return *this;
990 }
991 
992 /*!
993     Appends the QtSoapType \a item to the end of this array, which must
994     be one dimensional.
995 
996     \sa insert()
997 */
append(QtSoapType * item)998 void QtSoapArray::append(QtSoapType *item)
999 {
1000     if (order != 1) {
1001 	qWarning("Attempted to insert item at position (%i) in %i-dimensional QtSoapArray.",
1002 		 lastIndex, order);
1003 	return;
1004     }
1005 
1006     if (array.count() == 0) {
1007 	array.insert(0, item);
1008     } else {
1009 	array.insert(lastIndex + 1, item);
1010 	++lastIndex;
1011     }
1012 }
1013 
1014 /*!
1015     Inserts the QtSoapType \a item at the absolute position \a pos in
1016     the array. Note that this function can be used to insert items
1017     into arrays with any number of dimensions.
1018 
1019     If the array is one dimensional, then \a pos is simply the index
1020     position in the array. But if the array is multi-dimensional then
1021     \a pos is the absolute position. For example, if we have a two
1022     dimensional array [['a', 'b'], ['c', 'd'], ['e', 'f']], the
1023     element at position 0 is 'a', at position 1 is 'b', at position 2
1024     is 'c', and so on. (There are other insert() overloads that allow
1025     for each dimension to be specified individually.)
1026 */
insert(int pos,QtSoapType * item)1027 void QtSoapArray::insert(int pos, QtSoapType *item)
1028 {
1029     if (arrayType == Other)
1030 	arrayType = item->type();
1031 
1032     if (item->type() != arrayType) {
1033 	qWarning("Attempted to insert item of type \"%s\" in QtSoapArray of type \"%s\".",
1034 		 item->typeName().toLatin1().constData(), QtSoapType::typeToName(arrayType).toLatin1().constData());
1035 	return;
1036     }
1037 
1038     if (order == -1)
1039 	order = 1;
1040     else if (order == 1 && pos > lastIndex)
1041 	lastIndex = pos;
1042 
1043     array.insert(pos, item);
1044 }
1045 
1046 /*!
1047     \overload
1048 
1049     Insert the QtoSoapType \a item at position \a pos0 x \a pos1 in a
1050     two dimensional array.
1051 */
insert(int pos0,int pos1,QtSoapType * item)1052 void QtSoapArray::insert(int pos0, int pos1, QtSoapType *item)
1053 {
1054     if (order != 2) {
1055 	qWarning("Attempted to insert item at position (%i, %i)"
1056 		 " in %i-dimensional QtSoapArray.",
1057 		 pos0, pos1, order);
1058 	return;
1059     }
1060 
1061     if (pos0 < 0 || pos0 >= siz0 || pos1 < 0 || pos1 >= siz1) {
1062 	qWarning("Attempted to insert item at position (%i, %i)"
1063 		 " when range of QtSoapArray is (0..%i, 0..%i)",
1064 		 pos0, pos1, siz0 - 1, siz1 - 1);
1065 	return;
1066     }
1067 
1068     insert((pos0 * siz1) + pos1, item);
1069 }
1070 
1071 /*!
1072     \overload
1073 
1074     Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1075     pos2 in a three dimensional array.
1076 */
insert(int pos0,int pos1,int pos2,QtSoapType * item)1077 void QtSoapArray::insert(int pos0, int pos1, int pos2, QtSoapType *item)
1078 {
1079     if (order != 3) {
1080 	qWarning("Attempted to insert item at position (%i, %i, %i)"
1081 		 " in %i-dimensional QtSoapArray.",
1082 		 pos0, pos1, pos2, order);
1083 	return;
1084     }
1085 
1086     if (pos0 < 0 || pos0 >= siz0 || pos1 < 0 || pos1 >= siz1 || pos2 < 0 || pos2 >= siz2) {
1087 	qWarning("Attempted to insert item at position (%i, %i, %i)"
1088 		 " when range of QtSoapArray is (0..%i, 0..%i, 0..%i)",
1089 		 pos0, pos1, pos2, siz0 - 1, siz1 - 1, siz2 - 1);
1090 	return;
1091     }
1092 
1093     insert((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2, item);
1094 }
1095 
1096 /*!
1097     \overload
1098 
1099     Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1100     pos2 x \a pos3 in a four dimensional array.
1101 */
insert(int pos0,int pos1,int pos2,int pos3,QtSoapType * item)1102 void QtSoapArray::insert(int pos0, int pos1, int pos2, int pos3, QtSoapType *item)
1103 {
1104     if (order != 4) {
1105 	qWarning("Attempted to insert item at position (%i, %i, %i, %i)"
1106 		 " in %i-dimensional QtSoapArray.",
1107 		 pos0, pos1, pos2, pos3, order);
1108 	return;
1109     }
1110 
1111     insert((pos0 * siz3 * siz2 * siz1)
1112 	   + (pos1 * siz3 * siz2)
1113 	   + (pos2 * siz3)
1114 	   + pos3,
1115 	   item);
1116 }
1117 
1118 /*!
1119     \overload
1120 
1121     Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1122     pos2 x \a pos3 x \a pos4 in a five dimensional array.
1123 */
insert(int pos0,int pos1,int pos2,int pos3,int pos4,QtSoapType * item)1124 void QtSoapArray::insert(int pos0, int pos1, int pos2, int pos3, int pos4,
1125 			 QtSoapType *item)
1126 {
1127     if (order != 5) {
1128 	qWarning("Attempted to insert item at position (%i, %i, %i, %i, %i)"
1129 		 " in %i-dimensional QtSoapArray.",
1130 		 pos0, pos1, pos2, pos3, pos4, order);
1131 	return;
1132     }
1133 
1134     insert((pos0 * siz4 * siz3 * siz2 * siz1)
1135 	   + (pos1 * siz4 * siz3 * siz2)
1136 	   + (pos2 * siz4 * siz3)
1137 	   + (pos3 * siz4)
1138 	   + pos4,
1139 	   item);
1140 }
1141 
1142 /*! \internal
1143 
1144     Given the size and dimensions of the array, generates a string
1145     used to represent the array in XML. For example, a 1-dimensional
1146     array of size 5 would get [5], a 2-dimensional array of size 5x10
1147     would get [5,10].
1148 */
arraySizeString() const1149 QString QtSoapArray::arraySizeString() const
1150 {
1151     QString arraySize = "[";
1152     if (siz0 != -1) {
1153 	arraySize += QString::number(siz0);
1154 	if (order > 1) arraySize += "," + QString::number(siz1);
1155 	if (order > 2) arraySize += "," + QString::number(siz2);
1156 	if (order > 3) arraySize += "," + QString::number(siz3);
1157 	if (order > 4) arraySize += "," + QString::number(siz4);
1158     }
1159 
1160     arraySize += "]";
1161     return arraySize;
1162 }
1163 
1164 /*! \internal
1165 
1166     Recursively inspects the items and any child arrays' items to
1167     generate the aggregate type of items in this array. It the array
1168     contains ints, returns "int[5]", but if the array is of arrays of
1169     arrays of ints, the function returns "int[][][5]".
1170 */
arrayTypeString() const1171 QString QtSoapArray::arrayTypeString() const
1172 {
1173     if (arrayType != Array)
1174 	return QtSoapType::typeToName(arrayType);
1175 
1176     QString atString;
1177     QtSoapArray *ar = const_cast<QtSoapArray *>(this);
1178     do {
1179 	if (ar->count()	== 0)
1180 	    break;
1181 
1182 	atString += ar->arraySizeString();
1183 
1184 	QtSoapArrayIterator it(*const_cast<QtSoapArray *>(this));
1185 	if (it.data()->type() != Array)
1186 	    break;
1187 
1188 	ar = (QtSoapArray *)it.data();
1189     } while (ar);
1190 
1191 
1192     QtSoapArrayIterator it(*const_cast<QtSoapArray *>(this));
1193     if (ar->count() == 0)
1194 	atString = QtSoapSimpleType::typeToName(Int) + atString;
1195     else
1196 	atString = it.data()->typeName() + atString;
1197 
1198     return atString;
1199 }
1200 
1201 /*!
1202     Returns the QDomElement representation of this QtSoapArray. The
1203     returned QDomElement is created using \a doc.
1204 */
toDomElement(QDomDocument doc) const1205 QDomElement QtSoapArray::toDomElement(QDomDocument doc) const
1206 {
1207     QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
1208     QDomElement a = n.uri() == ""
1209 		    ? doc.createElement( n.name())
1210 		    : doc.createElementNS(n.uri(), prefix + ":" + n.name());
1211 
1212     QString schemaprefix = QtSoapNamespaces::instance().prefixFor(XML_SCHEMA_INSTANCE);
1213     a.setAttributeNS(XML_SCHEMA_INSTANCE, schemaprefix + ":type", "xsd:Array");
1214 
1215     QString encprefix = QtSoapNamespaces::instance().prefixFor(SOAPv11_ENCODING);
1216     a.setAttributeNS(SOAPv11_ENCODING, encprefix + ":arrayType", "xsd:" + arrayTypeString());
1217 
1218     for (QtSoapArrayIterator i(*const_cast<QtSoapArray *>(this)); !i.atEnd(); ++i) {
1219 	QDomElement item = i.data()->toDomElement(doc);
1220 	item.setTagName("item");
1221 
1222 	int pos0, pos1, pos2, pos3, pos4;
1223 	i.pos(&pos0, &pos1, &pos2, &pos3, &pos4);
1224 
1225 	QString position = "[" + QString::number(pos0);
1226 	if (order > 1) position += "," + QString::number(pos1);
1227 	if (order > 2) position += "," + QString::number(pos2);
1228 	if (order > 3) position += "," + QString::number(pos3);
1229 	if (order > 4) position += "," + QString::number(pos4);
1230 	position += "]";
1231 
1232 	QString envprefix = QtSoapNamespaces::instance().prefixFor(SOAPv11_ENVELOPE);
1233 	item.setAttributeNS(SOAPv11_ENVELOPE, envprefix + ":position", position);
1234 	a.appendChild(item);
1235     }
1236 
1237     return a;
1238 }
1239 
1240 /*! \reimp
1241 
1242     For this class, always returns true.
1243 */
isValid() const1244 bool QtSoapArray::isValid() const
1245 {
1246     return true;
1247 }
1248 
1249 /*!
1250     Inspects \a node and builds the content of the QtSoapArray if \a
1251     node qualifies as a SOAP array. Returns true if it does; otherwise
1252     returns false.
1253 */
parse(QDomNode node)1254 bool QtSoapArray::parse(QDomNode node)
1255 {
1256     if (node.isNull() || !node.isElement())
1257 	return false;
1258 
1259     QDomElement e = node.toElement();
1260     QDomAttr typeattr = e.attributeNode("type");
1261     if (!typeattr.isNull() && (localName(typeattr.value()).toLower() != "array"))
1262 	return false;
1263 
1264 
1265     QDomNodeList children = e.childNodes();
1266     int c = children.count();
1267     array.clear();
1268     // ### array.resize(c);
1269 
1270     int pos = 0;
1271     for (int i = 0; i < c; ++i) {
1272 	QDomNode n = children.item(i);
1273         if (n.isComment())
1274             continue;
1275 	if (!n.isElement()){
1276 	    // ### An error in the soap document.
1277 	    return false;
1278 	}
1279 
1280 	QDomElement elem = n.toElement();
1281 
1282 	QtSmartPtr<QtSoapType> type = QtSoapTypeFactory::instance().soapType(elem);
1283 	if (!type.ptr()) {
1284 	    // ### An error in the soap document.
1285 	    return false;
1286 	}
1287 
1288 	// ### Check namespace
1289 	QDomAttr posattr = elem.attributeNode("position");
1290 	if (!posattr.isNull())
1291 	    pos = posattr.value().toInt();
1292 
1293 	array.insert(pos, type);
1294 	++pos;
1295     }
1296 
1297     setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
1298     return true;
1299 }
1300 
1301 /*!
1302     Returns the number of items in the array. Note that this is not
1303     the same as the size of the array, because the array may be sparse.
1304 */
count() const1305 int QtSoapArray::count() const
1306 {
1307     return array.count();
1308 }
1309 
1310 /*!
1311     Returns a reference to the item at ordinal position \a pos. If
1312     there is no item at position \a pos, returns an empty QtSoapType.
1313 */
operator [](int pos)1314 QtSoapType &QtSoapArray::operator [](int pos)
1315 {
1316     return at(pos);
1317 }
1318 
1319 /*!
1320     \overload
1321 
1322     Returns a reference to the child item whose local name is \a s. If
1323     there is no item with this local name, returns an empty
1324     QtSoapType.
1325 */
operator [](const QString & s)1326 QtSoapType &QtSoapArray::operator [](const QString &s)
1327 {
1328     return QtSoapType::operator[](s);
1329 }
1330 
1331 /*!
1332     \overload
1333 
1334     Returns a reference to the child item whose QName (qualified name)
1335     is \a s. If there is no item with this name, returns an empty
1336     QtSoapType.
1337 */
operator [](const QtSoapQName & s)1338 QtSoapType &QtSoapArray::operator [](const QtSoapQName &s)
1339 {
1340     return QtSoapType::operator[](s);
1341 }
1342 
1343 /*!
1344     \overload
1345 
1346     Returns a reference to the item at ordinal position \a pos. If
1347     there is no item at position \a pos, returns an empty QtSoapType.
1348 */
operator [](int pos) const1349 const QtSoapType &QtSoapArray::operator [] (int pos) const
1350 {
1351     return at(pos);
1352 }
1353 
1354 /*!
1355     \overload
1356 
1357     Returns a reference to the child item whose local name is \a s. If
1358     there is no item with this local name, returns an empty
1359     QtSoapType.
1360 */
operator [](const QString & s) const1361 const QtSoapType &QtSoapArray::operator [](const QString &s) const
1362 {
1363     return QtSoapType::operator[](s);
1364 }
1365 
1366 /*!
1367     \overload
1368 
1369     Returns a reference to the child item whose QName (qualified name)
1370     is \a s. If there is no item with this name, returns an empty
1371     QtSoapType.
1372 */
operator [](const QtSoapQName & s) const1373 const QtSoapType &QtSoapArray::operator [](const QtSoapQName &s) const
1374 {
1375     return QtSoapType::operator[](s);
1376 }
1377 
1378 /*!
1379     Returns a reference to the item at ordinal position \a pos. If
1380     there is no item at position \a pos, returns an empty QtSoapType.
1381 */
at(int pos)1382 QtSoapType &QtSoapArray::at(int pos)
1383 {
1384     static QtSoapType NIL;
1385 
1386     if (array.find(pos) != array.end())
1387 	return *array[pos];
1388     else
1389 	return NIL;
1390 }
1391 
1392 /*!
1393     \overload
1394 
1395     Returns a reference to the item at ordinal position \a pos0 x \a
1396     pos1 in a two dimensional array. If there is no such item, returns
1397     an empty QtSoapType.
1398 */
at(int pos0,int pos1)1399 QtSoapType &QtSoapArray::at(int pos0, int pos1)
1400 {
1401     return at(pos0 * siz1 + pos1);
1402 }
1403 
1404 /*!
1405     \overload
1406 
1407     Returns a reference to the item at ordinal position \a pos0 x \a
1408     pos1 x \a pos2 in a three dimensional array. If there is no such
1409     item, returns an empty QtSoapType.
1410 */
at(int pos0,int pos1,int pos2)1411 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2)
1412 {
1413     return at((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2);
1414 }
1415 
1416 /*!
1417     \overload
1418 
1419     Returns a reference to the item at ordinal position \a pos0 x \a
1420     pos1 x \a pos2 x \a pos3 in a four dimensional array. If there is no
1421     such item, returns an empty QtSoapType.
1422 */
at(int pos0,int pos1,int pos2,int pos3)1423 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3)
1424 {
1425     return at((pos0 * siz3 * siz2 * siz1)
1426 	      + (pos1 * siz3 * siz2)
1427 	      + (pos2 * siz3)
1428 	      + pos3);
1429 }
1430 
1431 /*!
1432     \overload
1433 
1434     Returns a reference to the item at ordinal position \a pos0 x \a
1435     pos1 x \a pos2 x \a pos3 x \a pos4 in a five dimensional array. If
1436     there is no such item, returns an empty QtSoapType.
1437 */
at(int pos0,int pos1,int pos2,int pos3,int pos4)1438 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3, int pos4)
1439 {
1440     return at((pos0 * siz4 * siz3 * siz2 * siz1)
1441 	      + (pos1 * siz4 * siz3 * siz2)
1442 	      + (pos2 * siz4 * siz3)
1443 	      + (pos3 * siz4)
1444 	      + pos4);
1445 }
1446 
1447 /*!
1448     \overload
1449 
1450     Returns a reference to the item at ordinal position \a pos. If
1451     there is no item at position \a pos, returns an empty QtSoapType.
1452 */
at(int pos) const1453 const QtSoapType &QtSoapArray::at(int pos) const
1454 {
1455     static QtSoapType NIL;
1456 
1457     if (array.find(pos) != array.end())
1458 	return *array[pos];
1459     else
1460 	return NIL;
1461 }
1462 
1463 /*!
1464     \overload
1465 
1466     Returns a reference to the item at ordinal position \a pos0 x \a
1467     pos1 in a two dimensional array. If there is no such item, returns
1468     an empty QtSoapType.
1469 */
at(int pos0,int pos1) const1470 const QtSoapType &QtSoapArray::at(int pos0, int pos1) const
1471 {
1472     return at(pos0 * siz1 + pos1);
1473 }
1474 
1475 /*!
1476     \overload
1477 
1478     Returns a reference to the item at ordinal position \a pos0 x \a
1479     pos1 x \a pos2 in a three dimensional array. If there is no such
1480     item, returns an empty QtSoapType.
1481 */
at(int pos0,int pos1,int pos2) const1482 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2) const
1483 {
1484     return at((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2);
1485 }
1486 
1487 /*!
1488     \overload
1489 
1490     Returns a reference to the item at ordinal position \a pos0 x \a
1491     pos1 x \a pos2 x \a pos3 in a four dimensional array. If there is no
1492     such item, returns an empty QtSoapType.
1493 */
at(int pos0,int pos1,int pos2,int pos3) const1494 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3) const
1495 {
1496     return at((pos0 * siz3 * siz2 * siz1)
1497 	      + (pos1 * siz3 * siz2)
1498 	      + (pos2 * siz3)
1499 	      + pos3);
1500 }
1501 
1502 /*!
1503     \overload
1504 
1505     Returns a reference to the item at ordinal position \a pos0 x \a
1506     pos1 x \a pos2 x \a pos3 x \a pos4 in a five dimensional array. If
1507     there is no such item, returns an empty QtSoapType.
1508 */
at(int pos0,int pos1,int pos2,int pos3,int pos4) const1509 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3, int pos4) const
1510 {
1511     return at((pos0 * siz4 * siz3 * siz2 * siz1)
1512 	      + (pos1 * siz4 * siz3 * siz2)
1513 	      + (pos2 * siz4 * siz3)
1514 	      + (pos3 * siz4)
1515 	      + pos4);
1516 }
1517 
1518 /*!
1519     Constructs a QtSoapArrayIterator on \a array, initializing
1520     the iterator to point to the first element.
1521 */
QtSoapArrayIterator(QtSoapArray & array)1522 QtSoapArrayIterator::QtSoapArrayIterator(QtSoapArray &array)
1523     : it(array.array.begin()), arr(&array)
1524 {
1525 }
1526 
1527 /*!
1528     Constructs a QtSoapArrayIterator that is a copy of \a copy.
1529 */
QtSoapArrayIterator(const QtSoapArrayIterator & copy)1530 QtSoapArrayIterator::QtSoapArrayIterator(const QtSoapArrayIterator &copy)
1531     : it(copy.it), arr(copy.arr)
1532 {
1533 }
1534 
1535 /*!
1536     Returns false if this iterator points to an item in the array, otherwise true.
1537 */
atEnd() const1538 bool QtSoapArrayIterator::atEnd() const
1539 {
1540     return (it == arr->array.end());
1541 }
1542 
1543 /*!
1544     Assignment operator of QtSoapArrayIterator. Makes this iterator a
1545     copy of \a copy.
1546 */
operator =(const QtSoapArrayIterator & copy)1547 QtSoapArrayIterator &QtSoapArrayIterator::operator =(const QtSoapArrayIterator &copy)
1548 {
1549     it = copy.it;
1550     arr = copy.arr;
1551 
1552     return *this;
1553 }
1554 
1555 /*!
1556     Destructs the QtSoapArrayIterator.
1557 */
~QtSoapArrayIterator()1558 QtSoapArrayIterator::~QtSoapArrayIterator()
1559 {
1560 }
1561 
1562 /*!
1563     \overload
1564 
1565     Returns the ordinal position of the iterator. Works for arrays of
1566     any dimension, but is only useful for one dimensional arrays.
1567 */
pos() const1568 int QtSoapArrayIterator::pos() const
1569 {
1570     return it.key();
1571 }
1572 
1573 /*!
1574     Populates the arguments \a pos0, \a pos1, \a pos2, \a pos3 and \a
1575     pos4 with the coordinate of the current position of the iterator.
1576     For a one dimensional array, only \a pos0 is populated. For a two
1577     dimensional array, \a pos0 and \a pos1 are populated, and so on.
1578 
1579     Any of the arguments that are 0-pointers are ignored.
1580 */
pos(int * pos0,int * pos1,int * pos2,int * pos3,int * pos4) const1581 void QtSoapArrayIterator::pos(int *pos0, int *pos1, int *pos2,
1582 			      int *pos3, int *pos4) const
1583 {
1584     const int key = it.key();
1585 
1586     switch (arr->order) {
1587     case 1:
1588 	if (pos0) *pos0 = key;
1589 	break;
1590     case 2: {
1591 	const int tmp = key / arr->siz1;
1592 	if (pos0) *pos0 = tmp;
1593 	if (pos1) *pos1 = key - (tmp * arr->siz1);
1594     }
1595 	break;
1596     case 3: {
1597 	const int tmp0 = key / (arr->siz2 * arr->siz1);
1598 	const int tmp1 = key - (tmp0 * (arr->siz2 * arr->siz1));
1599 	const int tmp2 = tmp1 / arr->siz2;
1600 	if (pos0) *pos0 = tmp0;
1601 	if (pos1) *pos1 = tmp2;
1602 	if (pos2) *pos2 = tmp1 - (tmp2 * arr->siz2);
1603     }
1604 	break;
1605     case 4: {
1606 	const int tmp0 = key / (arr->siz3 * arr->siz2 * arr->siz1);
1607 	const int tmp1 = key - (tmp0 * (arr->siz3 * arr->siz2 * arr->siz1));
1608 	const int tmp2 = tmp1 / (arr->siz3 * arr->siz2);
1609 	const int tmp3 = tmp1 - (tmp2 * (arr->siz3 * arr->siz2));
1610 	const int tmp4 = tmp3 / arr->siz3;
1611 	const int tmp5 = tmp3 - (tmp4 * arr->siz3);
1612 	if (pos0) *pos0 = tmp0;
1613 	if (pos1) *pos1 = tmp2;
1614 	if (pos2) *pos2 = tmp4;
1615 	if (pos3) *pos3 = tmp5;
1616     }
1617 	break;
1618     case 5: {
1619 	const int tmp0 = key / (arr->siz4 * arr->siz3 * arr->siz2 * arr->siz1);
1620 	const int tmp1 = key - (tmp0 * (arr->siz4 * arr->siz3 * arr->siz2 * arr->siz1));
1621 	const int tmp2 = tmp1 / (arr->siz4 * arr->siz3 * arr->siz2);
1622 	const int tmp3 = tmp1 - (tmp2 * (arr->siz4 * arr->siz3 * arr->siz2));
1623 	const int tmp4 = tmp3 / (arr->siz4 * arr->siz3);
1624 	const int tmp5 = tmp3 - (tmp4 * arr->siz4 * arr->siz3);
1625 	const int tmp6 = tmp5 / arr->siz3;
1626 	const int tmp7 = tmp5 - (tmp6 * arr->siz3);
1627 	if (pos0) *pos0 = tmp0;
1628 	if (pos1) *pos1 = tmp2;
1629 	if (pos2) *pos2 = tmp4;
1630 	if (pos3) *pos3 = tmp6;
1631 	if (pos4) *pos4 = tmp7;
1632     }
1633 	break;
1634     default:
1635 	break;
1636     }
1637 }
1638 
1639 /*!
1640     Returns a reference to the item that the iterator is currently
1641     pointing to.
1642 */
data()1643 QtSoapType *QtSoapArrayIterator::data()
1644 {
1645     if (it == arr->array.end())
1646         return 0;
1647     return it.value().ptr();
1648 }
1649 
1650 /*!
1651     Returns a reference to the item that the iterator is currently
1652     pointing to.
1653 */
current() const1654 const QtSoapType *QtSoapArrayIterator::current() const
1655 {
1656     if (it == arr->array.end())
1657         return 0;
1658     return it.value().ptr();
1659 }
1660 
1661 /*!
1662     Moves the iterator position to the next item in the array.
1663 */
operator ++()1664 void QtSoapArrayIterator::operator ++()
1665 {
1666     ++it;
1667 }
1668 
1669 /*!
1670     Returns true if this Iterator's position is not equal to
1671     the position of \a j; otherwise returns false.
1672 */
operator !=(const QtSoapArrayIterator & j) const1673 bool QtSoapArrayIterator::operator != (const QtSoapArrayIterator &j) const
1674 {
1675     return it != j.it;
1676 }
1677 
1678 /*!
1679     Returns true if this Iterator's position is equal to the position
1680     of \a j; otherwise returns false.
1681 */
operator ==(const QtSoapArrayIterator & j) const1682 bool QtSoapArrayIterator::operator == (const QtSoapArrayIterator &j) const
1683 {
1684     return it == j.it;
1685 }
1686 
1687 /*!
1688     Constructs an empty QtSoapStruct.
1689 */
QtSoapStruct()1690 QtSoapStruct::QtSoapStruct()
1691     : QtSoapType(QtSoapQName(), Struct)
1692 {
1693 }
1694 
1695 /*!
1696     Constructs an empty QtSoapStruct and sets its QName (qualified
1697     name) to \a name.
1698 */
QtSoapStruct(const QtSoapQName & name)1699 QtSoapStruct::QtSoapStruct(const QtSoapQName &name)
1700     : QtSoapType(name, Struct)
1701 {
1702 }
1703 
1704 /*!
1705     Constructs a QtSoapStruct that is a copy of \a copy.
1706 */
QtSoapStruct(const QtSoapStruct & copy)1707 QtSoapStruct::QtSoapStruct(const QtSoapStruct &copy)
1708     : QtSoapType(copy)
1709 {
1710     *this = copy;
1711 }
1712 
1713 /*!
1714     Destructs the QtSoapStruct.
1715 */
~QtSoapStruct()1716 QtSoapStruct::~QtSoapStruct()
1717 {
1718 }
1719 
1720 /*!
1721     Removes all items from the struct.
1722 */
clear()1723 void QtSoapStruct::clear()
1724 {
1725     dict.clear();
1726 }
1727 
1728 /*!
1729     Makes this struct a copy of \a copy.
1730 */
operator =(const QtSoapStruct & copy)1731 QtSoapStruct &QtSoapStruct::operator =(const QtSoapStruct &copy)
1732 {
1733     if (this == &copy)
1734         return *this;
1735     t = copy.t;
1736     errorStr = copy.errorStr;
1737     i = copy.i;
1738     n = copy.n;
1739     u = copy.u;
1740     h = copy.h;
1741     i = copy.i;
1742     dict = copy.dict;
1743 
1744     return *this;
1745 }
1746 
1747 /*!
1748     Inserts the QtSoapType \a item into this struct. Any existing
1749     item with the same QName (qualified name) will be erased.
1750 */
insert(QtSoapType * item)1751 void QtSoapStruct::insert(QtSoapType *item)
1752 {
1753     dict.append(item);
1754 }
1755 
1756 /*!
1757     Generates the QDomElement representation of this struct.  The
1758     returned QDomElement is created using \a doc.
1759 */
toDomElement(QDomDocument doc) const1760 QDomElement QtSoapStruct::toDomElement(QDomDocument doc) const
1761 {
1762     QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
1763     QDomElement a = n.uri() == ""
1764 		    ? doc.createElement(n.name())
1765 		    : doc.createElementNS(n.uri(), prefix + ":" + n.name());
1766 
1767     for (QtSoapStructIterator i(*const_cast<QtSoapStruct *>(this)); i.data(); ++i)
1768 	a.appendChild(i.data()->toDomElement(doc));
1769 
1770     return a;
1771 }
1772 
1773 /*! \reimp
1774  */
isValid() const1775 bool QtSoapStruct::isValid() const
1776 {
1777     return true;
1778 }
1779 
1780 /*!
1781     Inspects \a node and constructs the equivalent QtSoapStruct if \a
1782     node qualifies as a SOAP struct. Returns true if it does;
1783     otherwise returns false.
1784 */
parse(QDomNode node)1785 bool QtSoapStruct::parse(QDomNode node)
1786 {
1787     if (node.isNull() || !node.isElement())
1788 	return false;
1789 
1790     QDomElement e = node.toElement();
1791     QDomNodeList children = e.childNodes();
1792     int c = children.count();
1793     dict.clear();
1794 
1795     for (int i = 0; i < c; ++i) {
1796 	QDomNode n = children.item(i);
1797         if (n.isComment())
1798             continue;
1799 	if (!n.isElement()){
1800 	    errorStr = "In the struct element " + e.tagName();
1801 	    errorStr += ", the " + QString::number(i) + "th child ";
1802 	    errorStr += "is not an element.";
1803 	    return false;
1804 	}
1805 
1806 	QtSmartPtr<QtSoapType> type = QtSoapTypeFactory::instance().soapType(n.toElement());
1807 	if (!type.ptr()) {
1808 	    errorStr = "In the struct element " + e.tagName();
1809 	    errorStr += ", child #" + QString::number(i) + ", ";
1810 	    errorStr += n.toElement().tagName() + ", was not recognized as a SOAP type.";
1811 	    return false;
1812 	}
1813 
1814 	dict.append(type);
1815     }
1816 
1817     setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
1818     return true;
1819 }
1820 
1821 /*!
1822     Returns the number of items in this struct.
1823 */
count() const1824 int QtSoapStruct::count() const
1825 {
1826     return dict.count();
1827 }
1828 
1829 /*!
1830     Returns a reference to the item in this struct whose QName
1831     (qualified name) is \a key. If no such item exists, an empty
1832     QtSoapType is returned.
1833 */
operator [](const QtSoapQName & key)1834 QtSoapType &QtSoapStruct::operator [](const QtSoapQName &key)
1835 {
1836     return at(key);
1837 }
1838 
1839 /*!
1840     \overload
1841 
1842     Returns a reference to the item in this struct whose QName
1843     (qualified name) is \a key. If no such item exists, an empty
1844     QtSoapType is returned.
1845 */
operator [](const QtSoapQName & key) const1846 const QtSoapType &QtSoapStruct::operator [](const QtSoapQName &key) const
1847 {
1848     return at(key);
1849 }
1850 
1851 /*!
1852     \overload
1853 
1854     Returns a reference to the item in this struct whose QName
1855     (qualified name) is \a key. If no such item exists, an empty
1856     QtSoapType is returned.
1857 */
operator [](const QString & key)1858 QtSoapType &QtSoapStruct::operator [](const QString &key)
1859 {
1860     return at(QtSoapQName(key, ""));
1861 }
1862 
1863 /*!
1864     \overload
1865 
1866     Returns a reference to the item in this struct whose QName
1867     (qualified name) is \a key. If no such item exists, an empty
1868     QtSoapType is returned.
1869 */
operator [](const QString & key) const1870 const QtSoapType &QtSoapStruct::operator [](const QString &key) const
1871 {
1872     return at(QtSoapQName(key, ""));
1873 }
1874 
1875 /*!
1876     \overload
1877 
1878     Returns a reference to item number \a i in this struct. If no such
1879     item exists, an empty QtSoapType is returned.
1880 
1881     The items are ordered in the sequence in which they were inserted,
1882     starting from 0.
1883 */
operator [](int i)1884 QtSoapType &QtSoapStruct::operator [](int i)
1885 {
1886     static QtSoapType NIL;
1887     if (i < 0 || i >= dict.count())
1888         return NIL;
1889 
1890     return *dict[i].ptr();
1891 }
1892 
1893 /*!
1894     \overload
1895 
1896     Returns a reference to item number \a i in this struct. If no such
1897     item exists, an empty QtSoapType is returned.
1898 
1899     The items are ordered in the sequence in which they were inserted,
1900     starting from 0.
1901 */
operator [](int i) const1902 const QtSoapType &QtSoapStruct::operator [](int i) const
1903 {
1904     static QtSoapType NIL;
1905     if (i < 0 || i >= dict.count())
1906         return NIL;
1907 
1908     return *dict[i].ptr();
1909 }
1910 
1911 /*!
1912     Returns a reference to the item in this struct whose QName
1913     (qualified name) is \a key. If no such item exists, an empty
1914     QtSoapType is returned.
1915 */
at(const QtSoapQName & key)1916 QtSoapType &QtSoapStruct::at(const QtSoapQName &key)
1917 {
1918     static QtSoapType NIL;
1919 
1920     QListIterator<QtSmartPtr<QtSoapType> > it(dict);
1921     while (it.hasNext()) {
1922         QtSoapType *ret = it.next().ptr();
1923         if (ret->name() == key)
1924             return *ret;
1925     }
1926 
1927     return NIL;
1928 }
1929 
1930 /*!
1931     \overload
1932 
1933     Returns a reference to the item in this struct whose QName
1934     (qualified name) is \a key. If no such item exists, an empty
1935     QtSoapType is returned.
1936 */
at(const QtSoapQName & key) const1937 const QtSoapType &QtSoapStruct::at(const QtSoapQName &key) const
1938 {
1939     static QtSoapType NIL;
1940 
1941     for (QtSoapStructIterator i(*const_cast<QtSoapStruct *>(this)); i.current(); ++i)
1942 	if (i.key() == key)
1943 	    return *i.current();
1944 
1945     return NIL;
1946 }
1947 
1948 /*!
1949     Constructs a QtSoapStructIterator and initializes it to point to
1950     the first element in the struct \a s.
1951 */
QtSoapStructIterator(QtSoapStruct & s)1952 QtSoapStructIterator::QtSoapStructIterator(QtSoapStruct &s) : it(s.dict.begin()), itEnd(s.dict.end())
1953 {
1954 }
1955 
1956 /*!
1957     Destructs the QtSoapStructIterator.
1958 */
~QtSoapStructIterator()1959 QtSoapStructIterator::~QtSoapStructIterator()
1960 {
1961 }
1962 
1963 
1964 /*!
1965     Returns the QName (qualified name) of the current item.
1966 */
key() const1967 QtSoapQName QtSoapStructIterator::key() const
1968 {
1969     if (it == itEnd)
1970         return QtSoapQName();
1971     return (*it)->name();
1972 }
1973 
1974 /*!
1975     Returns a pointer to the current item, or 0 if there is none.
1976 */
data()1977 QtSoapType *QtSoapStructIterator::data()
1978 {
1979     if (it == itEnd)
1980         return 0;
1981     return it->ptr();
1982 }
1983 
1984 /*!
1985     Returns a pointer to the current item, or 0 if there is none.
1986 */
current() const1987 const QtSoapType *QtSoapStructIterator::current() const
1988 {
1989     if (it == itEnd)
1990         return 0;
1991     return it->ptr();
1992 }
1993 
1994 /*!
1995     Moves the iterator to the next item in the struct.
1996 */
operator ++()1997 void QtSoapStructIterator::operator ++()
1998 {
1999     if (it == itEnd)
2000         return;
2001     ++it;
2002 }
2003 
2004 /*!
2005     Returns true if this iterator's position is not equal to that of
2006     \a j; otherwise returns false.
2007 */
operator !=(const QtSoapStructIterator & j) const2008 bool QtSoapStructIterator::operator !=(const QtSoapStructIterator &j) const
2009 {
2010     return it != j.it;
2011 }
2012 
2013 /*!
2014     Returns true if this iterator's position is equal to that of \a
2015     j; otherwise returns false.
2016 */
operator ==(const QtSoapStructIterator & j) const2017 bool QtSoapStructIterator::operator ==(const QtSoapStructIterator &j) const
2018 {
2019     return it == j.it;
2020 }
2021 
2022 /*!
2023     Constructs an empty QtSoapSimpleType.
2024 */
QtSoapSimpleType()2025 QtSoapSimpleType::QtSoapSimpleType()
2026 {
2027 }
2028 
2029 /*!
2030     \overload
2031 
2032     Constructs an empty QtSoapSimpleType, and sets its QName
2033     (qualified name) to \a name.
2034 */
QtSoapSimpleType(const QtSoapQName & name)2035 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name)
2036     : QtSoapType(name)
2037 {
2038 }
2039 
2040 /*!
2041     \overload
2042 
2043     Constructs a QtSoapSimpleType of type Int. Sets its QName
2044     (qualified name) to \a name and its value to \a n.
2045 */
QtSoapSimpleType(const QtSoapQName & name,int n)2046 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, int n)
2047     : QtSoapType(name, Int), v(QVariant(n))
2048 {
2049 }
2050 
2051 /*!
2052     \overload
2053 
2054     Constructs a QtSoapSimpleType of type Boolean. Sets its QName
2055     (qualified name) to \a name and its value to \a n.
2056 
2057     \a dummy is an unused variable that should be set to 0; it is
2058     needed for older compilers that cannot distinguish between bool
2059     and int.
2060 */
QtSoapSimpleType(const QtSoapQName & name,bool n,int)2061 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, bool n, int)
2062     : QtSoapType(name, Boolean), v(QVariant(n))
2063 {
2064 }
2065 
2066 /*!
2067     \overload
2068 
2069     Constructs a QtSoapSimpleType of type String. Sets its QName
2070     (qualified name) to \a name and its value to \a n.
2071 */
QtSoapSimpleType(const QtSoapQName & name,const QString & n)2072 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, const QString &n)
2073     : QtSoapType(name, String), v(QVariant(n))
2074 {
2075 }
2076 
2077 /*!
2078     Constructs a QtSoapSimpleType that is a copy of \a copy.
2079 */
QtSoapSimpleType(const QtSoapSimpleType & copy)2080 QtSoapSimpleType::QtSoapSimpleType(const QtSoapSimpleType &copy)
2081     : QtSoapType(copy), v(copy.v)
2082 {
2083 }
2084 
2085 /*!
2086     Destructs the QtSoapSimpleType.
2087 */
~QtSoapSimpleType()2088 QtSoapSimpleType::~QtSoapSimpleType()
2089 {
2090 }
2091 
2092 /*!
2093     Erases the value of this QtSoapSimpleType.
2094 */
clear()2095 void QtSoapSimpleType::clear()
2096 {
2097     v.clear();
2098 }
2099 
2100 /*!
2101     Returns the QDomElement representation of this QtSoapSimpleType.
2102     The returned QDomElement is created using \a doc.
2103 */
toDomElement(QDomDocument doc) const2104 QDomElement QtSoapSimpleType::toDomElement(QDomDocument doc) const
2105 {
2106     QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
2107     QDomElement a = n.uri() == ""
2108 		    ? doc.createElement(n.name())
2109 		    : doc.createElementNS(n.uri(), prefix + ":" + n.name());
2110 
2111     QString schemaprefix = QtSoapNamespaces::instance().prefixFor(XML_SCHEMA_INSTANCE);
2112     a.setAttributeNS(XML_SCHEMA_INSTANCE, schemaprefix + ":type", "xsd:" + typeName());
2113     a.appendChild(doc.createTextNode(v.toString()));
2114 
2115     return a;
2116 }
2117 
2118 /*! \reimp
2119 */
isValid() const2120 bool QtSoapSimpleType::isValid() const
2121 {
2122     return true;
2123 }
2124 
2125 /*!
2126     Makes this QtSoapSimpleType a copy of \a copy.
2127 */
operator =(const QtSoapSimpleType & copy)2128 QtSoapSimpleType &QtSoapSimpleType::operator =(const QtSoapSimpleType &copy)
2129 {
2130     t = copy.t;
2131     errorStr = copy.errorStr;
2132     i = copy.i;
2133     n = copy.n;
2134     u = copy.u;
2135     h = copy.h;
2136     v = copy.v;
2137 
2138     return *this;
2139 }
2140 
2141 /*!
2142     Inspects \a node and constructs the QtSoapSimpleType content if \a
2143     node qualifies as a SOAP simple type. Returns true if it does;
2144     otherwise returns false.
2145 */
parse(QDomNode node)2146 bool QtSoapSimpleType::parse(QDomNode node)
2147 {
2148     if (node.isNull() || !node.isElement())
2149 	return false;
2150 
2151     QDomElement e = node.toElement();
2152 
2153     QDomAttr typeattr = e.attributeNode("type");
2154     QString type = typeattr.isNull() ? QString("string") : localName(typeattr.value()).toLower();
2155 
2156     t = QtSoapType::nameToType(type);
2157     switch (t) {
2158     case Duration:
2159     case DateTime:
2160     case Time:
2161     case Date:
2162     case GYearMonth:
2163     case GYear:
2164     case GMonthDay:
2165     case GDay:
2166     case GMonth:
2167     case Base64Binary:
2168     case HexBinary:
2169     case AnyURI:
2170     case QName:
2171     case NOTATION:
2172     case String:
2173     case NormalizedString:
2174     case Token:
2175     case Language:
2176     case Name:
2177     case NMTOKEN:
2178     case NCName:
2179     case ID:
2180     case IDREF:
2181     case ENTITY:
2182 	v = QVariant(e.text());
2183 	break;
2184     case Float:
2185 	v = QVariant(e.text().toFloat());
2186 	break;
2187     case Double:
2188 	v = QVariant(e.text().toDouble());
2189 	break;
2190     case Decimal:
2191     case Integer:
2192     case NonPositiveInteger:
2193     case NegativeInteger:
2194     case Long:
2195     case Int:
2196     case Short:
2197     case Byte:
2198     case NonNegativeInteger:
2199     case UnsignedLong:
2200     case PositiveInteger:
2201     case UnsignedInt:
2202     case UnsignedShort:
2203     case UnsignedByte:
2204 	if (e.text() == "" || (e.text() != "" && (e.text()[0].isNumber() || e.text()[0] == '-')))
2205 	    v = QVariant(e.text().toInt());
2206 	else {
2207 	    errorStr = "Type error at element \"" + e.tagName() + "\"";
2208 	    return false;
2209 	}
2210 
2211 	break;
2212     case Boolean: {
2213 	QString val = e.text().trimmed().toLower();
2214 	if (val == "false")
2215 	    v = QVariant(false);
2216 	else if (val == "true")
2217 	    v = QVariant(true);
2218     }
2219 	break;
2220     default:
2221 	v = e.text();
2222 	break;
2223     }
2224 
2225     setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
2226     return true;
2227 }
2228 
2229 /*!
2230     Returns the value of the simple type as a QString.
2231 */
toString() const2232 QString QtSoapSimpleType::toString() const
2233 {
2234     return v.toString();
2235 }
2236 
2237 /*!
2238     Returns the value of the simple type as an int.
2239 */
toInt() const2240 int QtSoapSimpleType::toInt() const
2241 {
2242     return v.toInt();
2243 }
2244 
2245 /*!
2246     Returns the value of the simple type as a bool.
2247 */
toBool() const2248 bool QtSoapSimpleType::toBool() const
2249 {
2250     return v.toBool();
2251 }
2252 
2253 
2254 /*!
2255     Returns the QVariant value of this QtSoapSimpleType.
2256 */
value() const2257 QVariant QtSoapSimpleType::value() const
2258 {
2259     return v;
2260 }
2261 
2262 /*! \class QtSoapMessage qtsoap.h
2263     \brief The QtSoapMessage class provides easy access to SOAP
2264     messages.
2265 
2266     With this class, you can create and inspect any SOAP message.
2267     There are convenience functions available for generating the most
2268     common types of SOAP messages, and any other messages can be
2269     constructed manually using addBodyItem().
2270 
2271     Use setMethod() and addMethodArgument() to construct a method
2272     request. The return value of a method response is available
2273     from returnValue().
2274 
2275     Use setFaultCode(), setFaultString() and addFaultDetail() to
2276     construct a Fault message. To inspect a Fault message, use
2277     faultCode(), faultString() and faultDetail().
2278 
2279     To add items to the body part of the SOAP message, use
2280     addBodyItem(). To add items to the header, use addHeaderItem().
2281 
2282     toXmlString() returns a QString XML representation of the SOAP
2283     message. clear() resets all content in the message, creating an
2284     empty SOAP message.
2285 
2286     \code
2287     QtSoapMessage message;
2288 
2289     message.setMethod("getTemperature", "http://weather.example.com/temperature");
2290     message.addMethodArgument("city", "Oslo");
2291 
2292     // Get the SOAP message as an XML string.
2293     QString xml = message.toXmlString();
2294     \endcode
2295 
2296     QtSoap provides a partial implementation of version 1.1 of the
2297     SOAP protocol as defined in \l http://www.w3.org/TR/SOAP/.
2298 
2299     \list
2300     \i Server side SOAP is not supported.
2301     \i References to values (id and href attributes) are not supported.
2302     \i Arrays support a maximum of five dimensions.
2303     \i Namespaces for types are not checked. Only the type names are used.
2304     \i The encodingStyle attribute is ignored. The serialization and
2305        encoding rules from section 5 in the SOAP v1.1 specification
2306        are assumed regardless of the value of the encodingStyle
2307        attribute.
2308     \i QtSoapType does not have accessors for attributes, which means
2309        for example that actor, mustUnderstand and so on are not
2310        accessible in headers.
2311     \i The SOAP root attribute is not supported.
2312     \endlist
2313 
2314     \sa QtSoapType, QtSoapQName, QtSoapHttpTransport
2315 
2316 */
2317 
2318 /*! \enum QtSoapMessage::FaultCode
2319 
2320     This enum describes all the supported SOAP Fault codes:
2321 
2322     \value VersionMismatch
2323     The namespace for the Envelope element was unrecognized by the
2324     remote SOAP server. This usually means that the remote server does
2325     not support version 1.1 of the SOAP protocol.
2326 
2327     \value MustUnderstand
2328     One of the header items in the SOAP message with a
2329     "MustUnderstand" attribute was not recognized by the remote
2330     server.
2331 
2332     \value Client
2333     An error in the SOAP message or transport prevents further
2334     processing by the remote SOAP server.
2335 
2336     \value Server
2337     An error in the remote SOAP server prevents it from processing the
2338     SOAP message.
2339 
2340     \omitvalue Other
2341 */
2342 
2343 /*! \enum QtSoapMessage::MessageType
2344 
2345     \value Fault
2346     \value MethodRequest
2347     \value MethodResponse
2348     \value OtherType
2349 
2350 */
2351 
2352 /*!
2353     Constructs an empty QtSoapMessage. The message only contains the
2354     Envelope element, with no header and no body.
2355 */
QtSoapMessage()2356 QtSoapMessage::QtSoapMessage()
2357     : type(OtherType), envelope(QtSoapQName("Envelope", SOAPv11_ENVELOPE))
2358 {
2359     init();
2360 }
2361 
2362 /*!
2363     Constructs a copy of \a copy.
2364 */
QtSoapMessage(const QtSoapMessage & copy)2365 QtSoapMessage::QtSoapMessage(const QtSoapMessage &copy)
2366     : type(copy.type), envelope(copy.envelope), m(copy.m), margs(copy.margs),
2367       errorStr(copy.errorStr)
2368 {
2369     init();
2370 }
2371 
2372 /*!
2373     Destructs a QtSoapMessage.
2374 */
~QtSoapMessage()2375 QtSoapMessage::~QtSoapMessage()
2376 {
2377 }
2378 
2379 /*! \internal
2380 
2381     Registers the standard SOAP namespaces with prefixes.
2382 */
init()2383 void QtSoapMessage::init()
2384 {
2385     QtSoapNamespaces::instance().registerNamespace("SOAP-ENV", SOAPv11_ENVELOPE);
2386     QtSoapNamespaces::instance().registerNamespace("SOAP-ENC", SOAPv11_ENCODING);
2387     QtSoapNamespaces::instance().registerNamespace("xsi", XML_SCHEMA_INSTANCE);
2388     QtSoapNamespaces::instance().registerNamespace("xsd", XML_SCHEMA);
2389 }
2390 
2391 /*!
2392     Clears the content of the SOAP message.
2393 */
clear()2394 void QtSoapMessage::clear()
2395 {
2396     type = OtherType;
2397     envelope.clear();
2398     m = QtSoapQName();
2399     margs.clear();
2400     errorStr = "Unknown error";
2401 }
2402 
2403 /*!
2404     Makes this message a copy of \a copy.
2405 */
operator =(const QtSoapMessage & copy)2406 QtSoapMessage &QtSoapMessage::operator =(const QtSoapMessage &copy)
2407 {
2408     envelope = copy.envelope;
2409     m = copy.m;
2410     margs = copy.margs;
2411     errorStr = copy.errorStr;
2412     return *this;
2413 }
2414 
2415 /*!
2416     Imports the QDomDocument \a d if it validates as a SOAP
2417     message. Any existing message content is replaced.
2418 
2419     If the import fails, this message becomes a Fault message.
2420 
2421     Returns true if the import succeeds, otherwise false.
2422 */
setContent(QDomDocument & d)2423 bool QtSoapMessage::setContent(QDomDocument &d)
2424 {
2425     if (isValidSoapMessage(d)) {
2426 	clear();
2427         QDomNode node = d.firstChild();
2428         if (!node.isElement())
2429             node = node.nextSibling();
2430 
2431 	if (envelope.parse(node))
2432 	    return true;
2433     }
2434 
2435     return false;
2436 }
2437 
2438 /*!
2439     \overload
2440 
2441     Parses the XML document in \a buffer. Imports the document if it
2442     validates as a SOAP message. Any existing message content is
2443     replaced.
2444 
2445     If the import fails, this message becomes a Fault message.
2446 
2447     Returns true if the import succeeds, otherwise false.
2448 */
setContent(const QByteArray & buffer)2449 bool QtSoapMessage::setContent(const QByteArray &buffer)
2450 {
2451     int errorLine, errorColumn;
2452     QString errorMsg;
2453 
2454     QDomDocument doc;
2455     if (!doc.setContent(buffer, true, &errorMsg,
2456 			&errorLine, &errorColumn)) {
2457 	QString s;
2458 	s.sprintf("%s at line %i, column %i", errorMsg.toLatin1().constData(),
2459 		  errorLine, errorColumn);
2460 	setFaultCode(VersionMismatch);
2461 	setFaultString("XML parse error");
2462 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("ParseError"), s));
2463 	return false;
2464     }
2465 
2466     if (!isValidSoapMessage(doc))
2467 	return false;
2468 
2469     QDomNode node = doc.firstChild();
2470     if (!node.isElement())
2471 	node = node.nextSibling();
2472     bool res = envelope.parse(node);
2473     if (!res)
2474 	qDebug("QtSoapMessage::setContent(), parsing failed: %s", envelope.errorString().toLatin1().constData());
2475     return res;
2476 }
2477 
2478 /*!
2479     Validates the QDomDocument \a candidate using some simple
2480     heuristics. Returns true if the document is a valid SOAP message;
2481     otherwise returns false.
2482 */
isValidSoapMessage(const QDomDocument & candidate)2483 bool QtSoapMessage::isValidSoapMessage(const QDomDocument &candidate)
2484 {
2485     QDomNode tmp = candidate.firstChild();
2486     if (tmp.isNull())
2487 	return false;
2488 
2489     // Skip the initial processing instruction if there is one. Most
2490     // likely this isn't actually a processing instruction, but rather
2491     // the initial xml declaration <?xml...
2492     if (tmp.isProcessingInstruction()) {
2493 	tmp = tmp.nextSibling();
2494 
2495 	if (tmp.isNull() || !tmp.isElement())
2496 	    return false;
2497     }
2498 
2499     QDomElement tmpe = tmp.toElement();
2500 
2501     if (localName(tmpe.tagName()).toUpper() != "ENVELOPE") {
2502 	setFaultCode(VersionMismatch);
2503 	setFaultString("SOAP structure invalid");
2504 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "root element \"" + tmpe.localName()
2505 					+ "\"/\"" + tmpe.tagName() + "\" is not envelope"));
2506 	return false;
2507     }
2508 
2509     tmp = tmp.firstChild();
2510     if (tmp.isNull() || !tmp.isElement()) {
2511 	setFaultCode(VersionMismatch);
2512 	setFaultString("SOAP structure invalid");
2513 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2514 	return false;
2515     }
2516 
2517     QDomElement tmpe2 = tmp.toElement();
2518 
2519     bool foundHeader = false;
2520     if (localName(tmpe2.tagName()).toUpper() == "HEADER") {
2521 	foundHeader = true;
2522 	tmp = tmp.nextSibling();
2523     }
2524 
2525     if (!foundHeader && (tmp.isNull() || !tmp.isElement())) {
2526 	setFaultCode(VersionMismatch);
2527 	setFaultString("SOAP structure invalid");
2528 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2529 	return false;
2530     }
2531 
2532     QDomElement tmpe3 = tmp.toElement();
2533 
2534     if (localName(tmpe3.tagName()).toUpper() != "BODY") {
2535 	setFaultCode(VersionMismatch);
2536 	setFaultString("SOAP structure invalid");
2537 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2538 	return false;
2539     }
2540 
2541     // At this point, check that the version of the envelope is
2542     // correct.
2543     if (tmpe.namespaceURI() != SOAPv11_ENVELOPE) {
2544 	setFaultCode(VersionMismatch);
2545 	setFaultString("SOAP structure invalid");
2546 	addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "Unsupported namespace for envelope element"));
2547 	return false;
2548     }
2549 
2550     return true;
2551 }
2552 
2553 /*!
2554     Returns the XML representation of the SOAP message as a QString,
2555     optionally indenting using \a indent spaces.
2556 */
toXmlString(int indent) const2557 QString QtSoapMessage::toXmlString(int indent) const
2558 {
2559     QDomImplementation impl;
2560     QDomDocument doc = impl.createDocument(QString(), QString("placeholder"),
2561                                            QDomDocumentType());
2562     doc.removeChild(doc.firstChild());
2563     doc.appendChild(envelope.toDomElement(doc));
2564 
2565     QDomElement env = doc.firstChild().toElement();
2566 
2567     env.setAttribute(QtSoapNamespaces::instance().prefixFor(SOAPv11_ENVELOPE)
2568 		     + ":" + "encodingStyle",
2569 		     SOAPv11_ENCODING);
2570 
2571     env.setAttribute("xmlns:" + QtSoapNamespaces::instance().prefixFor(XML_SCHEMA),
2572 		     XML_SCHEMA);
2573 
2574     return doc.toString(indent);
2575 }
2576 
2577 /*!
2578     Returns a human readable explanation of the most recent error that
2579     occurred in the QtSoapMessage.
2580 */
errorString() const2581 QString QtSoapMessage::errorString() const
2582 {
2583     return errorStr;
2584 }
2585 
2586 /*!
2587     Adds \a item to the body in the SOAP message. The item is added
2588     after the last existing item in the body.
2589 */
addBodyItem(QtSoapType * item)2590 void QtSoapMessage::addBodyItem(QtSoapType *item)
2591 {
2592     body().insert(item);
2593 }
2594 
2595 /*!
2596     Adds \a item to the header in the SOAP message. The item is added
2597     after the last existing item in the header.
2598 */
addHeaderItem(QtSoapType * item)2599 void QtSoapMessage::addHeaderItem(QtSoapType *item)
2600 {
2601     QtSoapType &headerTmp = envelope[QtSoapQName("Header", SOAPv11_ENVELOPE)];
2602     if (!headerTmp.isValid())
2603 	envelope.insert(new QtSoapStruct(QtSoapQName("Header", SOAPv11_ENVELOPE)));
2604 
2605     QtSoapStruct &header = (QtSoapStruct &)envelope[QtSoapQName("Header", SOAPv11_ENVELOPE)];
2606     header.insert(item);
2607 }
2608 /*!
2609     Returns the return value of a SOAP method response as a
2610     QtSoapType.
2611 */
returnValue() const2612 const QtSoapType &QtSoapMessage::returnValue() const
2613 {
2614     static QtSoapType NIL;
2615 
2616     const QtSoapType &meth = method();
2617 
2618     if (!meth.isValid() || meth.type() != QtSoapType::Struct)
2619 	return NIL;
2620 
2621     QtSoapStruct &m = (QtSoapStruct &) meth;
2622     if (m.count() == 0)
2623 	return NIL;
2624 
2625     QtSoapStructIterator mi(m);
2626     return *mi.data();
2627 }
2628 
2629 /*!
2630     Returns the Fault detail element of a SOAP Fault message.
2631 */
faultDetail() const2632 const QtSoapType &QtSoapMessage::faultDetail() const
2633 {
2634     return body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)][QtSoapQName("Detail")];
2635 }
2636 
2637 /*!
2638     Returns the Fault faultstring element of a SOAP Fault message.
2639 */
faultString() const2640 const QtSoapType &QtSoapMessage::faultString() const
2641 {
2642     return body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)][QtSoapQName("Faultstring")];
2643 }
2644 
2645 /*!
2646     Returns true if the message is a SOAP Fault message; otherwise
2647     returns false.
2648 */
isFault() const2649 bool QtSoapMessage::isFault() const
2650 {
2651     return faultCode() != Other;
2652 }
2653 
2654 /*!
2655     Returns the Fault faultcode element of a SOAP Fault message.
2656 */
faultCode() const2657 QtSoapMessage::FaultCode QtSoapMessage::faultCode() const
2658 {
2659     QtSoapType &code = body()[QtSoapQName("Fault")][QtSoapQName("Faultcode")];
2660     if (!code.isValid() || (code.type() != QtSoapType::String
2661                             && code.type() != QtSoapType::QName))
2662 	return Other;
2663 
2664     QtSoapSimpleType &fcode = (QtSoapSimpleType &)code;
2665     QString fcodestr = fcode.value().toString();
2666 
2667     // Only test string before first .
2668     int pos;
2669     if ((pos = fcodestr.indexOf('.')) != -1)
2670         fcodestr.truncate(pos);
2671 
2672     if (localName(fcodestr.toLower()) == "versionmismatch")
2673 	return VersionMismatch;
2674 
2675     if (localName(fcodestr.toLower()) == "mustunderstand")
2676 	return MustUnderstand;
2677 
2678     if (localName(fcodestr.toLower()) == "client")
2679 	return Client;
2680 
2681     if (localName(fcodestr.toLower()) == "server")
2682 	return Server;
2683 
2684     return Other;
2685 }
2686 
2687 /*!
2688     Returns a reference to the body of the SOAP message.
2689 */
body() const2690 QtSoapStruct &QtSoapMessage::body() const
2691 {
2692     const QtSoapQName bodyName("Body", SOAPv11_ENVELOPE);
2693 
2694     QtSoapType &bodyTmp = envelope[bodyName];
2695     if (!bodyTmp.isValid())
2696 	envelope.insert(new QtSoapStruct(bodyName));
2697 
2698     return (QtSoapStruct &)envelope[bodyName];
2699 }
2700 
2701 /*!
2702     Returns a reference to the header of the SOAP message.
2703 */
header() const2704 QtSoapStruct &QtSoapMessage::header() const
2705 {
2706     const QtSoapQName headerName("Header", SOAPv11_ENVELOPE);
2707 
2708     QtSoapType &headerTmp = envelope[headerName];
2709     if (!headerTmp.isValid())
2710 	envelope.insert(new QtSoapStruct(headerName));
2711 
2712     return (QtSoapStruct &)envelope[headerName];
2713 }
2714 
2715 /*!
2716     Sets the fault code of the SOAP Fault message to \a code.
2717 */
setFaultCode(FaultCode code)2718 void QtSoapMessage::setFaultCode(FaultCode code)
2719 {
2720     if (type != Fault && type != OtherType) {
2721 	clear();
2722 	type = Fault;
2723     }
2724 
2725     if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2726 	addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2727 
2728     QString codeStr;
2729     switch (code) {
2730     case VersionMismatch:
2731 	codeStr = "SOAP-ENV:VersionMismatch";
2732 	break;
2733     case MustUnderstand:
2734 	codeStr = "SOAP-ENV:MustUnderstand";
2735 	break;
2736     case Client:
2737 	codeStr = "SOAP-ENV:Client";
2738 	break;
2739     case Server:
2740 	codeStr = "SOAP-ENV:Server";
2741 	break;
2742     case Other:
2743 	codeStr = "Other";
2744 	break;
2745     }
2746 
2747     QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2748     QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2749     fault.insert(new QtSoapSimpleType(QtSoapQName("Faultcode"), codeStr));
2750 }
2751 
2752 /*!
2753     Sets the Fault faultstring of the SOAP Fault message to \a s.
2754 */
setFaultString(const QString & s)2755 void QtSoapMessage::setFaultString(const QString &s)
2756 {
2757     if (type != Fault && type != OtherType) {
2758 	clear();
2759 	type = Fault;
2760     }
2761 
2762     if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2763 	addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2764 
2765     QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2766     QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2767     fault.insert(new QtSoapSimpleType(QtSoapQName("Faultstring"), s));
2768 }
2769 
2770 /*!
2771    Adds the QtSoapType \a detail to the end of the list of faultdetail
2772    items in a SOAP Fault message.
2773 */
addFaultDetail(QtSoapType * detail)2774 void QtSoapMessage::addFaultDetail(QtSoapType *detail)
2775 {
2776     if (type != Fault && type != OtherType) {
2777 	clear();
2778 	type = Fault;
2779     }
2780 
2781     if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2782 	addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2783 
2784     QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2785     QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2786     if (!fault[QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)].isValid())
2787 	fault.insert(new QtSoapStruct(QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)));
2788 
2789     QtSoapType &node2 = fault[QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)];
2790     QtSoapStruct &fdetail = reinterpret_cast<QtSoapStruct &>(node2);
2791 
2792     fdetail.insert(detail);
2793 }
2794 
2795 /*!
2796     Returns the method of a SOAP method request or response
2797     as a QtSoapType.
2798 */
method() const2799 const QtSoapType &QtSoapMessage::method() const
2800 {
2801     static QtSoapType NIL;
2802 
2803     if (body().count() == 0)
2804 	return NIL;
2805 
2806     QtSoapStructIterator it(body());
2807 
2808     return *it.data();
2809 }
2810 
2811 /*!
2812     Sets the QName (qualified name) of the method to call in a SOAP
2813     method request to \a meth.
2814 
2815     This function \e must be called before calling
2816     addMethodArgument().
2817 */
setMethod(const QtSoapQName & meth)2818 void QtSoapMessage::setMethod(const QtSoapQName &meth)
2819 {
2820     if (type != MethodRequest && type != OtherType) {
2821 	clear();
2822 	type = MethodRequest;
2823     }
2824 
2825     addBodyItem(new QtSoapStruct(meth));
2826 }
2827 
2828 /*! \overload
2829 
2830     Sets the method name to \a name and uri to \a uri.
2831 */
setMethod(const QString & name,const QString & uri)2832 void QtSoapMessage::setMethod(const QString &name, const QString &uri)
2833 {
2834     setMethod(QtSoapQName(name, uri));
2835 }
2836 
2837 /*!
2838    Adds argument \a arg to the list of arguments that are passed in a
2839    SOAP method request.
2840 
2841    \warning setMethod() must be called before calling this function.
2842 */
addMethodArgument(QtSoapType * arg)2843 void QtSoapMessage::addMethodArgument(QtSoapType *arg)
2844 {
2845     if (body().count() == 0) {
2846 	qWarning("Attempted to add argument (%s:%s) without first setting method",
2847 		 arg->name().uri().toLatin1().constData(), arg->name().name().toLatin1().constData());
2848 	return;
2849     }
2850 
2851     QtSoapStructIterator it(body());
2852     QtSoapType &node = *it.data();
2853     QtSoapStruct &meth = static_cast<QtSoapStruct &>(node);
2854     meth.insert(arg);
2855 }
2856 
2857 /*! \overload
2858 
2859     Adds an argument called \a name with a uri of \a uri. The type
2860     of the argument is QtSoapType::String and its value is \a value.
2861 */
addMethodArgument(const QString & name,const QString & uri,const QString & value)2862 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, const QString &value)
2863 {
2864     addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value));
2865 }
2866 
2867 /*! \overload
2868 
2869     Adds an argument called \a name with a uri of \a uri. The type
2870     of the argument is QtSoapType::Boolean and its value is \a value.
2871 
2872     The \a dummy argument is used to distinguish this function from
2873     the overload which takes an int.
2874 */
addMethodArgument(const QString & name,const QString & uri,bool value,int dummy)2875 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, bool value, int dummy)
2876 {
2877     addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value, dummy));
2878 }
2879 
2880 /*! \overload
2881 
2882     Adds an argument called \a name with a uri of \a uri. The type
2883     of the argument is QtSoapType::Integer and its value is \a value.
2884 */
addMethodArgument(const QString & name,const QString & uri,int value)2885 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, int value)
2886 {
2887     addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value));
2888 }
2889 
2890 /*!
2891     Constructs a QtSoapTypeFactory and initializes it with all the
2892     known SOAP types.
2893 */
QtSoapTypeFactory()2894 QtSoapTypeFactory::QtSoapTypeFactory()
2895 {
2896     QtSoapTypeConstructor<QtSoapStruct> *structConstructor = new QtSoapTypeConstructor<QtSoapStruct>();
2897     deleteList.append(structConstructor);
2898     QtSoapTypeConstructor<QtSoapArray> *arrayConstructor = new QtSoapTypeConstructor<QtSoapArray>();
2899     deleteList.append(arrayConstructor);
2900     QtSoapTypeConstructor<QtSoapSimpleType> *basicTypeConstructor = new QtSoapTypeConstructor<QtSoapSimpleType>();
2901     deleteList.append(basicTypeConstructor);
2902 
2903     registerHandler("struct", structConstructor);
2904     registerHandler("array", arrayConstructor);
2905     registerHandler("string", basicTypeConstructor);
2906     registerHandler("normalizedstring", basicTypeConstructor);
2907     registerHandler("token", basicTypeConstructor);
2908     registerHandler("language", basicTypeConstructor);
2909     registerHandler("name", basicTypeConstructor);
2910     registerHandler("ncname", basicTypeConstructor);
2911     registerHandler("id", basicTypeConstructor);
2912     registerHandler("idref", basicTypeConstructor);
2913     registerHandler("entity", basicTypeConstructor);
2914     registerHandler("nmtoken", basicTypeConstructor);
2915     registerHandler("nmtokens", basicTypeConstructor);
2916     registerHandler("boolean", basicTypeConstructor);
2917     registerHandler("decimal", basicTypeConstructor);
2918     registerHandler("integer", basicTypeConstructor);
2919     registerHandler("nonpositiveinteger", basicTypeConstructor);
2920     registerHandler("negativeinteger", basicTypeConstructor);
2921     registerHandler("int", basicTypeConstructor);
2922     registerHandler("long", basicTypeConstructor);
2923     registerHandler("short", basicTypeConstructor);
2924     registerHandler("byte", basicTypeConstructor);
2925     registerHandler("nonnegativeinteger", basicTypeConstructor);
2926     registerHandler("unsignedlong", basicTypeConstructor);
2927     registerHandler("unsignedint", basicTypeConstructor);
2928     registerHandler("unsignedshort", basicTypeConstructor);
2929     registerHandler("unsignedbyte", basicTypeConstructor);
2930     registerHandler("positiveinteger", basicTypeConstructor);
2931     registerHandler("float", basicTypeConstructor);
2932     registerHandler("double", basicTypeConstructor);
2933     registerHandler("other", structConstructor);
2934 }
2935 
2936 /*!
2937     Destructs the QtSoapTypeFactory. This destructor is called when
2938     the application exits.
2939 */
~QtSoapTypeFactory()2940 QtSoapTypeFactory::~QtSoapTypeFactory()
2941 {
2942     QLinkedList<QtSoapTypeConstructorBase*>::ConstIterator it = deleteList.begin();
2943     while (it != deleteList.end()) {
2944         delete *it;
2945         ++it;
2946     }
2947 }
2948 
2949 /*!
2950     Returns a reference to the QtSoapTypeFactory singleton.
2951 */
instance()2952 QtSoapTypeFactory &QtSoapTypeFactory::instance()
2953 {
2954     static QtSoapTypeFactory factory;
2955     return factory;
2956 }
2957 
2958 /*!
2959     Registers a handler \a handler for a QtSoapType called \a name.
2960 */
registerHandler(const QString & name,QtSoapTypeConstructorBase * handler)2961 bool QtSoapTypeFactory::registerHandler(const QString &name, QtSoapTypeConstructorBase *handler)
2962 {
2963     if (typeHandlers.find(name) != typeHandlers.end()) {
2964 	errorStr = "A handler for " + name + " is already registered.";
2965 	return false;
2966     }
2967 
2968     typeHandlers.insert(name, handler);
2969     return true;
2970 }
2971 
2972 /*! \internal
2973 */
soapType(QDomNode node) const2974 QtSmartPtr<QtSoapType> QtSoapTypeFactory::soapType(QDomNode node) const
2975 {
2976     if (node.isNull() || !node.isElement())
2977 	return QtSmartPtr<QtSoapType>();
2978 
2979     QDomElement elem = node.toElement();
2980 
2981     QDomAttr attr = elem.attributeNode("type");
2982     QtSoapTypeConstructorBase *constructor = 0;
2983     if (!attr.isNull()) {
2984         QHash<QString, QtSoapTypeConstructorBase *>::ConstIterator it;
2985 	it = typeHandlers.find(localName(attr.value().toLower()));
2986         if (it != typeHandlers.end())
2987             constructor = *it;
2988     }
2989 
2990     if (attr.isNull() || !constructor) {
2991         QHash<QString, QtSoapTypeConstructorBase *>::ConstIterator it;
2992 	if (node.firstChild().isElement()) {
2993             if (localName(node.nodeName().toLower()) == "array") {
2994                 it = typeHandlers.find("array");
2995             } else
2996                 it = typeHandlers.find("struct");
2997         } else
2998 	    it = typeHandlers.find("string");
2999         if (it != typeHandlers.end())
3000             constructor = *it;
3001     }
3002 
3003     if (!constructor) {
3004 	return QtSmartPtr<QtSoapType>();
3005     }
3006 
3007     QtSoapType *type = constructor->createObject(node);
3008 
3009     if (!type)
3010 	errorStr = constructor->errorString();
3011 
3012     return QtSmartPtr<QtSoapType>(type);
3013 }
3014 
3015 /*!
3016     Returns a human readable interpretation of the last error
3017     that occurred.
3018 */
errorString() const3019 QString QtSoapTypeFactory::errorString() const
3020 {
3021     return errorStr;
3022 }
3023 
3024 /*! \class QtSoapHttpTransport
3025 
3026     \brief The QtSoapHttpTransport class provides a mechanism for
3027     transporting SOAP messages to and from other hosts using the
3028     HTTP protocol.
3029 
3030     Use this class to submit SOAP messages to a web service.
3031     Set the hostname of the SOAP server with setHost(). Some servers
3032     also require the SOAPAction header to be set, and you can do this
3033     with setAction(). Next, submit the request with submitRequest(),
3034     passing the message to submit together with the path that you want
3035     to submit the message to. The responseReady() signal is emitted
3036     when a response has been received. Call getResponse() to get the
3037     reponse from the service.
3038 
3039     QtSoapHttpTransport usage example: If a SOAP weather service was
3040     running on the host weather.example.com, the following code might
3041     be used to find the temperature in any given city:
3042 
3043     \code
3044     void WeatherFetcher::findTemperature(const QString &city)
3045     {
3046         QtSoapMessage message;
3047         message.setMethod("getTemperature", "http://weather.example.com/temperature");
3048         message.setMethodArgument("city", "", city);
3049 
3050         // transport is a private member of WeatherFetcher, of type QtSoapHttpTransport
3051         transport.setHost("www.example.com");
3052         connect(&transport, SIGNAL(responseReady()), SLOT(readResponse()));
3053 
3054         transport.submitRequest(message, "/weatherfetcher/fetch.asp");
3055     }
3056     \endcode
3057 
3058     This is an example implementation of the readResponse() slot in
3059     the WeatherFetcher class:
3060 
3061     \code
3062     void WeatherFetcher::readResponse()
3063     {
3064         const QtSoapMessage &response = transport.getResponse();
3065         if (response.isFault()) {
3066             cout << response.faultString().toString().toLatin1().constData() << endl;
3067             return;
3068         }
3069 
3070         const QtSoapType &returnValue = response.returnValue();
3071         if (returnValue["temperature"].isValid()) {
3072         cout << "The current temperature is "
3073              << returnValue["temperature"].toString().toLatin1().constData()
3074              << " degrees Celcius." << endl;
3075     }
3076     \endcode
3077 
3078     \sa QtSoapMessage, QtSoapType
3079 */
3080 
3081 /*! \fn void QtSoapHttpTransport::responseReady()
3082 
3083     This signal is emitted when a SOAP response is received from a
3084     remote peer.
3085 
3086     \sa getResponse()
3087 */
3088 
3089 /*! \fn void QtSoapHttpTransport::responseReady(const QtSoapMessage &response)
3090 
3091     This signal is emitted when a SOAP response is received from a
3092     remote peer. The received response is available in \a
3093     response. This signal is emitted in tandem with the argument-less
3094     responseReady() signal.
3095 
3096     \sa responseReady()
3097 */
3098 
3099 /*!
3100     Constructs a QtSoapHttpTransport object. Passes \a parent to
3101     QObject's constructor.
3102 */
3103 
QtSoapHttpTransport(QObject * parent)3104 QtSoapHttpTransport::QtSoapHttpTransport(QObject *parent)
3105     : QObject(parent), networkMgr(this)
3106 {
3107     connect(&networkMgr, SIGNAL(finished(QNetworkReply *)),
3108             SLOT(readResponse(QNetworkReply *)));
3109 }
3110 
3111 /*!
3112     Destructs a QtSoapHttpTransport.
3113 */
~QtSoapHttpTransport()3114 QtSoapHttpTransport::~QtSoapHttpTransport()
3115 {
3116 }
3117 
3118 /*!
3119   \obsolete
3120 */
3121 
setHost(const QString & host,int port)3122 void QtSoapHttpTransport::setHost(const QString &host, int port)
3123 {
3124     setHost(host, false, port);
3125 }
3126 
3127 /*!
3128   Sets the \a host this transport should connect to. The transport
3129   mode will be HTTP, unless \a useSecureHTTP is set, in which case it
3130   will be HTTPS. This transport will connect to the well-known ports
3131   by default (80 for HTTP, 443 for HTTPS), unless a different,
3132   non-zero port is specified in \a port.
3133 */
setHost(const QString & host,bool useSecureHTTP,int port)3134 void QtSoapHttpTransport::setHost(const QString &host, bool useSecureHTTP, int port)
3135 {
3136     url.setHost(host);
3137     url.setScheme(useSecureHTTP ? QLatin1String("https") : QLatin1String("http"));
3138     if (port)
3139         url.setPort(port);
3140     else
3141         url.setPort(useSecureHTTP ? 443 : 80);
3142 }
3143 
3144 /*!
3145     Sets the HTTP header SOAPAction to \a action.
3146 */
setAction(const QString & action)3147 void QtSoapHttpTransport::setAction(const QString &action)
3148 {
3149     soapAction = action;
3150 }
3151 
3152 /*!
3153     Submits the SOAP message \a request to the path \a path on the
3154     HTTP server set using setHost().
3155 */
submitRequest(QtSoapMessage & request,const QString & path)3156 void QtSoapHttpTransport::submitRequest(QtSoapMessage &request, const QString &path)
3157 {
3158     QNetworkRequest networkReq;
3159     networkReq.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/xml;charset=utf-8"));
3160     networkReq.setRawHeader("SOAPAction", soapAction.toUtf8().data());
3161     url.setPath(path);
3162     networkReq.setUrl(url);
3163 
3164     soapResponse.clear();
3165     networkRep = networkMgr.post(networkReq, request.toXmlString().toUtf8().constData());
3166 }
3167 
3168 
3169 /*!
3170     Returns the most recently received response SOAP message. This
3171     message could be a Fault message, so it is wise to check using
3172     QtSoapMessage::isFault() before processing the response.
3173 */
getResponse() const3174 const QtSoapMessage &QtSoapHttpTransport::getResponse() const
3175 {
3176     return soapResponse;
3177 }
3178 
3179 
3180 /*!
3181     Returns a pointer to the QNetworkAccessManager object used by this
3182     transport. This is useful if the application needs to connect to its
3183     signals, or set or read its cookie jar, etc.
3184 */
3185 
networkAccessManager()3186 QNetworkAccessManager *QtSoapHttpTransport::networkAccessManager()
3187 {
3188     return &networkMgr;
3189 }
3190 
3191 
3192 /*!
3193     Returns a pointer to the QNetworkReply object of the current (or last)
3194     request, or 0 if no such object is currently available.
3195 
3196     This is useful if the application needs to access the raw header
3197     data etc.
3198 */
3199 
networkReply()3200 QNetworkReply *QtSoapHttpTransport::networkReply()
3201 {
3202     return networkRep;
3203 }
3204 
3205 /*!
3206 
3207 */
3208 
readResponse(QNetworkReply * reply)3209 void QtSoapHttpTransport::readResponse(QNetworkReply *reply)
3210 {
3211     networkRep = reply;
3212     switch (reply->error()) {
3213     case QNetworkReply::NoError:
3214     case QNetworkReply::ContentAccessDenied:
3215     case QNetworkReply::ContentOperationNotPermittedError:
3216     case QNetworkReply::ContentNotFoundError:
3217     case QNetworkReply::UnknownContentError:
3218         {
3219             soapResponse.setContent(reply->readAll());
3220 
3221             int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
3222             if (httpStatus != 200 && httpStatus != 100) {
3223                 if (soapResponse.faultCode() == QtSoapMessage::Other)
3224                     soapResponse.setFaultCode(QtSoapMessage::Client);
3225                 /*
3226                 QString httpReason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
3227                 soapResponse.setFaultString(QString("HTTP status %2 (%3).\n%1").arg(soapResponse.faultString().toString()).arg(httpStatus).arg(httpReason));
3228                 */
3229             }
3230         }
3231         break;
3232     default:
3233         {
3234             soapResponse.setFaultCode(QtSoapMessage::Client);
3235             soapResponse.setFaultString(QString("Network transport error (%1): %2").arg(reply->error()).arg(reply->errorString()));
3236         }
3237         break;
3238     }
3239 
3240     emit responseReady();
3241     emit responseReady(soapResponse);
3242 
3243     reply->deleteLater();
3244 }
3245 
3246 /*! \class QtSoapNamespaces qtsoap.h
3247 
3248     \brief The QtSoapNamespaces class provides a registry for XML
3249     namespaces and prefixes for use in QtSoap.
3250 
3251     When a QtSoapMessage is converted to XML via
3252     QtSoapMessage::toXmlString(), this class is used to find
3253     appropriate XML namespace prefixes for the QNames (qualified
3254     names) in the message.
3255 
3256     To register a namespace with a prefix, call register().
3257     prefixFor() will then return the prefix that is registered for the
3258     given namespace, if any.
3259 
3260     To access the QtSoapNamespaces registry, call
3261     QtSoapNamespaces::instance().
3262 
3263     \code
3264     QtSoapNamespaces &registry = QtSoapNamespaces::instance();
3265 
3266     registry.register("pre", "http://www.example.com/");
3267     QString prefix = registry.prefixFor("http://www.example.com/"); // returns "pre"
3268     \endcode
3269 
3270     \sa QtSoapMessage
3271 */
3272 
3273 /*!
3274     Returns a reference to the QtSoapNamespaces singleton.
3275 */
instance()3276 QtSoapNamespaces &QtSoapNamespaces::instance()
3277 {
3278     static QtSoapNamespaces ns;
3279     return ns;
3280 }
3281 
3282 /*! \internal
3283 
3284     Constructs a QtSoapNamespaces object.
3285 */
QtSoapNamespaces()3286 QtSoapNamespaces::QtSoapNamespaces()
3287 {
3288 }
3289 
3290 /*!
3291     Registers the namespace \a uri with the prefix \a prefix.
3292 */
registerNamespace(const QString & prefix,const QString & uri)3293 void QtSoapNamespaces::registerNamespace(const QString &prefix, const QString &uri)
3294 {
3295     namespaces.insert(uri, prefix);
3296 }
3297 
3298 /*!
3299     Returns the prefix for the namespace \a uri, or an empty string if
3300     no prefix has been registered for \a uri.
3301 */
prefixFor(const QString & uri)3302 QString QtSoapNamespaces::prefixFor(const QString &uri)
3303 {
3304     return namespaces.value(uri);
3305 }
3306