summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-03-28 15:46:49 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-03-28 15:46:49 (GMT)
commitf53a1ef582494458301b97bf6e546be52d7ff7e8 (patch)
tree7571b5cbcbd8a8f1dd1c966c9045b6cb69f0e295 /Swiften/Parser
parent638345680d72ca6acaf123f2c8c1c391f696e371 (diff)
downloadswift-contrib-f53a1ef582494458301b97bf6e546be52d7ff7e8.zip
swift-contrib-f53a1ef582494458301b97bf6e546be52d7ff7e8.tar.bz2
Moving submodule contents back.
Diffstat (limited to 'Swiften/Parser')
-rw-r--r--Swiften/Parser/AttributeMap.h35
-rw-r--r--Swiften/Parser/AuthChallengeParser.cpp24
-rw-r--r--Swiften/Parser/AuthChallengeParser.h20
-rw-r--r--Swiften/Parser/AuthFailureParser.h14
-rw-r--r--Swiften/Parser/AuthRequestParser.cpp27
-rw-r--r--Swiften/Parser/AuthRequestParser.h23
-rw-r--r--Swiften/Parser/AuthResponseParser.cpp24
-rw-r--r--Swiften/Parser/AuthResponseParser.h20
-rw-r--r--Swiften/Parser/AuthSuccessParser.cpp24
-rw-r--r--Swiften/Parser/AuthSuccessParser.h20
-rw-r--r--Swiften/Parser/CompressFailureParser.h14
-rw-r--r--Swiften/Parser/CompressParser.cpp28
-rw-r--r--Swiften/Parser/CompressParser.h25
-rw-r--r--Swiften/Parser/CompressedParser.h14
-rw-r--r--Swiften/Parser/ElementParser.cpp8
-rw-r--r--Swiften/Parser/ElementParser.h23
-rw-r--r--Swiften/Parser/ExpatParser.cpp70
-rw-r--r--Swiften/Parser/ExpatParser.h22
-rw-r--r--Swiften/Parser/GenericElementParser.h43
-rw-r--r--Swiften/Parser/GenericPayloadParser.h32
-rw-r--r--Swiften/Parser/GenericPayloadParserFactory.h28
-rw-r--r--Swiften/Parser/GenericStanzaParser.h33
-rw-r--r--Swiften/Parser/IQParser.cpp33
-rw-r--r--Swiften/Parser/IQParser.h17
-rw-r--r--Swiften/Parser/LibXMLParser.cpp65
-rw-r--r--Swiften/Parser/LibXMLParser.h20
-rw-r--r--Swiften/Parser/MessageParser.cpp33
-rw-r--r--Swiften/Parser/MessageParser.h17
-rw-r--r--Swiften/Parser/PayloadParser.cpp8
-rw-r--r--Swiften/Parser/PayloadParser.h24
-rw-r--r--Swiften/Parser/PayloadParserFactory.cpp8
-rw-r--r--Swiften/Parser/PayloadParserFactory.h19
-rw-r--r--Swiften/Parser/PayloadParserFactoryCollection.cpp31
-rw-r--r--Swiften/Parser/PayloadParserFactoryCollection.h28
-rw-r--r--Swiften/Parser/PayloadParsers/BodyParser.cpp23
-rw-r--r--Swiften/Parser/PayloadParsers/BodyParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/BodyParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/ChatStateParser.cpp35
-rw-r--r--Swiften/Parser/PayloadParsers/ChatStateParser.h18
-rw-r--r--Swiften/Parser/PayloadParsers/ChatStateParserFactory.h25
-rw-r--r--Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp27
-rw-r--r--Swiften/Parser/PayloadParsers/DiscoInfoParser.h25
-rw-r--r--Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/ErrorParser.cpp109
-rw-r--r--Swiften/Parser/PayloadParsers/ErrorParser.h26
-rw-r--r--Swiften/Parser/PayloadParsers/ErrorParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp61
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h19
-rw-r--r--Swiften/Parser/PayloadParsers/PriorityParser.cpp25
-rw-r--r--Swiften/Parser/PayloadParsers/PriorityParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/PriorityParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp43
-rw-r--r--Swiften/Parser/PayloadParsers/PrivateStorageParser.h25
-rw-r--r--Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h26
-rw-r--r--Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp26
-rw-r--r--Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h20
-rw-r--r--Swiften/Parser/PayloadParsers/ResourceBindParser.cpp37
-rw-r--r--Swiften/Parser/PayloadParsers/ResourceBindParser.h24
-rw-r--r--Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/RosterParser.cpp66
-rw-r--r--Swiften/Parser/PayloadParsers/RosterParser.h29
-rw-r--r--Swiften/Parser/PayloadParsers/RosterParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp59
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelParser.h31
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp55
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h32
-rw-r--r--Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp32
-rw-r--r--Swiften/Parser/PayloadParsers/SoftwareVersionParser.h26
-rw-r--r--Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/StartSessionParser.h18
-rw-r--r--Swiften/Parser/PayloadParsers/StartSessionParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/StatusParser.cpp23
-rw-r--r--Swiften/Parser/PayloadParsers/StatusParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/StatusParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/StatusShowParser.cpp37
-rw-r--r--Swiften/Parser/PayloadParsers/StatusShowParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/StatusShowParserFactory.h14
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParser.cpp49
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParser.h27
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParserFactory.h11
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp28
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp47
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp34
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h8
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h55
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp28
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp89
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp34
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp38
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp50
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp45
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp45
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp35
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp28
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp68
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp64
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp51
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp31
-rw-r--r--Swiften/Parser/PayloadParsers/VCardParser.cpp53
-rw-r--r--Swiften/Parser/PayloadParsers/VCardParser.h24
-rw-r--r--Swiften/Parser/PayloadParsers/VCardParserFactory.h11
-rw-r--r--Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp26
-rw-r--r--Swiften/Parser/PayloadParsers/VCardUpdateParser.h25
-rw-r--r--Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h11
-rw-r--r--Swiften/Parser/PlatformXMLParserFactory.cpp25
-rw-r--r--Swiften/Parser/PlatformXMLParserFactory.h15
-rw-r--r--Swiften/Parser/PresenceParser.cpp45
-rw-r--r--Swiften/Parser/PresenceParser.h17
-rw-r--r--Swiften/Parser/SConscript58
-rw-r--r--Swiften/Parser/SerializingParser.cpp41
-rw-r--r--Swiften/Parser/SerializingParser.h25
-rw-r--r--Swiften/Parser/StanzaParser.cpp78
-rw-r--r--Swiften/Parser/StanzaParser.h48
-rw-r--r--Swiften/Parser/StartTLSFailureParser.h14
-rw-r--r--Swiften/Parser/StartTLSParser.h14
-rw-r--r--Swiften/Parser/StreamFeaturesParser.cpp61
-rw-r--r--Swiften/Parser/StreamFeaturesParser.h28
-rw-r--r--Swiften/Parser/TLSProceedParser.h14
-rw-r--r--Swiften/Parser/UnitTest/AttributeMapTest.cpp71
-rw-r--r--Swiften/Parser/UnitTest/ElementParserTester.h10
-rw-r--r--Swiften/Parser/UnitTest/IQParserTest.cpp70
-rw-r--r--Swiften/Parser/UnitTest/MessageParserTest.cpp80
-rw-r--r--Swiften/Parser/UnitTest/ParserTester.h44
-rw-r--r--Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp97
-rw-r--r--Swiften/Parser/UnitTest/PresenceParserTest.cpp110
-rw-r--r--Swiften/Parser/UnitTest/SerializingParserTest.cpp58
-rw-r--r--Swiften/Parser/UnitTest/StanzaParserTest.cpp209
-rw-r--r--Swiften/Parser/UnitTest/StanzaParserTester.h11
-rw-r--r--Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp63
-rw-r--r--Swiften/Parser/UnitTest/XMLParserTest.cpp229
-rw-r--r--Swiften/Parser/UnitTest/XMPPParserTest.cpp186
-rw-r--r--Swiften/Parser/UnknownElementParser.h14
-rw-r--r--Swiften/Parser/UnknownPayloadParser.h25
-rw-r--r--Swiften/Parser/XMLParser.cpp11
-rw-r--r--Swiften/Parser/XMLParser.h25
-rw-r--r--Swiften/Parser/XMLParserClient.cpp9
-rw-r--r--Swiften/Parser/XMLParserClient.h19
-rw-r--r--Swiften/Parser/XMLParserFactory.cpp8
-rw-r--r--Swiften/Parser/XMLParserFactory.h16
-rw-r--r--Swiften/Parser/XMPPParser.cpp159
-rw-r--r--Swiften/Parser/XMPPParser.h54
-rw-r--r--Swiften/Parser/XMPPParserClient.cpp8
-rw-r--r--Swiften/Parser/XMPPParserClient.h19
146 files changed, 5257 insertions, 0 deletions
diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h
new file mode 100644
index 0000000..82c839a
--- /dev/null
+++ b/Swiften/Parser/AttributeMap.h
@@ -0,0 +1,35 @@
+#ifndef ATTRIBUTEMAP_H
+#define ATTRIBUTEMAP_H
+
+#include <map>
+
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class AttributeMap : public std::map<String,String> {
+ public:
+ AttributeMap() {}
+
+ String getAttribute(const String& attribute) const {
+ AttributeMap::const_iterator i = find(attribute);
+ if (i == end()) {
+ return "";
+ }
+ else {
+ return i->second;
+ }
+ }
+
+ bool getBoolAttribute(const String& attribute, bool defaultValue = false) const {
+ AttributeMap::const_iterator i = find(attribute);
+ if (i == end()) {
+ return defaultValue;
+ }
+ else {
+ return i->second == "true" || i->second == "1";
+ }
+ }
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/AuthChallengeParser.cpp b/Swiften/Parser/AuthChallengeParser.cpp
new file mode 100644
index 0000000..c83cf7d
--- /dev/null
+++ b/Swiften/Parser/AuthChallengeParser.cpp
@@ -0,0 +1,24 @@
+#include "Swiften/Parser/AuthChallengeParser.h"
+#include "Swiften/StringCodecs/Base64.h"
+
+namespace Swift {
+
+AuthChallengeParser::AuthChallengeParser() : GenericElementParser<AuthChallenge>(), depth(0) {
+}
+
+void AuthChallengeParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++depth;
+}
+
+void AuthChallengeParser::handleEndElement(const String&, const String&) {
+ --depth;
+ if (depth == 0) {
+ getElementGeneric()->setValue(Base64::decode(text));
+ }
+}
+
+void AuthChallengeParser::handleCharacterData(const String& text) {
+ this->text += text;
+}
+
+}
diff --git a/Swiften/Parser/AuthChallengeParser.h b/Swiften/Parser/AuthChallengeParser.h
new file mode 100644
index 0000000..be44b96
--- /dev/null
+++ b/Swiften/Parser/AuthChallengeParser.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/AuthChallenge.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class AuthChallengeParser : public GenericElementParser<AuthChallenge> {
+ public:
+ AuthChallengeParser();
+
+ virtual void handleStartElement(const String&, const String& ns, const AttributeMap&);
+ virtual void handleEndElement(const String&, const String& ns);
+ virtual void handleCharacterData(const String&);
+
+ private:
+ int depth;
+ String text;
+ };
+}
diff --git a/Swiften/Parser/AuthFailureParser.h b/Swiften/Parser/AuthFailureParser.h
new file mode 100644
index 0000000..3a950ef
--- /dev/null
+++ b/Swiften/Parser/AuthFailureParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_AuthFailureParser_H
+#define SWIFTEN_AuthFailureParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/AuthFailure.h"
+
+namespace Swift {
+ class AuthFailureParser : public GenericElementParser<AuthFailure> {
+ public:
+ AuthFailureParser() : GenericElementParser<AuthFailure>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/AuthRequestParser.cpp b/Swiften/Parser/AuthRequestParser.cpp
new file mode 100644
index 0000000..5338b88
--- /dev/null
+++ b/Swiften/Parser/AuthRequestParser.cpp
@@ -0,0 +1,27 @@
+#include "Swiften/Parser/AuthRequestParser.h"
+#include "Swiften/StringCodecs/Base64.h"
+
+namespace Swift {
+
+AuthRequestParser::AuthRequestParser() : GenericElementParser<AuthRequest>(), depth_(0) {
+}
+
+void AuthRequestParser::handleStartElement(const String&, const String&, const AttributeMap& attribute) {
+ if (depth_ == 0) {
+ getElementGeneric()->setMechanism(attribute.getAttribute("mechanism"));
+ }
+ ++depth_;
+}
+
+void AuthRequestParser::handleEndElement(const String&, const String&) {
+ --depth_;
+ if (depth_ == 0) {
+ getElementGeneric()->setMessage(Base64::decode(text_));
+ }
+}
+
+void AuthRequestParser::handleCharacterData(const String& text) {
+ text_ += text;
+}
+
+}
diff --git a/Swiften/Parser/AuthRequestParser.h b/Swiften/Parser/AuthRequestParser.h
new file mode 100644
index 0000000..8916922
--- /dev/null
+++ b/Swiften/Parser/AuthRequestParser.h
@@ -0,0 +1,23 @@
+#ifndef SWIFTEN_AuthRequestParser_H
+#define SWIFTEN_AuthRequestParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/AuthRequest.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class AuthRequestParser : public GenericElementParser<AuthRequest> {
+ public:
+ AuthRequestParser();
+
+ virtual void handleStartElement(const String&, const String& ns, const AttributeMap&);
+ virtual void handleEndElement(const String&, const String& ns);
+ virtual void handleCharacterData(const String&);
+
+ private:
+ String text_;
+ int depth_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/AuthResponseParser.cpp b/Swiften/Parser/AuthResponseParser.cpp
new file mode 100644
index 0000000..b5976a5
--- /dev/null
+++ b/Swiften/Parser/AuthResponseParser.cpp
@@ -0,0 +1,24 @@
+#include "Swiften/Parser/AuthResponseParser.h"
+#include "Swiften/StringCodecs/Base64.h"
+
+namespace Swift {
+
+AuthResponseParser::AuthResponseParser() : GenericElementParser<AuthResponse>(), depth(0) {
+}
+
+void AuthResponseParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++depth;
+}
+
+void AuthResponseParser::handleEndElement(const String&, const String&) {
+ --depth;
+ if (depth == 0) {
+ getElementGeneric()->setValue(Base64::decode(text));
+ }
+}
+
+void AuthResponseParser::handleCharacterData(const String& text) {
+ this->text += text;
+}
+
+}
diff --git a/Swiften/Parser/AuthResponseParser.h b/Swiften/Parser/AuthResponseParser.h
new file mode 100644
index 0000000..f2b3a9e
--- /dev/null
+++ b/Swiften/Parser/AuthResponseParser.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/AuthResponse.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class AuthResponseParser : public GenericElementParser<AuthResponse> {
+ public:
+ AuthResponseParser();
+
+ virtual void handleStartElement(const String&, const String& ns, const AttributeMap&);
+ virtual void handleEndElement(const String&, const String& ns);
+ virtual void handleCharacterData(const String&);
+
+ private:
+ int depth;
+ String text;
+ };
+}
diff --git a/Swiften/Parser/AuthSuccessParser.cpp b/Swiften/Parser/AuthSuccessParser.cpp
new file mode 100644
index 0000000..2dc2aa2
--- /dev/null
+++ b/Swiften/Parser/AuthSuccessParser.cpp
@@ -0,0 +1,24 @@
+#include "Swiften/Parser/AuthSuccessParser.h"
+#include "Swiften/StringCodecs/Base64.h"
+
+namespace Swift {
+
+AuthSuccessParser::AuthSuccessParser() : GenericElementParser<AuthSuccess>(), depth(0) {
+}
+
+void AuthSuccessParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++depth;
+}
+
+void AuthSuccessParser::handleEndElement(const String&, const String&) {
+ --depth;
+ if (depth == 0) {
+ getElementGeneric()->setValue(Base64::decode(text));
+ }
+}
+
+void AuthSuccessParser::handleCharacterData(const String& text) {
+ this->text += text;
+}
+
+}
diff --git a/Swiften/Parser/AuthSuccessParser.h b/Swiften/Parser/AuthSuccessParser.h
new file mode 100644
index 0000000..5d987c5
--- /dev/null
+++ b/Swiften/Parser/AuthSuccessParser.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/AuthSuccess.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class AuthSuccessParser : public GenericElementParser<AuthSuccess> {
+ public:
+ AuthSuccessParser();
+
+ virtual void handleStartElement(const String&, const String& ns, const AttributeMap&);
+ virtual void handleEndElement(const String&, const String& ns);
+ virtual void handleCharacterData(const String&);
+
+ private:
+ int depth;
+ String text;
+ };
+}
diff --git a/Swiften/Parser/CompressFailureParser.h b/Swiften/Parser/CompressFailureParser.h
new file mode 100644
index 0000000..d53e0ef
--- /dev/null
+++ b/Swiften/Parser/CompressFailureParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_CompressFailureParser_H
+#define SWIFTEN_CompressFailureParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/CompressFailure.h"
+
+namespace Swift {
+ class CompressFailureParser : public GenericElementParser<CompressFailure> {
+ public:
+ CompressFailureParser() : GenericElementParser<CompressFailure>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/CompressParser.cpp b/Swiften/Parser/CompressParser.cpp
new file mode 100644
index 0000000..7ca752d
--- /dev/null
+++ b/Swiften/Parser/CompressParser.cpp
@@ -0,0 +1,28 @@
+#include "Swiften/Parser/CompressParser.h"
+
+namespace Swift {
+
+CompressParser::CompressParser() : GenericElementParser<CompressRequest>(), currentDepth_(0), inMethod_(false) {
+}
+
+void CompressParser::handleStartElement(const String& element, const String&, const AttributeMap&) {
+ if (currentDepth_ == 1 && element == "method") {
+ inMethod_ = true;
+ currentText_ = "";
+ }
+ ++currentDepth_;
+}
+
+void CompressParser::handleEndElement(const String&, const String&) {
+ --currentDepth_;
+ if (currentDepth_ == 1 && inMethod_) {
+ getElementGeneric()->setMethod(currentText_);
+ inMethod_ = false;
+ }
+}
+
+void CompressParser::handleCharacterData(const String& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/CompressParser.h b/Swiften/Parser/CompressParser.h
new file mode 100644
index 0000000..8931778
--- /dev/null
+++ b/Swiften/Parser/CompressParser.h
@@ -0,0 +1,25 @@
+#ifndef SWIFTEN_CompressParser_H
+#define SWIFTEN_CompressParser_H
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/CompressRequest.h"
+
+namespace Swift {
+ class CompressParser : public GenericElementParser<CompressRequest> {
+ public:
+ CompressParser();
+
+ private:
+ void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes);
+ void handleEndElement(const String& element, const String& ns);
+ void handleCharacterData(const String& data);
+
+ private:
+ int currentDepth_;
+ String currentText_;
+ bool inMethod_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/CompressedParser.h b/Swiften/Parser/CompressedParser.h
new file mode 100644
index 0000000..365f619
--- /dev/null
+++ b/Swiften/Parser/CompressedParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_COMPRESSEDPARSER_H
+#define SWIFTEN_COMPRESSEDPARSER_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/Compressed.h"
+
+namespace Swift {
+ class CompressedParser : public GenericElementParser<Compressed> {
+ public:
+ CompressedParser() : GenericElementParser<Compressed>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/ElementParser.cpp b/Swiften/Parser/ElementParser.cpp
new file mode 100644
index 0000000..1c04d92
--- /dev/null
+++ b/Swiften/Parser/ElementParser.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/Parser/ElementParser.h"
+
+namespace Swift {
+
+ElementParser::~ElementParser() {
+}
+
+}
diff --git a/Swiften/Parser/ElementParser.h b/Swiften/Parser/ElementParser.h
new file mode 100644
index 0000000..3848f0c
--- /dev/null
+++ b/Swiften/Parser/ElementParser.h
@@ -0,0 +1,23 @@
+#ifndef SWIFTEN_ElementParser_H
+#define SWIFTEN_ElementParser_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Elements/Element.h"
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class ElementParser {
+ public:
+ virtual ~ElementParser();
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) = 0;
+ virtual void handleEndElement(const String& element, const String& ns) = 0;
+ virtual void handleCharacterData(const String& data) = 0;
+
+ virtual boost::shared_ptr<Element> getElement() const = 0;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp
new file mode 100644
index 0000000..6f7ff86
--- /dev/null
+++ b/Swiften/Parser/ExpatParser.cpp
@@ -0,0 +1,70 @@
+#include "Swiften/Parser/ExpatParser.h"
+
+#include <iostream>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/XMLParserClient.h"
+
+namespace Swift {
+
+static const char NAMESPACE_SEPARATOR = '\x01';
+
+static void handleStartElement(void* client, const XML_Char* name, const XML_Char** attributes) {
+ std::pair<String,String> nsTagPair = String(name).getSplittedAtFirst(NAMESPACE_SEPARATOR);
+ if (nsTagPair.second == "") {
+ nsTagPair.second = nsTagPair.first;
+ nsTagPair.first = "";
+ }
+ AttributeMap attributeValues;
+ const XML_Char** currentAttribute = attributes;
+ while (*currentAttribute) {
+ std::pair<String,String> nsAttributePair = String(*currentAttribute).getSplittedAtFirst(NAMESPACE_SEPARATOR);
+ if (nsAttributePair.second == "") {
+ nsAttributePair.second = nsAttributePair.first;
+ nsAttributePair.first = "";
+ }
+ attributeValues[nsAttributePair.second] = String(*(currentAttribute+1));
+ currentAttribute += 2;
+ }
+
+ static_cast<XMLParserClient*>(client)->handleStartElement(nsTagPair.second, nsTagPair.first, attributeValues);
+}
+
+static void handleEndElement(void* client, const XML_Char* name) {
+ std::pair<String,String> nsTagPair = String(name).getSplittedAtFirst(NAMESPACE_SEPARATOR);
+ if (nsTagPair.second == "") {
+ nsTagPair.second = nsTagPair.first;
+ nsTagPair.first = "";
+ }
+ static_cast<XMLParserClient*>(client)->handleEndElement(nsTagPair.second, nsTagPair.first);
+}
+
+static void handleCharacterData(void* client, const XML_Char* data, int len) {
+ static_cast<XMLParserClient*>(client)->handleCharacterData(String(data, len));
+}
+
+static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) {
+}
+
+
+ExpatParser::ExpatParser(XMLParserClient* client) : XMLParser(client) {
+ parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR);
+ XML_SetUserData(parser_, client);
+ XML_SetElementHandler(parser_, handleStartElement, handleEndElement);
+ XML_SetCharacterDataHandler(parser_, handleCharacterData);
+ XML_SetXmlDeclHandler(parser_, handleXMLDeclaration);
+}
+
+ExpatParser::~ExpatParser() {
+ XML_ParserFree(parser_);
+}
+
+bool ExpatParser::parse(const String& data) {
+ bool success = XML_Parse(parser_, data.getUTF8Data(), data.getUTF8Size(), false) == XML_STATUS_OK;
+ /*if (!success) {
+ std::cout << "ERROR: " << XML_ErrorString(XML_GetErrorCode(parser_)) << " while parsing " << data << std::endl;
+ }*/
+ return success;
+}
+
+}
diff --git a/Swiften/Parser/ExpatParser.h b/Swiften/Parser/ExpatParser.h
new file mode 100644
index 0000000..2b5e646
--- /dev/null
+++ b/Swiften/Parser/ExpatParser.h
@@ -0,0 +1,22 @@
+#ifndef SWIFTEN_ExpatParser_H
+#define SWIFTEN_ExpatParser_H
+
+#include <expat.h>
+#include <boost/noncopyable.hpp>
+
+#include "Swiften/Parser/XMLParser.h"
+
+namespace Swift {
+ class ExpatParser : public XMLParser, public boost::noncopyable {
+ public:
+ ExpatParser(XMLParserClient* client);
+ ~ExpatParser();
+
+ bool parse(const String& data);
+
+ private:
+ XML_Parser parser_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/GenericElementParser.h b/Swiften/Parser/GenericElementParser.h
new file mode 100644
index 0000000..e1b9cf7
--- /dev/null
+++ b/Swiften/Parser/GenericElementParser.h
@@ -0,0 +1,43 @@
+#ifndef SWIFTEN_GenericElementParser_H
+#define SWIFTEN_GenericElementParser_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Parser/ElementParser.h"
+
+namespace Swift {
+ class String;
+ class PayloadParserFactoryCollection;
+
+ template<typename ElementType>
+ class GenericElementParser : public ElementParser {
+ public:
+ GenericElementParser() {
+ stanza_ = boost::shared_ptr<ElementType>(new ElementType());
+ }
+
+ virtual boost::shared_ptr<Element> getElement() const {
+ return stanza_;
+ }
+
+ protected:
+ virtual boost::shared_ptr<ElementType> getElementGeneric() const {
+ return stanza_;
+ }
+
+ private:
+ virtual void handleStartElement(const String&, const String&, const AttributeMap&) {
+ }
+
+ virtual void handleEndElement(const String&, const String&) {
+ }
+
+ virtual void handleCharacterData(const String&) {
+ }
+
+ private:
+ boost::shared_ptr<ElementType> stanza_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/GenericPayloadParser.h b/Swiften/Parser/GenericPayloadParser.h
new file mode 100644
index 0000000..a07b795
--- /dev/null
+++ b/Swiften/Parser/GenericPayloadParser.h
@@ -0,0 +1,32 @@
+#ifndef GENERICPAYLOADPARSER_H
+#define GENERICPAYLOADPARSER_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Parser/PayloadParser.h"
+
+namespace Swift {
+ class String;
+
+ template<typename PAYLOAD_TYPE>
+ class GenericPayloadParser : public PayloadParser {
+ public:
+ GenericPayloadParser() : PayloadParser() {
+ payload_ = boost::shared_ptr<PAYLOAD_TYPE>(new PAYLOAD_TYPE());
+ }
+
+ virtual boost::shared_ptr<Payload> getPayload() const {
+ return payload_;
+ }
+
+ protected:
+ virtual boost::shared_ptr<PAYLOAD_TYPE> getPayloadInternal() const {
+ return payload_;
+ }
+
+ private:
+ boost::shared_ptr<PAYLOAD_TYPE> payload_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/GenericPayloadParserFactory.h b/Swiften/Parser/GenericPayloadParserFactory.h
new file mode 100644
index 0000000..d537b46
--- /dev/null
+++ b/Swiften/Parser/GenericPayloadParserFactory.h
@@ -0,0 +1,28 @@
+#ifndef SWIFTEN_GENERICPAYLOADPARSERFACTORY_H
+#define SWIFTEN_GENERICPAYLOADPARSERFACTORY_H
+
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+
+ template<typename PARSER_TYPE>
+ class GenericPayloadParserFactory : public PayloadParserFactory {
+ public:
+ GenericPayloadParserFactory(const String& tag, const String& xmlns = "") : tag_(tag), xmlns_(xmlns) {}
+
+ virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const {
+ return element == tag_ && (xmlns_.isEmpty() ? true : xmlns_ == ns);
+ }
+
+ virtual PayloadParser* createPayloadParser() {
+ return new PARSER_TYPE();
+ }
+
+ private:
+ String tag_;
+ String xmlns_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/GenericStanzaParser.h b/Swiften/Parser/GenericStanzaParser.h
new file mode 100644
index 0000000..ba1807a
--- /dev/null
+++ b/Swiften/Parser/GenericStanzaParser.h
@@ -0,0 +1,33 @@
+#ifndef SWIFTEN_GenericStanzaParser_H
+#define SWIFTEN_GenericStanzaParser_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Parser/StanzaParser.h"
+
+namespace Swift {
+ class String;
+ class PayloadParserFactoryCollection;
+
+ template<typename STANZA_TYPE>
+ class GenericStanzaParser : public StanzaParser {
+ public:
+ GenericStanzaParser(PayloadParserFactoryCollection* collection) :
+ StanzaParser(collection) {
+ stanza_ = boost::shared_ptr<STANZA_TYPE>(new STANZA_TYPE());
+ }
+
+ virtual boost::shared_ptr<Element> getElement() const {
+ return stanza_;
+ }
+
+ virtual boost::shared_ptr<STANZA_TYPE> getStanzaGeneric() const {
+ return stanza_;
+ }
+
+ private:
+ boost::shared_ptr<STANZA_TYPE> stanza_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/IQParser.cpp b/Swiften/Parser/IQParser.cpp
new file mode 100644
index 0000000..2b4b364
--- /dev/null
+++ b/Swiften/Parser/IQParser.cpp
@@ -0,0 +1,33 @@
+#include <iostream>
+
+#include "Swiften/Parser/IQParser.h"
+
+namespace Swift {
+
+IQParser::IQParser(PayloadParserFactoryCollection* factories) :
+ GenericStanzaParser<IQ>(factories) {
+}
+
+void IQParser::handleStanzaAttributes(const AttributeMap& attributes) {
+ AttributeMap::const_iterator type = attributes.find("type");
+ if (type != attributes.end()) {
+ if (type->second == "set") {
+ getStanzaGeneric()->setType(IQ::Set);
+ }
+ else if (type->second == "get") {
+ getStanzaGeneric()->setType(IQ::Get);
+ }
+ else if (type->second == "result") {
+ getStanzaGeneric()->setType(IQ::Result);
+ }
+ else if (type->second == "error") {
+ getStanzaGeneric()->setType(IQ::Error);
+ }
+ else {
+ std::cerr << "Unknown IQ type: " << type->second << std::endl;
+ getStanzaGeneric()->setType(IQ::Get);
+ }
+ }
+}
+
+}
diff --git a/Swiften/Parser/IQParser.h b/Swiften/Parser/IQParser.h
new file mode 100644
index 0000000..cd2fc05
--- /dev/null
+++ b/Swiften/Parser/IQParser.h
@@ -0,0 +1,17 @@
+#ifndef SWIFTEN_IQParser_H
+#define SWIFTEN_IQParser_H
+
+#include "Swiften/Parser/GenericStanzaParser.h"
+#include "Swiften/Elements/IQ.h"
+
+namespace Swift {
+ class IQParser : public GenericStanzaParser<IQ> {
+ public:
+ IQParser(PayloadParserFactoryCollection* factories);
+
+ private:
+ virtual void handleStanzaAttributes(const AttributeMap&);
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp
new file mode 100644
index 0000000..f43ed00
--- /dev/null
+++ b/Swiften/Parser/LibXMLParser.cpp
@@ -0,0 +1,65 @@
+#include "Swiften/Parser/LibXMLParser.h"
+
+#include <iostream>
+#include <cassert>
+#include <cstring>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/XMLParserClient.h"
+
+namespace Swift {
+
+static void handleStartElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int, const xmlChar ** attributes) {
+ AttributeMap attributeValues;
+ for (int i = 0; i < nbAttributes*5; i += 5) {
+ attributeValues[String(reinterpret_cast<const char*>(attributes[i]))] = String(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3]);
+ }
+ static_cast<XMLParserClient*>(client)->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : String()), attributeValues);
+}
+
+static void handleEndElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns) {
+ static_cast<XMLParserClient*>(client)->handleEndElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : String()));
+}
+
+static void handleCharacterData(void* client, const xmlChar* data, int len) {
+ static_cast<XMLParserClient*>(client)->handleCharacterData(String(reinterpret_cast<const char*>(data), len));
+}
+
+static void handleError(void*, const char*, ... ) {
+ /*
+ va_list args;
+ va_start(args, m);
+ vfprintf(stdout, m, args);
+ va_end(args);
+ */
+}
+
+static void handleWarning(void*, const char*, ... ) {
+}
+
+
+
+LibXMLParser::LibXMLParser(XMLParserClient* client) : XMLParser(client) {
+ memset(&handler_, 0, sizeof(handler_) );
+ handler_.initialized = XML_SAX2_MAGIC;
+ handler_.startElementNs = &handleStartElement;
+ handler_.endElementNs = &handleEndElement;
+ handler_.characters = &handleCharacterData;
+ handler_.warning = &handleWarning;
+ handler_.error = &handleError;
+
+ context_ = xmlCreatePushParserCtxt(&handler_, client, 0, 0, 0);
+ assert(context_);
+}
+
+LibXMLParser::~LibXMLParser() {
+ if (context_) {
+ xmlFreeParserCtxt(context_);
+ }
+}
+
+bool LibXMLParser::parse(const String& data) {
+ return xmlParseChunk(context_, data.getUTF8Data(), data.getUTF8Size(), false) == XML_ERR_OK;
+}
+
+}
diff --git a/Swiften/Parser/LibXMLParser.h b/Swiften/Parser/LibXMLParser.h
new file mode 100644
index 0000000..58a65f1
--- /dev/null
+++ b/Swiften/Parser/LibXMLParser.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <libxml/parser.h>
+#include <boost/noncopyable.hpp>
+
+#include "Swiften/Parser/XMLParser.h"
+
+namespace Swift {
+ class LibXMLParser : public XMLParser, public boost::noncopyable {
+ public:
+ LibXMLParser(XMLParserClient* client);
+ ~LibXMLParser();
+
+ bool parse(const String& data);
+
+ private:
+ xmlSAXHandler handler_;
+ xmlParserCtxtPtr context_;
+ };
+}
diff --git a/Swiften/Parser/MessageParser.cpp b/Swiften/Parser/MessageParser.cpp
new file mode 100644
index 0000000..5e83fad
--- /dev/null
+++ b/Swiften/Parser/MessageParser.cpp
@@ -0,0 +1,33 @@
+#include <iostream>
+
+#include "Swiften/Parser/MessageParser.h"
+
+namespace Swift {
+
+MessageParser::MessageParser(PayloadParserFactoryCollection* factories) :
+ GenericStanzaParser<Message>(factories) {
+ getStanzaGeneric()->setType(Message::Normal);
+}
+
+void MessageParser::handleStanzaAttributes(const AttributeMap& attributes) {
+ AttributeMap::const_iterator type = attributes.find("type");
+ if (type != attributes.end()) {
+ if (type->second == "chat") {
+ getStanzaGeneric()->setType(Message::Chat);
+ }
+ else if (type->second == "error") {
+ getStanzaGeneric()->setType(Message::Error);
+ }
+ else if (type->second == "groupchat") {
+ getStanzaGeneric()->setType(Message::Groupchat);
+ }
+ else if (type->second == "headline") {
+ getStanzaGeneric()->setType(Message::Headline);
+ }
+ else {
+ getStanzaGeneric()->setType(Message::Normal);
+ }
+ }
+}
+
+}
diff --git a/Swiften/Parser/MessageParser.h b/Swiften/Parser/MessageParser.h
new file mode 100644
index 0000000..05c9280
--- /dev/null
+++ b/Swiften/Parser/MessageParser.h
@@ -0,0 +1,17 @@
+#ifndef SWIFTEN_MESSAGEPARSER_H
+#define SWIFTEN_MESSAGEPARSER_H
+
+#include "Swiften/Parser/GenericStanzaParser.h"
+#include "Swiften/Elements/Message.h"
+
+namespace Swift {
+ class MessageParser : public GenericStanzaParser<Message> {
+ public:
+ MessageParser(PayloadParserFactoryCollection* factories);
+
+ private:
+ virtual void handleStanzaAttributes(const AttributeMap&);
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParser.cpp b/Swiften/Parser/PayloadParser.cpp
new file mode 100644
index 0000000..072edef
--- /dev/null
+++ b/Swiften/Parser/PayloadParser.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/Parser/PayloadParser.h"
+
+namespace Swift {
+
+PayloadParser::~PayloadParser() {
+}
+
+}
diff --git a/Swiften/Parser/PayloadParser.h b/Swiften/Parser/PayloadParser.h
new file mode 100644
index 0000000..fc1e1c8
--- /dev/null
+++ b/Swiften/Parser/PayloadParser.h
@@ -0,0 +1,24 @@
+#ifndef SWIFTEN_PAYLOADPARSER_H
+#define SWIFTEN_PAYLOADPARSER_H
+
+#include <boost/shared_ptr.hpp>
+#include "Swiften/Parser/AttributeMap.h"
+
+#include "Swiften/Elements/Payload.h"
+
+namespace Swift {
+ class String;
+
+ class PayloadParser {
+ public:
+ virtual ~PayloadParser();
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) = 0;
+ virtual void handleEndElement(const String& element, const String& ns) = 0;
+ virtual void handleCharacterData(const String& data) = 0;
+
+ virtual boost::shared_ptr<Payload> getPayload() const = 0;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParserFactory.cpp b/Swiften/Parser/PayloadParserFactory.cpp
new file mode 100644
index 0000000..b31f8ae
--- /dev/null
+++ b/Swiften/Parser/PayloadParserFactory.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+namespace Swift {
+
+PayloadParserFactory::~PayloadParserFactory() {
+}
+
+}
diff --git a/Swiften/Parser/PayloadParserFactory.h b/Swiften/Parser/PayloadParserFactory.h
new file mode 100644
index 0000000..728b4e8
--- /dev/null
+++ b/Swiften/Parser/PayloadParserFactory.h
@@ -0,0 +1,19 @@
+#ifndef SWIFTEN_PAYLOADPARSERFACTORY_H
+#define SWIFTEN_PAYLOADPARSERFACTORY_H
+
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class String;
+ class PayloadParser;
+
+ class PayloadParserFactory {
+ public:
+ virtual ~PayloadParserFactory();
+
+ virtual bool canParse(const String& element, const String& ns, const AttributeMap& attributes) const = 0;
+ virtual PayloadParser* createPayloadParser() = 0;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParserFactoryCollection.cpp
new file mode 100644
index 0000000..6d3a4cf
--- /dev/null
+++ b/Swiften/Parser/PayloadParserFactoryCollection.cpp
@@ -0,0 +1,31 @@
+#include <boost/bind.hpp>
+#include <algorithm>
+
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+namespace Swift {
+
+PayloadParserFactoryCollection::PayloadParserFactoryCollection() : defaultFactory_(NULL) {
+}
+
+void PayloadParserFactoryCollection::addFactory(PayloadParserFactory* factory) {
+ factories_.push_back(factory);
+}
+
+void PayloadParserFactoryCollection::removeFactory(PayloadParserFactory* factory) {
+ factories_.erase(remove(factories_.begin(), factories_.end(), factory), factories_.end());
+}
+
+void PayloadParserFactoryCollection::setDefaultFactory(PayloadParserFactory* factory) {
+ defaultFactory_ = factory;
+}
+
+PayloadParserFactory* PayloadParserFactoryCollection::getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes) {
+ std::vector<PayloadParserFactory*>::reverse_iterator i = std::find_if(
+ factories_.rbegin(), factories_.rend(),
+ boost::bind(&PayloadParserFactory::canParse, _1, element, ns, attributes));
+ return (i != factories_.rend() ? *i : defaultFactory_);
+}
+
+}
diff --git a/Swiften/Parser/PayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParserFactoryCollection.h
new file mode 100644
index 0000000..80a763b
--- /dev/null
+++ b/Swiften/Parser/PayloadParserFactoryCollection.h
@@ -0,0 +1,28 @@
+#ifndef SWIFTEN_PAYLOADPARSERFACTORYCOLLECTION_H
+#define SWIFTEN_PAYLOADPARSERFACTORYCOLLECTION_H
+
+#include <vector>
+
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class PayloadParserFactory;
+ class String;
+
+ class PayloadParserFactoryCollection {
+ public:
+ PayloadParserFactoryCollection();
+
+ void addFactory(PayloadParserFactory* factory);
+ void removeFactory(PayloadParserFactory* factory);
+ void setDefaultFactory(PayloadParserFactory* factory);
+
+ PayloadParserFactory* getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes);
+
+ private:
+ std::vector<PayloadParserFactory*> factories_;
+ PayloadParserFactory* defaultFactory_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/BodyParser.cpp b/Swiften/Parser/PayloadParsers/BodyParser.cpp
new file mode 100644
index 0000000..e5898ff
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/BodyParser.cpp
@@ -0,0 +1,23 @@
+#include "Swiften/Parser/PayloadParsers/BodyParser.h"
+
+namespace Swift {
+
+BodyParser::BodyParser() : level_(0) {
+}
+
+void BodyParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++level_;
+}
+
+void BodyParser::handleEndElement(const String&, const String&) {
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setText(text_);
+ }
+}
+
+void BodyParser::handleCharacterData(const String& data) {
+ text_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/BodyParser.h b/Swiften/Parser/PayloadParsers/BodyParser.h
new file mode 100644
index 0000000..2d272ea
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/BodyParser.h
@@ -0,0 +1,22 @@
+#ifndef SWIFTEN_BodyParser_H
+#define SWIFTEN_BodyParser_H
+
+#include "Swiften/Elements/Body.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class BodyParser : public GenericPayloadParser<Body> {
+ public:
+ BodyParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ String text_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/BodyParserFactory.h b/Swiften/Parser/PayloadParsers/BodyParserFactory.h
new file mode 100644
index 0000000..3da7393
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/BodyParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_BodyParserFACTORY_H
+#define SWIFTEN_BodyParserFACTORY_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/BodyParser.h"
+
+namespace Swift {
+ class BodyParserFactory : public GenericPayloadParserFactory<BodyParser> {
+ public:
+ BodyParserFactory() : GenericPayloadParserFactory<BodyParser>("body") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.cpp b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp
new file mode 100644
index 0000000..52d860a
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp
@@ -0,0 +1,35 @@
+#include "Swiften/Parser/PayloadParsers/ChatStateParser.h"
+
+namespace Swift {
+
+ChatStateParser::ChatStateParser() : level_(0) {
+}
+
+void ChatStateParser::handleStartElement(const String& element, const String&, const AttributeMap&) {
+ if (level_ == 0) {
+ ChatState::ChatStateType state = ChatState::Active;
+ if (element == "active") {
+ state = ChatState::Active;
+ } else if (element == "composing") {
+ state = ChatState::Composing;
+ } else if (element == "inactive") {
+ state = ChatState::Inactive;
+ } else if (element == "paused") {
+ state = ChatState::Paused;
+ } else if (element == "gone") {
+ state = ChatState::Gone;
+ }
+ getPayloadInternal()->setChatState(state);
+ }
+ ++level_;
+}
+
+void ChatStateParser::handleEndElement(const String&, const String&) {
+ --level_;
+}
+
+void ChatStateParser::handleCharacterData(const String&) {
+
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.h b/Swiften/Parser/PayloadParsers/ChatStateParser.h
new file mode 100644
index 0000000..cd212c0
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ChatStateParser.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Swiften/Elements/ChatState.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class ChatStateParser : public GenericPayloadParser<ChatState> {
+ public:
+ ChatStateParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h
new file mode 100644
index 0000000..1582d09
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ChatStateParser.h"
+
+namespace Swift {
+ class PayloadParserFactoryCollection;
+
+ class ChatStateParserFactory : public PayloadParserFactory {
+ public:
+ ChatStateParserFactory() {
+ }
+
+ virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const {
+ return ns == "http://jabber.org/protocol/chatstates" &&
+ (element == "active" || element == "composing"
+ || element == "paused" || element == "inactive" || element == "gone");
+ }
+
+ virtual PayloadParser* createPayloadParser() {
+ return new ChatStateParser();
+ }
+
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp
new file mode 100644
index 0000000..ffa24ad
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp
@@ -0,0 +1,27 @@
+#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h"
+
+namespace Swift {
+
+DiscoInfoParser::DiscoInfoParser() : level_(TopLevel) {
+}
+
+void DiscoInfoParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) {
+ if (level_ == PayloadLevel) {
+ if (element == "identity") {
+ getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang")));
+ }
+ else if (element == "feature") {
+ getPayloadInternal()->addFeature(attributes.getAttribute("var"));
+ }
+ }
+ ++level_;
+}
+
+void DiscoInfoParser::handleEndElement(const String&, const String&) {
+ --level_;
+}
+
+void DiscoInfoParser::handleCharacterData(const String&) {
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.h b/Swiften/Parser/PayloadParsers/DiscoInfoParser.h
new file mode 100644
index 0000000..b7be972
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.h
@@ -0,0 +1,25 @@
+#ifndef SWIFTEN_DiscoInfoParser_H
+#define SWIFTEN_DiscoInfoParser_H
+
+#include "Swiften/Elements/DiscoInfo.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class DiscoInfoParser : public GenericPayloadParser<DiscoInfo> {
+ public:
+ DiscoInfoParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+ int level_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h b/Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h
new file mode 100644
index 0000000..ef1c31c
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_DiscoInfoParserFactory_H
+#define SWIFTEN_DiscoInfoParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h"
+
+namespace Swift {
+ class DiscoInfoParserFactory : public GenericPayloadParserFactory<DiscoInfoParser> {
+ public:
+ DiscoInfoParserFactory() : GenericPayloadParserFactory<DiscoInfoParser>("query", "http://jabber.org/protocol/disco#info") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/ErrorParser.cpp b/Swiften/Parser/PayloadParsers/ErrorParser.cpp
new file mode 100644
index 0000000..ae85265
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ErrorParser.cpp
@@ -0,0 +1,109 @@
+#include "Swiften/Parser/PayloadParsers/ErrorParser.h"
+
+namespace Swift {
+
+ErrorParser::ErrorParser() : level_(TopLevel) {
+}
+
+void ErrorParser::handleStartElement(const String&, const String&, const AttributeMap& attributes) {
+ if (level_ == TopLevel) {
+ String type = attributes.getAttribute("type");
+ if (type == "continue") {
+ getPayloadInternal()->setType(ErrorPayload::Continue);
+ }
+ else if (type == "modify") {
+ getPayloadInternal()->setType(ErrorPayload::Modify);
+ }
+ else if (type == "auth") {
+ getPayloadInternal()->setType(ErrorPayload::Auth);
+ }
+ else if (type == "wait") {
+ getPayloadInternal()->setType(ErrorPayload::Wait);
+ }
+ else {
+ getPayloadInternal()->setType(ErrorPayload::Cancel);
+ }
+ }
+ ++level_;
+}
+
+void ErrorParser::handleEndElement(const String& element, const String&) {
+ --level_;
+ if (level_ == PayloadLevel) {
+ if (element == "text") {
+ getPayloadInternal()->setText(currentText_);
+ }
+ else if (element == "bad-request") {
+ getPayloadInternal()->setCondition(ErrorPayload::BadRequest);
+ }
+ else if (element == "conflict") {
+ getPayloadInternal()->setCondition(ErrorPayload::Conflict);
+ }
+ else if (element == "feature-not-implemented") {
+ getPayloadInternal()->setCondition(ErrorPayload::FeatureNotImplemented);
+ }
+ else if (element == "forbidden") {
+ getPayloadInternal()->setCondition(ErrorPayload::Forbidden);
+ }
+ else if (element == "gone") {
+ getPayloadInternal()->setCondition(ErrorPayload::Gone);
+ }
+ else if (element == "internal-server-error") {
+ getPayloadInternal()->setCondition(ErrorPayload::InternalServerError);
+ }
+ else if (element == "item-not-found") {
+ getPayloadInternal()->setCondition(ErrorPayload::ItemNotFound);
+ }
+ else if (element == "jid-malformed") {
+ getPayloadInternal()->setCondition(ErrorPayload::JIDMalformed);
+ }
+ else if (element == "not-acceptable") {
+ getPayloadInternal()->setCondition(ErrorPayload::NotAcceptable);
+ }
+ else if (element == "not-allowed") {
+ getPayloadInternal()->setCondition(ErrorPayload::NotAllowed);
+ }
+ else if (element == "not-authorized") {
+ getPayloadInternal()->setCondition(ErrorPayload::NotAuthorized);
+ }
+ else if (element == "payment-required") {
+ getPayloadInternal()->setCondition(ErrorPayload::PaymentRequired);
+ }
+ else if (element == "recipient-unavailable") {
+ getPayloadInternal()->setCondition(ErrorPayload::RecipientUnavailable);
+ }
+ else if (element == "redirect") {
+ getPayloadInternal()->setCondition(ErrorPayload::Redirect);
+ }
+ else if (element == "registration-required") {
+ getPayloadInternal()->setCondition(ErrorPayload::RegistrationRequired);
+ }
+ else if (element == "remote-server-not-found") {
+ getPayloadInternal()->setCondition(ErrorPayload::RemoteServerNotFound);
+ }
+ else if (element == "remote-server-timeout") {
+ getPayloadInternal()->setCondition(ErrorPayload::RemoteServerTimeout);
+ }
+ else if (element == "resource-constraint") {
+ getPayloadInternal()->setCondition(ErrorPayload::ResourceConstraint);
+ }
+ else if (element == "service-unavailable") {
+ getPayloadInternal()->setCondition(ErrorPayload::ServiceUnavailable);
+ }
+ else if (element == "subscription-required") {
+ getPayloadInternal()->setCondition(ErrorPayload::SubscriptionRequired);
+ }
+ else if (element == "unexpected-request") {
+ getPayloadInternal()->setCondition(ErrorPayload::UnexpectedRequest);
+ }
+ else {
+ getPayloadInternal()->setCondition(ErrorPayload::UndefinedCondition);
+ }
+ }
+}
+
+void ErrorParser::handleCharacterData(const String& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/ErrorParser.h b/Swiften/Parser/PayloadParsers/ErrorParser.h
new file mode 100644
index 0000000..17b78b9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ErrorParser.h
@@ -0,0 +1,26 @@
+#ifndef SWIFTEN_ErrorParser_H
+#define SWIFTEN_ErrorParser_H
+
+#include "Swiften/Elements/ErrorPayload.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class ErrorParser : public GenericPayloadParser<ErrorPayload> {
+ public:
+ ErrorParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+ int level_;
+ String currentText_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/ErrorParserFactory.h b/Swiften/Parser/PayloadParsers/ErrorParserFactory.h
new file mode 100644
index 0000000..36d1f55
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ErrorParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_ErrorParserFactory_H
+#define SWIFTEN_ErrorParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ErrorParser.h"
+
+namespace Swift {
+ class ErrorParserFactory : public GenericPayloadParserFactory<ErrorParser> {
+ public:
+ ErrorParserFactory() : GenericPayloadParserFactory<ErrorParser>("error") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
new file mode 100644
index 0000000..0857f64
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -0,0 +1,61 @@
+#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ErrorParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/BodyParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ChatStateParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PriorityParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StartSessionParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StatusParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StatusShowParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/RosterParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StorageParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/VCardParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h"
+
+using namespace boost;
+
+namespace Swift {
+
+FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new StatusParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new StatusShowParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new BodyParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new PriorityParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new ErrorParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new SoftwareVersionParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new StorageParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new RosterParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new DiscoInfoParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new ResourceBindParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new StartSessionParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelsCatalogParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new PrivateStorageParserFactory(this)));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new ChatStateParserFactory()));
+ foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
+ addFactory(factory.get());
+ }
+ defaultFactory_ = new RawXMLPayloadParserFactory();
+ setDefaultFactory(defaultFactory_);
+}
+
+FullPayloadParserFactoryCollection::~FullPayloadParserFactoryCollection() {
+ setDefaultFactory(NULL);
+ delete defaultFactory_;
+ foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
+ removeFactory(factory.get());
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h
new file mode 100644
index 0000000..82e5a56
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+namespace Swift {
+ class FullPayloadParserFactoryCollection : public PayloadParserFactoryCollection {
+ public:
+ FullPayloadParserFactoryCollection();
+ ~FullPayloadParserFactoryCollection();
+
+ private:
+ std::vector< boost::shared_ptr<PayloadParserFactory> > factories_;
+ PayloadParserFactory* defaultFactory_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/PriorityParser.cpp b/Swiften/Parser/PayloadParsers/PriorityParser.cpp
new file mode 100644
index 0000000..3dcca51
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PriorityParser.cpp
@@ -0,0 +1,25 @@
+#include "Swiften/Parser/PayloadParsers/PriorityParser.h"
+
+#include <boost/lexical_cast.hpp>
+
+namespace Swift {
+
+PriorityParser::PriorityParser() : level_(0) {
+}
+
+void PriorityParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++level_;
+}
+
+void PriorityParser::handleEndElement(const String&, const String&) {
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setPriority(boost::lexical_cast<int>(text_));
+ }
+}
+
+void PriorityParser::handleCharacterData(const String& data) {
+ text_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/PriorityParser.h b/Swiften/Parser/PayloadParsers/PriorityParser.h
new file mode 100644
index 0000000..7f3836f
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PriorityParser.h
@@ -0,0 +1,22 @@
+#ifndef SWIFTEN_PriorityParser_H
+#define SWIFTEN_PriorityParser_H
+
+#include "Swiften/Elements/Priority.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class PriorityParser : public GenericPayloadParser<Priority> {
+ public:
+ PriorityParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ String text_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/PriorityParserFactory.h b/Swiften/Parser/PayloadParsers/PriorityParserFactory.h
new file mode 100644
index 0000000..5386326
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PriorityParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_PriorityParserFactory_H
+#define SWIFTEN_PriorityParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PriorityParser.h"
+
+namespace Swift {
+ class PriorityParserFactory : public GenericPayloadParserFactory<PriorityParser> {
+ public:
+ PriorityParserFactory() : GenericPayloadParserFactory<PriorityParser>("priority") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp
new file mode 100644
index 0000000..5c3af26
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp
@@ -0,0 +1,43 @@
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+namespace Swift {
+
+PrivateStorageParser::PrivateStorageParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) {
+}
+
+void PrivateStorageParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ if (level == 1) {
+ PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes);
+ if (payloadParserFactory) {
+ currentPayloadParser.reset(payloadParserFactory->createPayloadParser());
+ }
+ }
+
+ if (level >= 1 && currentPayloadParser.get()) {
+ currentPayloadParser->handleStartElement(element, ns, attributes);
+ }
+ ++level;
+}
+
+void PrivateStorageParser::handleEndElement(const String& element, const String& ns) {
+ --level;
+ if (currentPayloadParser.get()) {
+ if (level >= 1) {
+ currentPayloadParser->handleEndElement(element, ns);
+ }
+
+ if (level == 1) {
+ getPayloadInternal()->setPayload(currentPayloadParser->getPayload());
+ }
+ }
+}
+
+void PrivateStorageParser::handleCharacterData(const String& data) {
+ if (level > 1 && currentPayloadParser.get()) {
+ currentPayloadParser->handleCharacterData(data);
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.h b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h
new file mode 100644
index 0000000..fae0f10
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "Swiften/Elements/PrivateStorage.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class PayloadParserFactoryCollection;
+
+ class PrivateStorageParser : public GenericPayloadParser<PrivateStorage> {
+ public:
+ PrivateStorageParser(PayloadParserFactoryCollection* factories);
+
+ private:
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ PayloadParserFactoryCollection* factories;
+ int level;
+ std::auto_ptr<PayloadParser> currentPayloadParser;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h
new file mode 100644
index 0000000..4d9c02b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+
+namespace Swift {
+ class PayloadParserFactoryCollection;
+
+ class PrivateStorageParserFactory : public PayloadParserFactory {
+ public:
+ PrivateStorageParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) {
+ }
+
+ virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const {
+ return element == "query" && ns == "jabber:iq:private";
+ }
+
+ virtual PayloadParser* createPayloadParser() {
+ return new PrivateStorageParser(factories);
+ }
+
+ private:
+ PayloadParserFactoryCollection* factories;
+
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp
new file mode 100644
index 0000000..c49af3e
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp
@@ -0,0 +1,26 @@
+#include "Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h"
+#include "Swiften/Parser/SerializingParser.h"
+
+namespace Swift {
+
+RawXMLPayloadParser::RawXMLPayloadParser() : level_(0) {
+}
+
+void RawXMLPayloadParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ ++level_;
+ serializingParser_.handleStartElement(element, ns, attributes);
+}
+
+void RawXMLPayloadParser::handleEndElement(const String& element, const String& ns) {
+ serializingParser_.handleEndElement(element, ns);
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setRawXML(serializingParser_.getResult());
+ }
+}
+
+void RawXMLPayloadParser::handleCharacterData(const String& data) {
+ serializingParser_.handleCharacterData(data);
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h
new file mode 100644
index 0000000..f636486
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "Swiften/Elements/RawXMLPayload.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+#include "Swiften/Parser/SerializingParser.h"
+
+namespace Swift {
+ class SerializingParser;
+
+ class RawXMLPayloadParser : public GenericPayloadParser<RawXMLPayload> {
+ public:
+ RawXMLPayloadParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ SerializingParser serializingParser_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h
new file mode 100644
index 0000000..46b1183
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class RawXMLPayloadParserFactory : public PayloadParserFactory {
+ public:
+ RawXMLPayloadParserFactory() {}
+
+ virtual bool canParse(const String&, const String&, const AttributeMap&) const {
+ return true;
+ }
+
+ virtual PayloadParser* createPayloadParser() {
+ return new RawXMLPayloadParser();
+ }
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp b/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp
new file mode 100644
index 0000000..c5ca787
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp
@@ -0,0 +1,37 @@
+#include "Swiften/Parser/PayloadParsers/ResourceBindParser.h"
+
+namespace Swift {
+
+ResourceBindParser::ResourceBindParser() : level_(0), inJID_(false), inResource_(false) {
+}
+
+void ResourceBindParser::handleStartElement(const String& element, const String&, const AttributeMap&) {
+ if (level_ == 1) {
+ text_ = "";
+ if (element == "resource") {
+ inResource_ = true;
+ }
+ if (element == "jid") {
+ inJID_ = true;
+ }
+ }
+ ++level_;
+}
+
+void ResourceBindParser::handleEndElement(const String&, const String&) {
+ --level_;
+ if (level_ == 1) {
+ if (inJID_) {
+ getPayloadInternal()->setJID(JID(text_));
+ }
+ else if (inResource_) {
+ getPayloadInternal()->setResource(text_);
+ }
+ }
+}
+
+void ResourceBindParser::handleCharacterData(const String& data) {
+ text_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/ResourceBindParser.h b/Swiften/Parser/PayloadParsers/ResourceBindParser.h
new file mode 100644
index 0000000..1341140
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ResourceBindParser.h
@@ -0,0 +1,24 @@
+#ifndef SWIFTEN_ResourceBindParser_H
+#define SWIFTEN_ResourceBindParser_H
+
+#include "Swiften/Elements/ResourceBind.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class ResourceBindParser : public GenericPayloadParser<ResourceBind> {
+ public:
+ ResourceBindParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ bool inJID_;
+ bool inResource_;
+ String text_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h b/Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h
new file mode 100644
index 0000000..54af9c9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ResourceBindParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_ResourceBindParserFactory_H
+#define SWIFTEN_ResourceBindParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/ResourceBindParser.h"
+
+namespace Swift {
+ class ResourceBindParserFactory : public GenericPayloadParserFactory<ResourceBindParser> {
+ public:
+ ResourceBindParserFactory() : GenericPayloadParserFactory<ResourceBindParser>("bind", "urn:ietf:params:xml:ns:xmpp-bind") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp
new file mode 100644
index 0000000..0c4e99b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp
@@ -0,0 +1,66 @@
+#include "Swiften/Parser/PayloadParsers/RosterParser.h"
+
+namespace Swift {
+
+RosterParser::RosterParser() : level_(TopLevel) {
+}
+
+void RosterParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) {
+ if (level_ == PayloadLevel) {
+ if (element == "item") {
+ inItem_ = true;
+ currentItem_ = RosterItemPayload();
+
+ currentItem_.setJID(JID(attributes.getAttribute("jid")));
+ currentItem_.setName(attributes.getAttribute("name"));
+
+ String subscription = attributes.getAttribute("subscription");
+ if (subscription == "both") {
+ currentItem_.setSubscription(RosterItemPayload::Both);
+ }
+ else if (subscription == "to") {
+ currentItem_.setSubscription(RosterItemPayload::To);
+ }
+ else if (subscription == "from") {
+ currentItem_.setSubscription(RosterItemPayload::From);
+ }
+ else if (subscription == "remove") {
+ currentItem_.setSubscription(RosterItemPayload::Remove);
+ }
+ else {
+ currentItem_.setSubscription(RosterItemPayload::None);
+ }
+
+ if (attributes.getAttribute("ask") == "subscribe") {
+ currentItem_.setSubscriptionRequested();
+ }
+ }
+ }
+ else if (level_ == ItemLevel) {
+ if (element == "group") {
+ currentText_ = "";
+ }
+ }
+ ++level_;
+}
+
+void RosterParser::handleEndElement(const String& element, const String&) {
+ --level_;
+ if (level_ == PayloadLevel) {
+ if (inItem_) {
+ getPayloadInternal()->addItem(currentItem_);
+ inItem_ = false;
+ }
+ }
+ else if (level_ == ItemLevel) {
+ if (element == "group") {
+ currentItem_.addGroup(currentText_);
+ }
+ }
+}
+
+void RosterParser::handleCharacterData(const String& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/RosterParser.h b/Swiften/Parser/PayloadParsers/RosterParser.h
new file mode 100644
index 0000000..bd8186a
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RosterParser.h
@@ -0,0 +1,29 @@
+#ifndef SWIFTEN_RosterParser_H
+#define SWIFTEN_RosterParser_H
+
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class RosterParser : public GenericPayloadParser<RosterPayload> {
+ public:
+ RosterParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1,
+ ItemLevel = 2
+ };
+ int level_;
+ bool inItem_;
+ RosterItemPayload currentItem_;
+ String currentText_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/RosterParserFactory.h b/Swiften/Parser/PayloadParsers/RosterParserFactory.h
new file mode 100644
index 0000000..f51b3ab
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RosterParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_RosterParserFactory_H
+#define SWIFTEN_RosterParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/RosterParser.h"
+
+namespace Swift {
+ class RosterParserFactory : public GenericPayloadParserFactory<RosterParser> {
+ public:
+ RosterParserFactory() : GenericPayloadParserFactory<RosterParser>("query", "jabber:iq:roster") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp b/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp
new file mode 100644
index 0000000..7e65575
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp
@@ -0,0 +1,59 @@
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParser.h"
+#include "Swiften/Parser/SerializingParser.h"
+
+namespace Swift {
+
+SecurityLabelParser::SecurityLabelParser() : level_(TopLevel), labelParser_(0) {
+}
+
+void SecurityLabelParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ ++level_;
+ if (level_ == DisplayMarkingOrLabelLevel) {
+ if (element == "displaymarking") {
+ currentText_ = "";
+ getPayloadInternal()->setBackgroundColor(attributes.getAttribute("bgcolor"));
+ getPayloadInternal()->setForegroundColor(attributes.getAttribute("fgcolor"));
+ }
+ else if (element == "label" || element == "equivalentlabel") {
+ assert(!labelParser_);
+ labelParser_ = new SerializingParser();
+ }
+ }
+ else if (level_ >= SecurityLabelLevel && labelParser_) {
+ labelParser_->handleStartElement(element, ns, attributes);
+ }
+}
+
+void SecurityLabelParser::handleEndElement(const String& element, const String& ns) {
+ if (level_ == DisplayMarkingOrLabelLevel) {
+ if (element == "displaymarking") {
+ getPayloadInternal()->setDisplayMarking(currentText_);
+ }
+ else if (labelParser_) {
+ if (element == "label") {
+ getPayloadInternal()->setLabel(labelParser_->getResult());
+ }
+ else {
+ getPayloadInternal()->addEquivalentLabel(labelParser_->getResult());
+ }
+ delete labelParser_;
+ labelParser_ = 0;
+ }
+ }
+ else if (labelParser_ && level_ >= SecurityLabelLevel) {
+ labelParser_->handleEndElement(element, ns);
+ }
+ --level_;
+
+}
+
+void SecurityLabelParser::handleCharacterData(const String& data) {
+ if (labelParser_) {
+ labelParser_->handleCharacterData(data);
+ }
+ else {
+ currentText_ += data;
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParser.h b/Swiften/Parser/PayloadParsers/SecurityLabelParser.h
new file mode 100644
index 0000000..70040d9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelParser.h
@@ -0,0 +1,31 @@
+#ifndef SWIFTEN_SecurityLabelParser_H
+#define SWIFTEN_SecurityLabelParser_H
+
+#include "Swiften/Elements/SecurityLabel.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SerializingParser;
+
+ class SecurityLabelParser : public GenericPayloadParser<SecurityLabel> {
+ public:
+ SecurityLabelParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1,
+ DisplayMarkingOrLabelLevel = 2,
+ SecurityLabelLevel = 3
+ };
+ int level_;
+ SerializingParser* labelParser_;
+ String currentText_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h b/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h
new file mode 100644
index 0000000..0341fbb
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_SecurityLabelParserFactory_H
+#define SWIFTEN_SecurityLabelParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParser.h"
+
+namespace Swift {
+ class SecurityLabelParserFactory : public GenericPayloadParserFactory<SecurityLabelParser> {
+ public:
+ SecurityLabelParserFactory() : GenericPayloadParserFactory<SecurityLabelParser>("securitylabel", "urn:xmpp:sec-label:0") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp
new file mode 100644
index 0000000..e4da756
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp
@@ -0,0 +1,55 @@
+#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParser.h"
+
+namespace Swift {
+
+SecurityLabelsCatalogParser::SecurityLabelsCatalogParser() : level_(TopLevel), labelParser_(0) {
+ labelParserFactory_ = new SecurityLabelParserFactory();
+}
+
+SecurityLabelsCatalogParser::~SecurityLabelsCatalogParser() {
+ delete labelParserFactory_;
+}
+
+void SecurityLabelsCatalogParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ ++level_;
+ if (level_ == PayloadLevel) {
+ getPayloadInternal()->setTo(JID(attributes.getAttribute("to")));
+ getPayloadInternal()->setName(attributes.getAttribute("name"));
+ getPayloadInternal()->setDescription(attributes.getAttribute("desc"));
+ }
+ else if (level_ == LabelLevel) {
+ assert(!labelParser_);
+ if (labelParserFactory_->canParse(element, ns, attributes)) {
+ labelParser_ = dynamic_cast<SecurityLabelParser*>(labelParserFactory_->createPayloadParser());
+ assert(labelParser_);
+ }
+ }
+
+ if (labelParser_) {
+ labelParser_->handleStartElement(element, ns, attributes);
+ }
+}
+
+void SecurityLabelsCatalogParser::handleEndElement(const String& element, const String& ns) {
+ if (labelParser_) {
+ labelParser_->handleEndElement(element, ns);
+ }
+ if (level_ == LabelLevel && labelParser_) {
+ SecurityLabel* label = dynamic_cast<SecurityLabel*>(labelParser_->getPayload().get());
+ assert(label);
+ getPayloadInternal()->addLabel(SecurityLabel(*label));
+ delete labelParser_;
+ labelParser_ = 0;
+ }
+ --level_;
+}
+
+void SecurityLabelsCatalogParser::handleCharacterData(const String& data) {
+ if (labelParser_) {
+ labelParser_->handleCharacterData(data);
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h
new file mode 100644
index 0000000..799e43a
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h
@@ -0,0 +1,32 @@
+#ifndef SWIFTEN_SecurityLabelsCatalogParser_H
+#define SWIFTEN_SecurityLabelsCatalogParser_H
+
+#include "Swiften/Elements/SecurityLabelsCatalog.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SecurityLabelParserFactory;
+ class SecurityLabelParser;
+
+ class SecurityLabelsCatalogParser : public GenericPayloadParser<SecurityLabelsCatalog> {
+ public:
+ SecurityLabelsCatalogParser();
+ ~SecurityLabelsCatalogParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1,
+ LabelLevel = 2
+ };
+ int level_;
+ SecurityLabelParserFactory* labelParserFactory_;
+ SecurityLabelParser* labelParser_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h
new file mode 100644
index 0000000..99a310b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_SecurityLabelsCatalogParserFactory_H
+#define SWIFTEN_SecurityLabelsCatalogParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h"
+
+namespace Swift {
+ class SecurityLabelsCatalogParserFactory : public GenericPayloadParserFactory<SecurityLabelsCatalogParser> {
+ public:
+ SecurityLabelsCatalogParserFactory() : GenericPayloadParserFactory<SecurityLabelsCatalogParser>("catalog", "urn:xmpp:sec-label:catalog:0") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp
new file mode 100644
index 0000000..dae9f94
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp
@@ -0,0 +1,32 @@
+#include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h"
+
+namespace Swift {
+
+SoftwareVersionParser::SoftwareVersionParser() : level_(TopLevel) {
+}
+
+void SoftwareVersionParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++level_;
+}
+
+void SoftwareVersionParser::handleEndElement(const String& element, const String&) {
+ --level_;
+ if (level_ == PayloadLevel) {
+ if (element == "name") {
+ getPayloadInternal()->setName(currentText_);
+ }
+ else if (element == "version") {
+ getPayloadInternal()->setVersion(currentText_);
+ }
+ else if (element == "os") {
+ getPayloadInternal()->setOS(currentText_);
+ }
+ currentText_ = "";
+ }
+}
+
+void SoftwareVersionParser::handleCharacterData(const String& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h
new file mode 100644
index 0000000..bfffc90
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h
@@ -0,0 +1,26 @@
+#ifndef SWIFTEN_SoftwareVersionParser_H
+#define SWIFTEN_SoftwareVersionParser_H
+
+#include "Swiften/Elements/SoftwareVersion.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SoftwareVersionParser : public GenericPayloadParser<SoftwareVersion> {
+ public:
+ SoftwareVersionParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+ int level_;
+ String currentText_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h b/Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h
new file mode 100644
index 0000000..cb33e0b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_SoftwareVersionParserFactory_H
+#define SWIFTEN_SoftwareVersionParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h"
+
+namespace Swift {
+ class SoftwareVersionParserFactory : public GenericPayloadParserFactory<SoftwareVersionParser> {
+ public:
+ SoftwareVersionParserFactory() : GenericPayloadParserFactory<SoftwareVersionParser>("query", "jabber:iq:version") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StartSessionParser.h b/Swiften/Parser/PayloadParsers/StartSessionParser.h
new file mode 100644
index 0000000..059d036
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StartSessionParser.h
@@ -0,0 +1,18 @@
+#ifndef SWIFTEN_StartSessionParser_H
+#define SWIFTEN_StartSessionParser_H
+
+#include "Swiften/Elements/StartSession.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class StartSessionParser : public GenericPayloadParser<StartSession> {
+ public:
+ StartSessionParser() {}
+
+ virtual void handleStartElement(const String&, const String&, const AttributeMap&) {}
+ virtual void handleEndElement(const String&, const String&) {}
+ virtual void handleCharacterData(const String&) {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StartSessionParserFactory.h b/Swiften/Parser/PayloadParsers/StartSessionParserFactory.h
new file mode 100644
index 0000000..5eed749
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StartSessionParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_StartSessionParserFactory_H
+#define SWIFTEN_StartSessionParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StartSessionParser.h"
+
+namespace Swift {
+ class StartSessionParserFactory : public GenericPayloadParserFactory<StartSessionParser> {
+ public:
+ StartSessionParserFactory() : GenericPayloadParserFactory<StartSessionParser>("session", "urn:ietf:params:xml:ns:xmpp-session") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StatusParser.cpp b/Swiften/Parser/PayloadParsers/StatusParser.cpp
new file mode 100644
index 0000000..c7771b9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusParser.cpp
@@ -0,0 +1,23 @@
+#include "Swiften/Parser/PayloadParsers/StatusParser.h"
+
+namespace Swift {
+
+StatusParser::StatusParser() : level_(0) {
+}
+
+void StatusParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++level_;
+}
+
+void StatusParser::handleEndElement(const String&, const String&) {
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setText(text_);
+ }
+}
+
+void StatusParser::handleCharacterData(const String& data) {
+ text_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/StatusParser.h b/Swiften/Parser/PayloadParsers/StatusParser.h
new file mode 100644
index 0000000..36ae094
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusParser.h
@@ -0,0 +1,22 @@
+#ifndef SWIFTEN_StatusParser_H
+#define SWIFTEN_StatusParser_H
+
+#include "Swiften/Elements/Status.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class StatusParser : public GenericPayloadParser<Status> {
+ public:
+ StatusParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ String text_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StatusParserFactory.h b/Swiften/Parser/PayloadParsers/StatusParserFactory.h
new file mode 100644
index 0000000..72af5a9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_StatusParserFactory_H
+#define SWIFTEN_StatusParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StatusParser.h"
+
+namespace Swift {
+ class StatusParserFactory : public GenericPayloadParserFactory<StatusParser> {
+ public:
+ StatusParserFactory() : GenericPayloadParserFactory<StatusParser>("status") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StatusShowParser.cpp b/Swiften/Parser/PayloadParsers/StatusShowParser.cpp
new file mode 100644
index 0000000..c3719af
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusShowParser.cpp
@@ -0,0 +1,37 @@
+#include "Swiften/Parser/PayloadParsers/StatusShowParser.h"
+
+namespace Swift {
+
+StatusShowParser::StatusShowParser() : level_(0) {
+}
+
+void StatusShowParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ ++level_;
+}
+
+void StatusShowParser::handleEndElement(const String&, const String&) {
+ --level_;
+ if (level_ == 0) {
+ if (text_ == "away") {
+ getPayloadInternal()->setType(StatusShow::Away);
+ }
+ else if (text_ == "chat") {
+ getPayloadInternal()->setType(StatusShow::FFC);
+ }
+ else if (text_ == "xa") {
+ getPayloadInternal()->setType(StatusShow::XA);
+ }
+ else if (text_ == "dnd") {
+ getPayloadInternal()->setType(StatusShow::DND);
+ }
+ else {
+ getPayloadInternal()->setType(StatusShow::Online);
+ }
+ }
+}
+
+void StatusShowParser::handleCharacterData(const String& data) {
+ text_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/StatusShowParser.h b/Swiften/Parser/PayloadParsers/StatusShowParser.h
new file mode 100644
index 0000000..a8ddb09
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusShowParser.h
@@ -0,0 +1,22 @@
+#ifndef SWIFTEN_StatusShowParser_H
+#define SWIFTEN_StatusShowParser_H
+
+#include "Swiften/Elements/StatusShow.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class StatusShowParser : public GenericPayloadParser<StatusShow> {
+ public:
+ StatusShowParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ int level_;
+ String text_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StatusShowParserFactory.h b/Swiften/Parser/PayloadParsers/StatusShowParserFactory.h
new file mode 100644
index 0000000..2ddc190
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StatusShowParserFactory.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_StatusShowParserFactory_H
+#define SWIFTEN_StatusShowParserFactory_H
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StatusShowParser.h"
+
+namespace Swift {
+ class StatusShowParserFactory : public GenericPayloadParserFactory<StatusShowParser> {
+ public:
+ StatusShowParserFactory() : GenericPayloadParserFactory<StatusShowParser>("show") {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PayloadParsers/StorageParser.cpp b/Swiften/Parser/PayloadParsers/StorageParser.cpp
new file mode 100644
index 0000000..3eab15e
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParser.cpp
@@ -0,0 +1,49 @@
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+
+#include <cassert>
+
+namespace Swift {
+
+StorageParser::StorageParser() : level(TopLevel) {
+}
+
+void StorageParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) {
+ if (level == BookmarkLevel) {
+ if (element == "conference") {
+ assert(!conference);
+ conference = Storage::Conference();
+ conference->autoJoin = attributes.getBoolAttribute("autojoin", false);
+ conference->jid = JID(attributes.getAttribute("jid"));
+ conference->name = attributes.getAttribute("name");
+ }
+ }
+ else if (level == DetailLevel) {
+ currentText = "";
+ }
+ ++level;
+}
+
+void StorageParser::handleEndElement(const String& element, const String&) {
+ --level;
+ if (level == BookmarkLevel) {
+ if (element == "conference") {
+ assert(conference);
+ getPayloadInternal()->addConference(*conference);
+ conference.reset();
+ }
+ }
+ else if (level == DetailLevel && conference) {
+ if (element == "nick") {
+ conference->nick = currentText;
+ }
+ else if (element == "password") {
+ conference->password = currentText;
+ }
+ }
+}
+
+void StorageParser::handleCharacterData(const String& data) {
+ currentText += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/StorageParser.h b/Swiften/Parser/PayloadParsers/StorageParser.h
new file mode 100644
index 0000000..ad0ab4d
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParser.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "Swiften/Elements/Storage.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class StorageParser : public GenericPayloadParser<Storage> {
+ public:
+ StorageParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ BookmarkLevel = 1,
+ DetailLevel = 2
+ };
+ int level;
+ String currentText;
+ boost::optional<Storage::Conference> conference;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/StorageParserFactory.h b/Swiften/Parser/PayloadParsers/StorageParserFactory.h
new file mode 100644
index 0000000..147d178
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParserFactory.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+
+namespace Swift {
+ class StorageParserFactory : public GenericPayloadParserFactory<StorageParser> {
+ public:
+ StorageParserFactory() : GenericPayloadParserFactory<StorageParser>("storage", "storage:bookmarks") {}
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp
new file mode 100644
index 0000000..2fc6180
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp
@@ -0,0 +1,28 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/BodyParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class BodyParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(BodyParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ BodyParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<body>foo<baz>bar</baz>fum</body>"));
+
+ Body* payload = dynamic_cast<Body*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("foobarfum"), payload->getText());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(BodyParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp
new file mode 100644
index 0000000..49b706e
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp
@@ -0,0 +1,47 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class DiscoInfoParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DiscoInfoParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ DiscoInfoParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<query xmlns=\"http://jabber.org/protocol/disco#info\">"
+ "<identity name=\"Swift\" category=\"client\" type=\"pc\" xml:lang=\"en\"/>"
+ "<identity name=\"Vlug\" category=\"client\" type=\"pc\" xml:lang=\"nl\"/>"
+ "<feature var=\"foo-feature\"/>"
+ "<feature var=\"bar-feature\"/>"
+ "<feature var=\"baz-feature\"/>"
+ "</query>"));
+
+ DiscoInfo* payload = dynamic_cast<DiscoInfo*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getIdentities().size()));
+ CPPUNIT_ASSERT_EQUAL(String("Swift"), payload->getIdentities()[0].getName());
+ CPPUNIT_ASSERT_EQUAL(String("pc"), payload->getIdentities()[0].getType());
+ CPPUNIT_ASSERT_EQUAL(String("client"), payload->getIdentities()[0].getCategory());
+ CPPUNIT_ASSERT_EQUAL(String("en"), payload->getIdentities()[0].getLanguage());
+ CPPUNIT_ASSERT_EQUAL(String("Vlug"), payload->getIdentities()[1].getName());
+ CPPUNIT_ASSERT_EQUAL(String("pc"), payload->getIdentities()[1].getType());
+ CPPUNIT_ASSERT_EQUAL(String("client"), payload->getIdentities()[1].getCategory());
+ CPPUNIT_ASSERT_EQUAL(String("nl"), payload->getIdentities()[1].getLanguage());
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getFeatures().size()));
+ CPPUNIT_ASSERT_EQUAL(String("foo-feature"), payload->getFeatures()[0]);
+ CPPUNIT_ASSERT_EQUAL(String("bar-feature"), payload->getFeatures()[1]);
+ CPPUNIT_ASSERT_EQUAL(String("baz-feature"), payload->getFeatures()[2]);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DiscoInfoParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp
new file mode 100644
index 0000000..dcd3172
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp
@@ -0,0 +1,34 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/ErrorParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class ErrorParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ErrorParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ ErrorParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<error type=\"modify\">"
+ "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"
+ "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>"
+ "</error>"));
+
+ ErrorPayload* payload = dynamic_cast<ErrorPayload*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, payload->getCondition());
+ CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, payload->getType());
+ CPPUNIT_ASSERT_EQUAL(String("boo"), payload->getText());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ErrorParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h
new file mode 100644
index 0000000..20a5feb
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "Swiften/Parser/UnitTest/ParserTester.h"
+#include "Swiften/Parser/PayloadParser.h"
+
+namespace Swift {
+ typedef ParserTester<PayloadParser> PayloadParserTester;
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h
new file mode 100644
index 0000000..ac167cf
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
+#include "Swiften/Parser/XMLParser.h"
+#include "Swiften/Parser/XMLParserClient.h"
+#include "Swiften/Parser/PlatformXMLParserFactory.h"
+
+namespace Swift {
+ class PayloadsParserTester : public XMLParserClient {
+ public:
+ PayloadsParserTester() : level(0) {
+ xmlParser = PlatformXMLParserFactory().createXMLParser(this);
+ }
+
+ ~PayloadsParserTester() {
+ delete xmlParser;
+ }
+
+ bool parse(const String& data) {
+ return xmlParser->parse(data);
+ }
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ if (level == 0) {
+ CPPUNIT_ASSERT(!payloadParser.get());
+ PayloadParserFactory* payloadParserFactory = factories.getPayloadParserFactory(element, ns, attributes);
+ CPPUNIT_ASSERT(payloadParserFactory);
+ payloadParser.reset(payloadParserFactory->createPayloadParser());
+ }
+ payloadParser->handleStartElement(element, ns, attributes);
+ level++;
+ }
+
+ virtual void handleEndElement(const String& element, const String& ns) {
+ level--;
+ payloadParser->handleEndElement(element, ns);
+ }
+
+ virtual void handleCharacterData(const String& data) {
+ payloadParser->handleCharacterData(data);
+ }
+
+ boost::shared_ptr<Payload> getPayload() const {
+ return payloadParser->getPayload();
+ }
+
+ private:
+ XMLParser* xmlParser;
+ FullPayloadParserFactoryCollection factories;
+ std::auto_ptr<PayloadParser> payloadParser;
+ int level;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp
new file mode 100644
index 0000000..acea437
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp
@@ -0,0 +1,28 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/PriorityParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class PriorityParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(PriorityParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ PriorityParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<priority>-120</priority>"));
+
+ Priority* payload = dynamic_cast<Priority*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(-120, payload->getPriority());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PriorityParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp
new file mode 100644
index 0000000..e820083
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp
@@ -0,0 +1,89 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Elements/Storage.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
+
+using namespace Swift;
+
+class PrivateStorageParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(PrivateStorageParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST(testParse_NoPayload);
+ CPPUNIT_TEST(testParse_MultiplePayloads);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ PrivateStorageParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<query xmlns='jabber:iq:private'>"
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference name='Swift' jid='swift@rooms.swift.im'>"
+ "<nick>Alice</nick>"
+ "</conference>"
+ "</storage>"
+ "</query>"));
+
+ boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+ CPPUNIT_ASSERT(payload);
+ boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
+ CPPUNIT_ASSERT(storage);
+ CPPUNIT_ASSERT_EQUAL(String("Alice"), storage->getConferences()[0].nick);
+ CPPUNIT_ASSERT_EQUAL(JID("swift@rooms.swift.im"), storage->getConferences()[0].jid);
+ }
+
+ void testParse_NoPayload() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:private'/>"));
+
+ boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+ CPPUNIT_ASSERT(payload);
+ CPPUNIT_ASSERT(!payload->getPayload());
+ }
+
+ void testParse_MultiplePayloads() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<query xmlns='jabber:iq:private'>"
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference name='Swift' jid='swift@rooms.swift.im'>"
+ "<nick>Alice</nick>"
+ "</conference>"
+ "</storage>"
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference name='Swift' jid='swift@rooms.swift.im'>"
+ "<nick>Rabbit</nick>"
+ "</conference>"
+ "</storage>"
+ "</query>"));
+
+ boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+ CPPUNIT_ASSERT(payload);
+ boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
+ CPPUNIT_ASSERT(storage);
+ CPPUNIT_ASSERT_EQUAL(String("Rabbit"), storage->getConferences()[0].nick);
+ }
+
+ void testParse_UnsupportedPayload() {
+ PayloadParserFactoryCollection factories;
+ PrivateStorageParser testling(&factories);
+ PayloadParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<query xmlns='jabber:iq:private'>"
+ "<foo>Bar</foo>"
+ "</query>"));
+
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<PrivateStorage>(testling.getPayload())->getPayload());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PrivateStorageParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp
new file mode 100644
index 0000000..81cc207
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp
@@ -0,0 +1,34 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
+
+using namespace Swift;
+
+class RawXMLPayloadParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RawXMLPayloadParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ RawXMLPayloadParserTest() {}
+
+ void testParse() {
+ RawXMLPayloadParser testling;
+ PayloadParserTester parser(&testling);
+
+ String xml =
+ "<foo foo-attr=\"foo-val\" xmlns=\"ns:foo\">"
+ "<bar bar-attr=\"bar-val\" xmlns=\"ns:bar\"/>"
+ "<baz baz-attr=\"baz-val\" xmlns=\"ns:baz\"/>"
+ "</foo>";
+ CPPUNIT_ASSERT(parser.parse(xml));
+
+ RawXMLPayload* payload = dynamic_cast<RawXMLPayload*>(testling.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(xml, payload->getRawXML());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RawXMLPayloadParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp
new file mode 100644
index 0000000..b1b61ef
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp
@@ -0,0 +1,38 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/ResourceBindParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class ResourceBindParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ResourceBindParserTest);
+ CPPUNIT_TEST(testParse_JID);
+ CPPUNIT_TEST(testParse_Resource);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ ResourceBindParserTest() {}
+
+ void testParse_JID() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>somenode@example.com/someresource</jid></bind>"));
+
+ ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(JID("somenode@example.com/someresource"), payload->getJID());
+ }
+
+ void testParse_Resource() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>someresource</resource></bind>"));
+
+ ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("someresource"), payload->getResource());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ResourceBindParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp
new file mode 100644
index 0000000..4c8db07
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp
@@ -0,0 +1,50 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/RosterParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class RosterParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RosterParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ RosterParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+ parser.parse(
+ "<query xmlns='jabber:iq:roster'>"
+ " <item jid='foo@bar.com' name='Foo @ Bar' subscription='from' ask='subscribe'>"
+ " <group>Group 1</group>"
+ " <group>Group 2</group>"
+ " </item>"
+ " <item jid='baz@blo.com' name='Baz'/>"
+ "</query>");
+
+ RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get());
+ const RosterPayload::RosterItemPayloads& items = payload->getItems();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size());
+
+ CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), items[0].getJID());
+ CPPUNIT_ASSERT_EQUAL(String("Foo @ Bar"), items[0].getName());
+ CPPUNIT_ASSERT_EQUAL(RosterItemPayload::From, items[0].getSubscription());
+ CPPUNIT_ASSERT(items[0].getSubscriptionRequested());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size());
+ CPPUNIT_ASSERT_EQUAL(String("Group 1"), items[0].getGroups()[0]);
+ CPPUNIT_ASSERT_EQUAL(String("Group 2"), items[0].getGroups()[1]);
+
+ CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID());
+ CPPUNIT_ASSERT_EQUAL(String("Baz"), items[1].getName());
+ CPPUNIT_ASSERT_EQUAL(RosterItemPayload::None, items[1].getSubscription());
+ CPPUNIT_ASSERT(!items[1].getSubscriptionRequested());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RosterParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp
new file mode 100644
index 0000000..8272bee
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp
@@ -0,0 +1,45 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/SecurityLabelParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class SecurityLabelParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SecurityLabelParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ SecurityLabelParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">"
+ "<displaymarking fgcolor=\"black\" bgcolor=\"red\">SECRET</displaymarking>"
+ "<label>"
+ "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"
+ "</label>"
+ "<equivalentlabel>"
+ "<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>"
+ "</equivalentlabel>"
+ "<equivalentlabel>"
+ "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"
+ "</equivalentlabel>"
+ "</securitylabel>"));
+
+ SecurityLabel* payload = dynamic_cast<SecurityLabel*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("SECRET"), payload->getDisplayMarking());
+ CPPUNIT_ASSERT_EQUAL(String("black"), payload->getForegroundColor());
+ CPPUNIT_ASSERT_EQUAL(String("red"), payload->getBackgroundColor());
+ CPPUNIT_ASSERT_EQUAL(String("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getLabel());
+ CPPUNIT_ASSERT_EQUAL(String("<icismlabel classification=\"S\" disseminationControls=\"FOUO\" ownerProducer=\"USA\" xmlns=\"http://example.gov/IC-ISM/0\"/>"), payload->getEquivalentLabels()[0]);
+ CPPUNIT_ASSERT_EQUAL(String("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"), payload->getEquivalentLabels()[1]);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp
new file mode 100644
index 0000000..b2378b6
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp
@@ -0,0 +1,45 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class SecurityLabelsCatalogParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SecurityLabelsCatalogParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ SecurityLabelsCatalogParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:0\">"
+ "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">"
+ "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>"
+ "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>"
+ "</securitylabel>"
+ "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">"
+ "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>"
+ "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>"
+ "</securitylabel>"
+ "</catalog>"));
+
+ SecurityLabelsCatalog* payload = dynamic_cast<SecurityLabelsCatalog*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("Default"), payload->getName());
+ CPPUNIT_ASSERT_EQUAL(String("an example set of labels"), payload->getDescription());
+ CPPUNIT_ASSERT_EQUAL(JID("example.com"), payload->getTo());
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getLabels().size()));
+ CPPUNIT_ASSERT_EQUAL(String("SECRET"), payload->getLabels()[0].getDisplayMarking());
+ CPPUNIT_ASSERT_EQUAL(String("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getLabels()[0].getLabel());
+ CPPUNIT_ASSERT_EQUAL(String("CONFIDENTIAL"), payload->getLabels()[1].getDisplayMarking());
+ CPPUNIT_ASSERT_EQUAL(String("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"), payload->getLabels()[1].getLabel());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelsCatalogParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp
new file mode 100644
index 0000000..eeaa8d9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp
@@ -0,0 +1,35 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class SoftwareVersionParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SoftwareVersionParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ SoftwareVersionParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<query xmlns=\"jabber:iq:version\">"
+ "<name>myclient</name>"
+ "<version>1.0</version>"
+ "<os>Mac OS X</os>"
+ "</query>"));
+
+ SoftwareVersion* payload = dynamic_cast<SoftwareVersion*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("myclient"), payload->getName());
+ CPPUNIT_ASSERT_EQUAL(String("1.0"), payload->getVersion());
+ CPPUNIT_ASSERT_EQUAL(String("Mac OS X"), payload->getOS());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SoftwareVersionParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp
new file mode 100644
index 0000000..71d5b0b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp
@@ -0,0 +1,28 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/StatusParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class StatusParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(StatusParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StatusParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<status>foo<baz>bar</baz>fum</status>"));
+
+ Status* payload = dynamic_cast<Status*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("foobarfum"), payload->getText());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StatusParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp
new file mode 100644
index 0000000..d45e98b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp
@@ -0,0 +1,68 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/StatusShowParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class StatusShowParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(StatusShowParserTest);
+ CPPUNIT_TEST(testParse_Invalid);
+ CPPUNIT_TEST(testParse_Away);
+ CPPUNIT_TEST(testParse_FFC);
+ CPPUNIT_TEST(testParse_XA);
+ CPPUNIT_TEST(testParse_DND);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StatusShowParserTest() {}
+
+ void testParse_Invalid() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<show>invalid</show>"));
+
+ StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(StatusShow::Online == payload->getType());
+ }
+
+ void testParse_Away() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<show>away</show>"));
+
+ StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(StatusShow::Away == payload->getType());
+ }
+
+ void testParse_FFC() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<show>chat</show>"));
+
+ StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(StatusShow::FFC == payload->getType());
+ }
+
+ void testParse_XA() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<show>xa</show>"));
+
+ StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(StatusShow::XA == payload->getType());
+ }
+
+ void testParse_DND() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<show>dnd</show>"));
+
+ StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(StatusShow::DND == payload->getType());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StatusShowParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
new file mode 100644
index 0000000..3fbf27a
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
@@ -0,0 +1,64 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class StorageParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(StorageParserTest);
+ CPPUNIT_TEST(testParse_Conference);
+ CPPUNIT_TEST(testParse_MultipleConferences);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StorageParserTest() {}
+
+ void testParse_Conference() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference "
+ "name='Council of Oberon' "
+ "autojoin='true' jid='council@conference.underhill.org'>"
+ "<nick>Puck</nick>"
+ "<password>MyPass</password>"
+ "</conference>"
+ "</storage>"));
+
+ Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get());
+ std::vector<Storage::Conference> conferences = payload->getConferences();
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(conferences.size()));
+ CPPUNIT_ASSERT_EQUAL(String("Council of Oberon"), conferences[0].name);
+ CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), conferences[0].jid);
+ CPPUNIT_ASSERT(conferences[0].autoJoin);
+ CPPUNIT_ASSERT_EQUAL(String("Puck"), conferences[0].nick);
+ CPPUNIT_ASSERT_EQUAL(String("MyPass"), conferences[0].password);
+ }
+
+ void testParse_MultipleConferences() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference "
+ "name='Council of Oberon' "
+ "jid='council@conference.underhill.org' />"
+ "<conference "
+ "name='Tea party' "
+ "jid='teaparty@wonderland.lit' />"
+ "</storage>"));
+
+ Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get());
+ std::vector<Storage::Conference> conferences = payload->getConferences();
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(conferences.size()));
+ CPPUNIT_ASSERT_EQUAL(String("Council of Oberon"), conferences[0].name);
+ CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), conferences[0].jid);
+ CPPUNIT_ASSERT_EQUAL(String("Tea party"), conferences[1].name);
+ CPPUNIT_ASSERT_EQUAL(JID("teaparty@wonderland.lit"), conferences[1].jid);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StorageParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
new file mode 100644
index 0000000..d1ddba3
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
@@ -0,0 +1,51 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/VCardParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class VCardParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(VCardParserTest);
+ CPPUNIT_TEST(testParse_Photo);
+ CPPUNIT_TEST(testParse_Nickname);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ VCardParserTest() {}
+
+ void testParse_Photo() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<vCard xmlns='vcard-temp'>"
+ "<PHOTO>"
+ "<TYPE>image/jpeg</TYPE>"
+ "<BINVAL>"
+ "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ej"
+ "EyMzQ1Njc4OTA="
+ "</BINVAL>"
+ "</PHOTO>"
+ "</vCard>"));
+
+ VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), payload->getPhotoType());
+ CPPUNIT_ASSERT_EQUAL(ByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"), payload->getPhoto());
+ }
+
+ void testParse_Nickname() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<vCard xmlns='vcard-temp'>"
+ "<NICKNAME>mynick</NICKNAME>"
+ "</vCard>"));
+
+ VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("mynick"), payload->getNickname());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VCardParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp
new file mode 100644
index 0000000..ef6c78e
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp
@@ -0,0 +1,31 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/VCardUpdateParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class VCardUpdateParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(VCardUpdateParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ VCardUpdateParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<x xmlns='vcard-temp:x:update'>"
+ "<photo>sha1-hash-of-image</photo>"
+ "</x>"));
+
+ VCardUpdate* payload = dynamic_cast<VCardUpdate*>(parser.getPayload().get());
+ CPPUNIT_ASSERT_EQUAL(String("sha1-hash-of-image"), payload->getPhotoHash());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateParserTest);
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp
new file mode 100644
index 0000000..87416ab
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp
@@ -0,0 +1,53 @@
+#include "Swiften/Parser/PayloadParsers/VCardParser.h"
+#include "Swiften/Base/foreach.h"
+#include "Swiften/StringCodecs/Base64.h"
+
+namespace Swift {
+
+VCardParser::VCardParser() {
+}
+
+void VCardParser::handleStartElement(const String& element, const String&, const AttributeMap&) {
+ elementStack_.push_back(element);
+ currentText_ = "";
+}
+
+void VCardParser::handleEndElement(const String&, const String&) {
+ String elementHierarchy = getElementHierarchy();
+ if (elementHierarchy == "/vCard/PHOTO/TYPE") {
+ getPayloadInternal()->setPhotoType(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/PHOTO/BINVAL") {
+ getPayloadInternal()->setPhoto(Base64::decode(currentText_));
+ }
+ else if (elementHierarchy == "/vCard/NICKNAME") {
+ getPayloadInternal()->setNickname(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/FN") {
+ getPayloadInternal()->setFullName(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/N/FAMILY") {
+ getPayloadInternal()->setFamilyName(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/N/GIVEN") {
+ getPayloadInternal()->setGivenName(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/EMAIL/USERID") {
+ getPayloadInternal()->setEMail(currentText_);
+ }
+ elementStack_.pop_back();
+}
+
+void VCardParser::handleCharacterData(const String& text) {
+ currentText_ += text;
+}
+
+String VCardParser::getElementHierarchy() const {
+ String result;
+ foreach(const String& element, elementStack_) {
+ result += "/" + element;
+ }
+ return result;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h
new file mode 100644
index 0000000..c1ed46b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardParser.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "Swiften/Elements/VCard.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SerializingParser;
+
+ class VCardParser : public GenericPayloadParser<VCard> {
+ public:
+ VCardParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ String getElementHierarchy() const;
+
+ private:
+ std::vector<String> elementStack_;
+ String currentText_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/VCardParserFactory.h b/Swiften/Parser/PayloadParsers/VCardParserFactory.h
new file mode 100644
index 0000000..2d5302b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardParserFactory.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/VCardParser.h"
+
+namespace Swift {
+ class VCardParserFactory : public GenericPayloadParserFactory<VCardParser> {
+ public:
+ VCardParserFactory() : GenericPayloadParserFactory<VCardParser>("vCard", "vcard-temp") {}
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp
new file mode 100644
index 0000000..e195eb7
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp
@@ -0,0 +1,26 @@
+#include "Swiften/Parser/PayloadParsers/VCardUpdateParser.h"
+
+namespace Swift {
+
+VCardUpdateParser::VCardUpdateParser() : level_(TopLevel) {
+}
+
+void VCardUpdateParser::handleStartElement(const String&, const String&, const AttributeMap&) {
+ if (level_ == PayloadLevel) {
+ currentText_ = "";
+ }
+ ++level_;
+}
+
+void VCardUpdateParser::handleEndElement(const String& element, const String&) {
+ --level_;
+ if (level_ == PayloadLevel && element == "photo") {
+ getPayloadInternal()->setPhotoHash(currentText_);
+ }
+}
+
+void VCardUpdateParser::handleCharacterData(const String& text) {
+ currentText_ += text;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParser.h b/Swiften/Parser/PayloadParsers/VCardUpdateParser.h
new file mode 100644
index 0000000..3682ccf
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardUpdateParser.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Swiften/Elements/VCardUpdate.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SerializingParser;
+
+ class VCardUpdateParser : public GenericPayloadParser<VCardUpdate> {
+ public:
+ VCardUpdateParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+ int level_;
+ String currentText_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h b/Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h
new file mode 100644
index 0000000..0a8dddf
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/VCardUpdateParser.h"
+
+namespace Swift {
+ class VCardUpdateParserFactory : public GenericPayloadParserFactory<VCardUpdateParser> {
+ public:
+ VCardUpdateParserFactory() : GenericPayloadParserFactory<VCardUpdateParser>("x", "vcard-temp:x:update") {}
+ };
+}
diff --git a/Swiften/Parser/PlatformXMLParserFactory.cpp b/Swiften/Parser/PlatformXMLParserFactory.cpp
new file mode 100644
index 0000000..0624a2d
--- /dev/null
+++ b/Swiften/Parser/PlatformXMLParserFactory.cpp
@@ -0,0 +1,25 @@
+#include "Swiften/Parser/PlatformXMLParserFactory.h"
+
+#include <cassert>
+
+#ifdef HAVE_LIBXML
+#include "Swiften/Parser/LibXMLParser.h"
+#else
+#include "Swiften/Parser/ExpatParser.h"
+#endif
+
+
+namespace Swift {
+
+PlatformXMLParserFactory::PlatformXMLParserFactory() {
+}
+
+XMLParser* PlatformXMLParserFactory::createXMLParser(XMLParserClient* client) {
+#ifdef HAVE_LIBXML
+ return new LibXMLParser(client);
+#else
+ return new ExpatParser(client);
+#endif
+}
+
+}
diff --git a/Swiften/Parser/PlatformXMLParserFactory.h b/Swiften/Parser/PlatformXMLParserFactory.h
new file mode 100644
index 0000000..28b1657
--- /dev/null
+++ b/Swiften/Parser/PlatformXMLParserFactory.h
@@ -0,0 +1,15 @@
+#ifndef SWIFTEN_PlatformXMLParserFactory_H
+#define SWIFTEN_PlatformXMLParserFactory_H
+
+#include "Swiften/Parser/XMLParserFactory.h"
+
+namespace Swift {
+ class PlatformXMLParserFactory : public XMLParserFactory {
+ public:
+ PlatformXMLParserFactory();
+
+ virtual XMLParser* createXMLParser(XMLParserClient*);
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/PresenceParser.cpp b/Swiften/Parser/PresenceParser.cpp
new file mode 100644
index 0000000..72cdd4c
--- /dev/null
+++ b/Swiften/Parser/PresenceParser.cpp
@@ -0,0 +1,45 @@
+#include <iostream>
+
+#include "Swiften/Parser/PresenceParser.h"
+
+namespace Swift {
+
+PresenceParser::PresenceParser(PayloadParserFactoryCollection* factories) :
+ GenericStanzaParser<Presence>(factories) {
+}
+
+void PresenceParser::handleStanzaAttributes(const AttributeMap& attributes) {
+ AttributeMap::const_iterator type = attributes.find("type");
+ if (type != attributes.end()) {
+ if (type->second == "unavailable") {
+ getStanzaGeneric()->setType(Presence::Unavailable);
+ }
+ else if (type->second == "probe") {
+ getStanzaGeneric()->setType(Presence::Probe);
+ }
+ else if (type->second == "subscribe") {
+ getStanzaGeneric()->setType(Presence::Subscribe);
+ }
+ else if (type->second == "subscribed") {
+ getStanzaGeneric()->setType(Presence::Subscribed);
+ }
+ else if (type->second == "unsubscribe") {
+ getStanzaGeneric()->setType(Presence::Unsubscribe);
+ }
+ else if (type->second == "unsubscribed") {
+ getStanzaGeneric()->setType(Presence::Unsubscribed);
+ }
+ else if (type->second == "error") {
+ getStanzaGeneric()->setType(Presence::Error);
+ }
+ else {
+ std::cerr << "Unknown Presence type: " << type->second << std::endl;
+ getStanzaGeneric()->setType(Presence::Available);
+ }
+ }
+ else {
+ getStanzaGeneric()->setType(Presence::Available);
+ }
+}
+
+}
diff --git a/Swiften/Parser/PresenceParser.h b/Swiften/Parser/PresenceParser.h
new file mode 100644
index 0000000..b3ba445
--- /dev/null
+++ b/Swiften/Parser/PresenceParser.h
@@ -0,0 +1,17 @@
+#ifndef SWIFTEN_PresenceParser_H
+#define SWIFTEN_PresenceParser_H
+
+#include "Swiften/Parser/GenericStanzaParser.h"
+#include "Swiften/Elements/Presence.h"
+
+namespace Swift {
+ class PresenceParser : public GenericStanzaParser<Presence> {
+ public:
+ PresenceParser(PayloadParserFactoryCollection* factories);
+
+ private:
+ virtual void handleStanzaAttributes(const AttributeMap&);
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
new file mode 100644
index 0000000..7d93d8b
--- /dev/null
+++ b/Swiften/Parser/SConscript
@@ -0,0 +1,58 @@
+Import("swiften_env")
+
+myenv = swiften_env.Clone()
+myenv.MergeFlags(swiften_env["BOOST_FLAGS"])
+myenv.MergeFlags(swiften_env.get("LIBXML_FLAGS", ""))
+myenv.MergeFlags(swiften_env.get("EXPAT_FLAGS", ""))
+
+sources = [
+ "AuthRequestParser.cpp",
+ "AuthChallengeParser.cpp",
+ "AuthSuccessParser.cpp",
+ "AuthResponseParser.cpp",
+ "CompressParser.cpp",
+ "ElementParser.cpp",
+ "IQParser.cpp",
+ "MessageParser.cpp",
+ "PayloadParser.cpp",
+ "PayloadParserFactory.cpp",
+ "PayloadParserFactoryCollection.cpp",
+ "PayloadParsers/BodyParser.cpp",
+ "PayloadParsers/ChatStateParser.cpp",
+ "PayloadParsers/DiscoInfoParser.cpp",
+ "PayloadParsers/ErrorParser.cpp",
+ "PayloadParsers/FullPayloadParserFactoryCollection.cpp",
+ "PayloadParsers/PriorityParser.cpp",
+ "PayloadParsers/PrivateStorageParser.cpp",
+ "PayloadParsers/RawXMLPayloadParser.cpp",
+ "PayloadParsers/ResourceBindParser.cpp",
+ "PayloadParsers/RosterParser.cpp",
+ "PayloadParsers/SecurityLabelParser.cpp",
+ "PayloadParsers/SecurityLabelsCatalogParser.cpp",
+ "PayloadParsers/SoftwareVersionParser.cpp",
+ "PayloadParsers/StorageParser.cpp",
+ "PayloadParsers/StatusParser.cpp",
+ "PayloadParsers/StatusShowParser.cpp",
+ "PayloadParsers/VCardParser.cpp",
+ "PayloadParsers/VCardUpdateParser.cpp",
+ "PlatformXMLParserFactory.cpp",
+ "PresenceParser.cpp",
+ "SerializingParser.cpp",
+ "StanzaParser.cpp",
+ "StreamFeaturesParser.cpp",
+ "XMLParser.cpp",
+ "XMLParserClient.cpp",
+ "XMLParserFactory.cpp",
+ "XMPPParser.cpp",
+ "XMPPParserClient.cpp",
+ ]
+
+if myenv.get("HAVE_EXPAT", 0) :
+ myenv.Append(CPPDEFINES = "HAVE_EXPAT")
+ sources += ["ExpatParser.cpp"]
+if myenv.get("HAVE_LIBXML", 0) :
+ myenv.Append(CPPDEFINES = "HAVE_LIBXML")
+ sources += ["LibXMLParser.cpp"]
+
+objects = myenv.StaticObject(sources)
+swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Parser/SerializingParser.cpp b/Swiften/Parser/SerializingParser.cpp
new file mode 100644
index 0000000..f69e732
--- /dev/null
+++ b/Swiften/Parser/SerializingParser.cpp
@@ -0,0 +1,41 @@
+#include "Swiften/Parser/SerializingParser.h"
+#include "Swiften/Serializer/XML/XMLTextNode.h"
+#include "Swiften/Base/foreach.h"
+#include <iostream>
+
+namespace Swift {
+
+SerializingParser::SerializingParser() {
+}
+
+void SerializingParser::handleStartElement(const String& tag, const String& ns, const AttributeMap& attributes) {
+ boost::shared_ptr<XMLElement> element(new XMLElement(tag, ns));
+ for (AttributeMap::const_iterator i = attributes.begin(); i != attributes.end(); ++i) {
+ element->setAttribute((*i).first, (*i).second);
+ }
+
+ if (elementStack_.empty()) {
+ rootElement_ = element;
+ }
+ else {
+ (*(elementStack_.end() - 1))->addNode(element);
+ }
+ elementStack_.push_back(element);
+}
+
+void SerializingParser::handleEndElement(const String&, const String&) {
+ assert(!elementStack_.empty());
+ elementStack_.pop_back();
+}
+
+void SerializingParser::handleCharacterData(const String& data) {
+ if (!elementStack_.empty()) {
+ (*(elementStack_.end()-1))->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(data)));
+ }
+}
+
+String SerializingParser::getResult() const {
+ return (rootElement_ ? rootElement_->serialize() : "");
+}
+
+}
diff --git a/Swiften/Parser/SerializingParser.h b/Swiften/Parser/SerializingParser.h
new file mode 100644
index 0000000..b1d4575
--- /dev/null
+++ b/Swiften/Parser/SerializingParser.h
@@ -0,0 +1,25 @@
+#ifndef SWIFTEN_SerializingParser_H
+#define SWIFTEN_SerializingParser_H
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/AttributeMap.h"
+#include "Swiften/Serializer/XML/XMLElement.h"
+
+namespace Swift {
+ class SerializingParser {
+ public:
+ SerializingParser();
+
+ void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes);
+ void handleEndElement(const String& element, const String& ns);
+ void handleCharacterData(const String& data);
+
+ String getResult() const;
+
+ private:
+ std::vector< boost::shared_ptr<XMLElement> > elementStack_;
+ boost::shared_ptr<XMLElement> rootElement_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/StanzaParser.cpp b/Swiften/Parser/StanzaParser.cpp
new file mode 100644
index 0000000..952265c
--- /dev/null
+++ b/Swiften/Parser/StanzaParser.cpp
@@ -0,0 +1,78 @@
+#include "Swiften/Parser/StanzaParser.h"
+
+#include <iostream>
+#include <cassert>
+
+#include "Swiften/Parser/PayloadParser.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/UnknownPayloadParser.h"
+
+namespace Swift {
+
+StanzaParser::StanzaParser(PayloadParserFactoryCollection* factories) :
+ currentDepth_(0), factories_(factories) {
+}
+
+StanzaParser::~StanzaParser() {
+}
+
+void StanzaParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ if (inStanza()) {
+ if (!inPayload()) {
+ assert(!currentPayloadParser_.get());
+ PayloadParserFactory* payloadParserFactory = factories_->getPayloadParserFactory(element, ns, attributes);
+ if (payloadParserFactory) {
+ currentPayloadParser_.reset(payloadParserFactory->createPayloadParser());
+ }
+ else {
+ currentPayloadParser_.reset(new UnknownPayloadParser());
+ }
+ }
+ assert(currentPayloadParser_.get());
+ currentPayloadParser_->handleStartElement(element, ns, attributes);
+ }
+ else {
+ AttributeMap::const_iterator from = attributes.find("from");
+ if (from != attributes.end()) {
+ getStanza()->setFrom(JID(from->second));
+ }
+ AttributeMap::const_iterator to = attributes.find("to");
+ if (to != attributes.end()) {
+ getStanza()->setTo(JID(to->second));
+ }
+ AttributeMap::const_iterator id = attributes.find("id");
+ if (id != attributes.end()) {
+ getStanza()->setID(id->second);
+ }
+ handleStanzaAttributes(attributes);
+ }
+ ++currentDepth_;
+}
+
+void StanzaParser::handleEndElement(const String& element, const String& ns) {
+ assert(inStanza());
+ if (inPayload()) {
+ assert(currentPayloadParser_.get());
+ currentPayloadParser_->handleEndElement(element, ns);
+ --currentDepth_;
+ if (!inPayload()) {
+ boost::shared_ptr<Payload> payload(currentPayloadParser_->getPayload());
+ if (payload) {
+ getStanza()->addPayload(payload);
+ }
+ currentPayloadParser_.reset();
+ }
+ }
+ else {
+ --currentDepth_;
+ }
+}
+
+void StanzaParser::handleCharacterData(const String& data) {
+ if (currentPayloadParser_.get()) {
+ currentPayloadParser_->handleCharacterData(data);
+ }
+}
+
+}
diff --git a/Swiften/Parser/StanzaParser.h b/Swiften/Parser/StanzaParser.h
new file mode 100644
index 0000000..c6cf753
--- /dev/null
+++ b/Swiften/Parser/StanzaParser.h
@@ -0,0 +1,48 @@
+#ifndef SWIFTEN_StanzaParser_H
+#define SWIFTEN_StanzaParser_H
+
+#include <boost/noncopyable.hpp>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Elements/Stanza.h"
+#include "Swiften/Parser/ElementParser.h"
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class PayloadParser;
+ class PayloadParserFactoryCollection;
+
+ class StanzaParser : public ElementParser, public boost::noncopyable {
+ public:
+ StanzaParser(PayloadParserFactoryCollection* factories);
+ ~StanzaParser();
+
+ void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes);
+ void handleEndElement(const String& element, const String& ns);
+ void handleCharacterData(const String& data);
+
+ virtual boost::shared_ptr<Element> getElement() const = 0;
+ virtual void handleStanzaAttributes(const AttributeMap&) {}
+
+ virtual boost::shared_ptr<Stanza> getStanza() const {
+ return boost::dynamic_pointer_cast<Stanza>(getElement());
+ }
+
+ private:
+ bool inPayload() const {
+ return currentDepth_ > 1;
+ }
+
+ bool inStanza() const {
+ return currentDepth_ > 0;
+ }
+
+
+ private:
+ int currentDepth_;
+ PayloadParserFactoryCollection* factories_;
+ std::auto_ptr<PayloadParser> currentPayloadParser_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/StartTLSFailureParser.h b/Swiften/Parser/StartTLSFailureParser.h
new file mode 100644
index 0000000..c955ca0
--- /dev/null
+++ b/Swiften/Parser/StartTLSFailureParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_StartTLSFailureParser_H
+#define SWIFTEN_StartTLSFailureParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/StartTLSFailure.h"
+
+namespace Swift {
+ class StartTLSFailureParser : public GenericElementParser<StartTLSFailure> {
+ public:
+ StartTLSFailureParser() : GenericElementParser<StartTLSFailure>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/StartTLSParser.h b/Swiften/Parser/StartTLSParser.h
new file mode 100644
index 0000000..afacec2
--- /dev/null
+++ b/Swiften/Parser/StartTLSParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_StartTLSParser_H
+#define SWIFTEN_StartTLSParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/StartTLSRequest.h"
+
+namespace Swift {
+ class StartTLSParser : public GenericElementParser<StartTLSRequest> {
+ public:
+ StartTLSParser() : GenericElementParser<StartTLSRequest>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/StreamFeaturesParser.cpp b/Swiften/Parser/StreamFeaturesParser.cpp
new file mode 100644
index 0000000..5072e7c
--- /dev/null
+++ b/Swiften/Parser/StreamFeaturesParser.cpp
@@ -0,0 +1,61 @@
+#include "Swiften/Parser/StreamFeaturesParser.h"
+
+namespace Swift {
+
+StreamFeaturesParser::StreamFeaturesParser() : GenericElementParser<StreamFeatures>(), currentDepth_(0), inMechanisms_(false), inMechanism_(false), inCompression_(false), inCompressionMethod_(false) {
+}
+
+void StreamFeaturesParser::handleStartElement(const String& element, const String& ns, const AttributeMap&) {
+ if (currentDepth_ == 1) {
+ if (element == "starttls" && ns == "urn:ietf:params:xml:ns:xmpp-tls") {
+ getElementGeneric()->setHasStartTLS();
+ }
+ else if (element == "session" && ns == "urn:ietf:params:xml:ns:xmpp-session") {
+ getElementGeneric()->setHasSession();
+ }
+ else if (element == "bind" && ns == "urn:ietf:params:xml:ns:xmpp-bind") {
+ getElementGeneric()->setHasResourceBind();
+ }
+ else if (element == "mechanisms" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") {
+ inMechanisms_ = true;
+ }
+ else if (element == "compression" && ns == "http://jabber.org/features/compress") {
+ inCompression_ = true;
+ }
+ }
+ else if (currentDepth_ == 2) {
+ if (inCompression_ && element == "method") {
+ inCompressionMethod_ = true;
+ currentText_ = "";
+ }
+ else if (inMechanisms_ && element == "mechanism") {
+ inMechanism_ = true;
+ currentText_ = "";
+ }
+ }
+ ++currentDepth_;
+}
+
+void StreamFeaturesParser::handleEndElement(const String&, const String&) {
+ --currentDepth_;
+ if (currentDepth_ == 1) {
+ inCompression_ = false;
+ inMechanisms_ = false;
+ }
+ else if (currentDepth_ == 2) {
+ if (inCompressionMethod_) {
+ getElementGeneric()->addCompressionMethod(currentText_);
+ inCompressionMethod_ = false;
+ }
+ else if (inMechanism_) {
+ getElementGeneric()->addAuthenticationMechanism(currentText_);
+ inMechanism_ = false;
+ }
+ }
+}
+
+void StreamFeaturesParser::handleCharacterData(const String& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/StreamFeaturesParser.h b/Swiften/Parser/StreamFeaturesParser.h
new file mode 100644
index 0000000..184a7e6
--- /dev/null
+++ b/Swiften/Parser/StreamFeaturesParser.h
@@ -0,0 +1,28 @@
+#ifndef SWIFTEN_STREAMFEATURESPARSER_H
+#define SWIFTEN_STREAMFEATURESPARSER_H
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/StreamFeatures.h"
+
+namespace Swift {
+ class StreamFeaturesParser : public GenericElementParser<StreamFeatures> {
+ public:
+ StreamFeaturesParser();
+
+ private:
+ void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes);
+ void handleEndElement(const String& element, const String& ns);
+ void handleCharacterData(const String& data);
+
+ private:
+ int currentDepth_;
+ String currentText_;
+ bool inMechanisms_;
+ bool inMechanism_;
+ bool inCompression_;
+ bool inCompressionMethod_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/TLSProceedParser.h b/Swiften/Parser/TLSProceedParser.h
new file mode 100644
index 0000000..2ad5438
--- /dev/null
+++ b/Swiften/Parser/TLSProceedParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_TLSProceedParser_H
+#define SWIFTEN_TLSProceedParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/TLSProceed.h"
+
+namespace Swift {
+ class TLSProceedParser : public GenericElementParser<TLSProceed> {
+ public:
+ TLSProceedParser() : GenericElementParser<TLSProceed>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/UnitTest/AttributeMapTest.cpp b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
new file mode 100644
index 0000000..17bda95
--- /dev/null
+++ b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
@@ -0,0 +1,71 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/AttributeMap.h"
+
+using namespace Swift;
+
+class AttributeMapTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(AttributeMapTest);
+ CPPUNIT_TEST(testGetBoolAttribute_True);
+ CPPUNIT_TEST(testGetBoolAttribute_1);
+ CPPUNIT_TEST(testGetBoolAttribute_False);
+ CPPUNIT_TEST(testGetBoolAttribute_0);
+ CPPUNIT_TEST(testGetBoolAttribute_Invalid);
+ CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultTrue);
+ CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultFalse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ AttributeMapTest() {}
+
+ void testGetBoolAttribute_True() {
+ AttributeMap testling;
+ testling["foo"] = "true";
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
+ }
+
+ void testGetBoolAttribute_1() {
+ AttributeMap testling;
+ testling["foo"] = "1";
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
+ }
+
+ void testGetBoolAttribute_False() {
+ AttributeMap testling;
+ testling["foo"] = "false";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_0() {
+ AttributeMap testling;
+ testling["foo"] = "0";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_Invalid() {
+ AttributeMap testling;
+ testling["foo"] = "bla";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_UnknownWithDefaultTrue() {
+ AttributeMap testling;
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_UnknownWithDefaultFalse() {
+ AttributeMap testling;
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", false));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AttributeMapTest);
diff --git a/Swiften/Parser/UnitTest/ElementParserTester.h b/Swiften/Parser/UnitTest/ElementParserTester.h
new file mode 100644
index 0000000..4d84c44
--- /dev/null
+++ b/Swiften/Parser/UnitTest/ElementParserTester.h
@@ -0,0 +1,10 @@
+#ifndef SWIFTEN_ElementParserTester_H
+#define SWIFTEN_ElementParserTester_H
+
+#include "Swiften/Parser/UnitTest/ParserTester.h"
+
+namespace Swift {
+ typedef ParserTester<ElementParser> ElementParserTester;
+}
+
+#endif
diff --git a/Swiften/Parser/UnitTest/IQParserTest.cpp b/Swiften/Parser/UnitTest/IQParserTest.cpp
new file mode 100644
index 0000000..22b0adc
--- /dev/null
+++ b/Swiften/Parser/UnitTest/IQParserTest.cpp
@@ -0,0 +1,70 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/IQParser.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/UnitTest/StanzaParserTester.h"
+
+using namespace Swift;
+
+class IQParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(IQParserTest);
+ CPPUNIT_TEST(testParse_Set);
+ CPPUNIT_TEST(testParse_Get);
+ CPPUNIT_TEST(testParse_Result);
+ CPPUNIT_TEST(testParse_Error);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ IQParserTest() {}
+
+ void setUp() {
+ factoryCollection_ = new PayloadParserFactoryCollection();
+ }
+
+ void tearDown() {
+ delete factoryCollection_;
+ }
+
+ void testParse_Set() {
+ IQParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<iq type=\"set\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(IQ::Set, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Get() {
+ IQParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<iq type=\"get\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(IQ::Get, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Result() {
+ IQParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<iq type=\"result\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(IQ::Result, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Error() {
+ IQParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<iq type=\"error\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(IQ::Error, testling.getStanzaGeneric()->getType());
+ }
+
+ private:
+ PayloadParserFactoryCollection* factoryCollection_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(IQParserTest);
diff --git a/Swiften/Parser/UnitTest/MessageParserTest.cpp b/Swiften/Parser/UnitTest/MessageParserTest.cpp
new file mode 100644
index 0000000..61a8d20
--- /dev/null
+++ b/Swiften/Parser/UnitTest/MessageParserTest.cpp
@@ -0,0 +1,80 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/MessageParser.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/UnitTest/StanzaParserTester.h"
+
+using namespace Swift;
+
+class MessageParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(MessageParserTest);
+ CPPUNIT_TEST(testParse_Normal);
+ CPPUNIT_TEST(testParse_Chat);
+ CPPUNIT_TEST(testParse_Error);
+ CPPUNIT_TEST(testParse_Groupchat);
+ CPPUNIT_TEST(testParse_Headline);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ MessageParserTest() {}
+
+ void setUp() {
+ factoryCollection_ = new PayloadParserFactoryCollection();
+ }
+
+ void tearDown() {
+ delete factoryCollection_;
+ }
+
+ void testParse_Chat() {
+ MessageParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<message type=\"chat\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Message::Chat, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Groupchat() {
+ MessageParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<message type=\"groupchat\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Message::Groupchat, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Error() {
+ MessageParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<message type=\"error\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Message::Error, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Headline() {
+ MessageParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<message type=\"headline\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Message::Headline, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Normal() {
+ MessageParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<message/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Message::Normal, testling.getStanzaGeneric()->getType());
+ }
+
+ private:
+ PayloadParserFactoryCollection* factoryCollection_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MessageParserTest);
diff --git a/Swiften/Parser/UnitTest/ParserTester.h b/Swiften/Parser/UnitTest/ParserTester.h
new file mode 100644
index 0000000..7aacc8e
--- /dev/null
+++ b/Swiften/Parser/UnitTest/ParserTester.h
@@ -0,0 +1,44 @@
+#ifndef SWIFTEN_ParserTester_H
+#define SWIFTEN_ParserTester_H
+
+#include "Swiften/Parser/XMLParserClient.h"
+#include "Swiften/Parser/PlatformXMLParserFactory.h"
+#include "Swiften/Parser/XMLParser.h"
+
+namespace Swift {
+ class XMLParser;
+
+ template<typename ParserType>
+ class ParserTester : public XMLParserClient {
+ public:
+ ParserTester(ParserType* parser) : parser_(parser) {
+ xmlParser_ = PlatformXMLParserFactory().createXMLParser(this);
+ }
+
+ ~ParserTester() {
+ delete xmlParser_;
+ }
+
+ bool parse(const String& data) {
+ return xmlParser_->parse(data);
+ }
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ parser_->handleStartElement(element, ns, attributes);
+ }
+
+ virtual void handleEndElement(const String& element, const String& ns) {
+ parser_->handleEndElement(element, ns);
+ }
+
+ virtual void handleCharacterData(const String& data) {
+ parser_->handleCharacterData(data);
+ }
+
+ private:
+ XMLParser* xmlParser_;
+ ParserType* parser_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp
new file mode 100644
index 0000000..bfd2c2c
--- /dev/null
+++ b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp
@@ -0,0 +1,97 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+using namespace Swift;
+
+class PayloadParserFactoryCollectionTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(PayloadParserFactoryCollectionTest);
+ CPPUNIT_TEST(testGetPayloadParserFactory);
+ CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchingFactory);
+ CPPUNIT_TEST(testGetPayloadParserFactory_TwoMatchingFactories);
+ CPPUNIT_TEST(testGetPayloadParserFactory_MatchWithDefaultFactory);
+ CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchWithDefaultFactory);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ PayloadParserFactoryCollectionTest() {}
+
+ void setUp() {
+ }
+
+ void tearDown() {
+ }
+
+ void testGetPayloadParserFactory() {
+ PayloadParserFactoryCollection testling;
+ DummyFactory factory1("foo");
+ testling.addFactory(&factory1);
+ DummyFactory factory2("bar");
+ testling.addFactory(&factory2);
+ DummyFactory factory3("baz");
+ testling.addFactory(&factory3);
+
+ PayloadParserFactory* factory = testling.getPayloadParserFactory("bar", "", AttributeMap());
+
+ CPPUNIT_ASSERT(factory == &factory2);
+ }
+
+ void testGetPayloadParserFactory_NoMatchingFactory() {
+ PayloadParserFactoryCollection testling;
+ DummyFactory factory("foo");
+
+ CPPUNIT_ASSERT(!testling.getPayloadParserFactory("bar", "", AttributeMap()));
+ }
+
+ void testGetPayloadParserFactory_TwoMatchingFactories() {
+ PayloadParserFactoryCollection testling;
+ DummyFactory factory1("foo");
+ testling.addFactory(&factory1);
+ DummyFactory factory2("foo");
+ testling.addFactory(&factory2);
+
+ PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap());
+
+ CPPUNIT_ASSERT(factory == &factory2);
+ }
+
+ void testGetPayloadParserFactory_MatchWithDefaultFactory() {
+ PayloadParserFactoryCollection testling;
+ DummyFactory factory1("foo");
+ testling.addFactory(&factory1);
+ DummyFactory factory2;
+ testling.setDefaultFactory(&factory2);
+
+ PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap());
+
+ CPPUNIT_ASSERT(factory == &factory1);
+ }
+
+ void testGetPayloadParserFactory_NoMatchWithDefaultFactory() {
+ PayloadParserFactoryCollection testling;
+ DummyFactory factory1("foo");
+ testling.addFactory(&factory1);
+ DummyFactory factory2;
+ testling.setDefaultFactory(&factory2);
+
+ PayloadParserFactory* factory = testling.getPayloadParserFactory("baz", "", AttributeMap());
+
+ CPPUNIT_ASSERT(factory == &factory2);
+ }
+
+
+ private:
+ struct DummyFactory : public PayloadParserFactory {
+ DummyFactory(const String& element = "") : element(element) {}
+ virtual bool canParse(const String& e, const String&, const AttributeMap&) const {
+ return element.isEmpty() ? true : element == e;
+ }
+ virtual PayloadParser* createPayloadParser() { return NULL; }
+ String element;
+ };
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PayloadParserFactoryCollectionTest);
diff --git a/Swiften/Parser/UnitTest/PresenceParserTest.cpp b/Swiften/Parser/UnitTest/PresenceParserTest.cpp
new file mode 100644
index 0000000..5305161
--- /dev/null
+++ b/Swiften/Parser/UnitTest/PresenceParserTest.cpp
@@ -0,0 +1,110 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PresenceParser.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/UnitTest/StanzaParserTester.h"
+
+using namespace Swift;
+
+class PresenceParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(PresenceParserTest);
+ CPPUNIT_TEST(testParse_Available);
+ CPPUNIT_TEST(testParse_Unavailable);
+ CPPUNIT_TEST(testParse_Subscribe);
+ CPPUNIT_TEST(testParse_Subscribed);
+ CPPUNIT_TEST(testParse_Unsubscribe);
+ CPPUNIT_TEST(testParse_Unsubscribed);
+ CPPUNIT_TEST(testParse_Probe);
+ CPPUNIT_TEST(testParse_Error);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ PresenceParserTest() {}
+
+ void setUp() {
+ factoryCollection_ = new PayloadParserFactoryCollection();
+ }
+
+ void tearDown() {
+ delete factoryCollection_;
+ }
+
+ void testParse_Available() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Available, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Unavailable() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"unavailable\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Probe() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"probe\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Probe, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Subscribe() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribe\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Subscribe, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Subscribed() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribed\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Subscribed, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Unsubscribe() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribe\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribe, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Unsubscribed() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribed\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribed, testling.getStanzaGeneric()->getType());
+ }
+
+ void testParse_Error() {
+ PresenceParser testling(factoryCollection_);
+ StanzaParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse("<presence type=\"error\"/>"));
+
+ CPPUNIT_ASSERT_EQUAL(Presence::Error, testling.getStanzaGeneric()->getType());
+ }
+
+ private:
+ PayloadParserFactoryCollection* factoryCollection_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PresenceParserTest);
diff --git a/Swiften/Parser/UnitTest/SerializingParserTest.cpp b/Swiften/Parser/UnitTest/SerializingParserTest.cpp
new file mode 100644
index 0000000..e08a3d0
--- /dev/null
+++ b/Swiften/Parser/UnitTest/SerializingParserTest.cpp
@@ -0,0 +1,58 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/SerializingParser.h"
+#include "Swiften/Parser/UnitTest/StanzaParserTester.h"
+
+using namespace Swift;
+
+class SerializingParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SerializingParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST(testParse_Empty);
+ CPPUNIT_TEST(testParse_ToplevelCharacterData);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ SerializingParserTest() {}
+
+ void testParse() {
+ SerializingParser testling;
+ ParserTester<SerializingParser> parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<message type=\"chat\" to=\"me@foo.com\">"
+ "<body>Hello&lt;&amp;World</body>"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "foo<b>bar</b>baz"
+ "</html>"
+ "</message>"));
+
+ CPPUNIT_ASSERT_EQUAL(String(
+ "<message to=\"me@foo.com\" type=\"chat\">"
+ "<body>Hello&lt;&amp;World</body>"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">foo<b xmlns=\"http://www.w3.org/1999/xhtml\">bar</b>baz</html>"
+ "</message>"), testling.getResult());
+ }
+
+ void testParse_Empty() {
+ SerializingParser testling;
+
+ CPPUNIT_ASSERT_EQUAL(String(""), testling.getResult());
+ }
+
+ void testParse_ToplevelCharacterData() {
+ SerializingParser testling;
+
+ AttributeMap attributes;
+ testling.handleCharacterData("foo");
+ testling.handleStartElement("message", "", attributes);
+ testling.handleEndElement("message", "");
+ testling.handleCharacterData("bar");
+
+ CPPUNIT_ASSERT_EQUAL(String("<message/>"), testling.getResult());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SerializingParserTest);
diff --git a/Swiften/Parser/UnitTest/StanzaParserTest.cpp b/Swiften/Parser/UnitTest/StanzaParserTest.cpp
new file mode 100644
index 0000000..3cb1879
--- /dev/null
+++ b/Swiften/Parser/UnitTest/StanzaParserTest.cpp
@@ -0,0 +1,209 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/StanzaParser.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Elements/Stanza.h"
+#include "Swiften/Elements/Payload.h"
+
+using namespace Swift;
+
+class StanzaParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(StanzaParserTest);
+ CPPUNIT_TEST(testHandleEndElement_OnePayload);
+ CPPUNIT_TEST(testHandleEndElement_MultiplePayloads);
+ CPPUNIT_TEST(testHandleEndElement_StrayCharacterData);
+ CPPUNIT_TEST(testHandleEndElement_UnknownPayload);
+ CPPUNIT_TEST(testHandleParse_BasicAttributes);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StanzaParserTest() {}
+
+ void setUp() {
+ factoryCollection_ = new PayloadParserFactoryCollection();
+ factoryCollection_->addFactory(&factory1_);
+ factoryCollection_->addFactory(&factory2_);
+ }
+
+ void tearDown() {
+ delete factoryCollection_;
+ }
+
+ void testHandleEndElement_OnePayload() {
+ MyStanzaParser testling(factoryCollection_);
+
+ AttributeMap attributes;
+ attributes["foo"] = "fum";
+ attributes["bar"] = "baz";
+ testling.handleStartElement("mystanza", "", attributes);
+ testling.handleStartElement("mypayload1", "", attributes);
+ testling.handleStartElement("child", "", attributes);
+ testling.handleEndElement("child", "");
+ testling.handleEndElement("mypayload1", "");
+ testling.handleEndElement("mystanza", "");
+
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>());
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()->hasChild);
+ }
+
+ void testHandleEndElement_MultiplePayloads() {
+ MyStanzaParser testling(factoryCollection_);
+
+ AttributeMap attributes;
+ testling.handleStartElement("mystanza", "", attributes);
+ testling.handleStartElement("mypayload1", "", attributes);
+ testling.handleEndElement("mypayload1", "");
+ testling.handleStartElement("mypayload2", "", attributes);
+ testling.handleEndElement("mypayload2", "");
+ testling.handleEndElement("mystanza", "");
+
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>());
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>());
+ }
+
+ void testHandleEndElement_StrayCharacterData() {
+ MyStanzaParser testling(factoryCollection_);
+
+ AttributeMap attributes;
+ testling.handleStartElement("mystanza", "", attributes);
+ testling.handleStartElement("mypayload1", "", attributes);
+ testling.handleEndElement("mypayload1", "");
+ testling.handleCharacterData("bla");
+ testling.handleStartElement("mypayload2", "", attributes);
+ testling.handleEndElement("mypayload2", "");
+ testling.handleEndElement("mystanza", "");
+
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>());
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>());
+ }
+
+ void testHandleEndElement_UnknownPayload() {
+ MyStanzaParser testling(factoryCollection_);
+
+ AttributeMap attributes;
+ testling.handleStartElement("mystanza", "", attributes);
+ testling.handleStartElement("mypayload1", "", attributes);
+ testling.handleEndElement("mypayload1", "");
+ testling.handleStartElement("unknown-payload", "", attributes);
+ testling.handleStartElement("unknown-payload-child", "", attributes);
+ testling.handleEndElement("unknown-payload-child", "");
+ testling.handleEndElement("unknown-payload", "");
+ testling.handleStartElement("mypayload2", "", attributes);
+ testling.handleEndElement("mypayload2", "");
+ testling.handleEndElement("mystanza", "");
+
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>());
+ CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>());
+ }
+
+ void testHandleParse_BasicAttributes() {
+ MyStanzaParser testling(factoryCollection_);
+
+ AttributeMap attributes;
+ attributes["to"] = "foo@example.com/blo";
+ attributes["from"] = "bar@example.com/baz";
+ attributes["id"] = "id-123";
+ testling.handleStartElement("mystanza", "", attributes);
+ testling.handleEndElement("mypayload1", "");
+
+ CPPUNIT_ASSERT_EQUAL(JID("foo@example.com/blo"), testling.getStanza()->getTo());
+ CPPUNIT_ASSERT_EQUAL(JID("bar@example.com/baz"), testling.getStanza()->getFrom());
+ CPPUNIT_ASSERT_EQUAL(String("id-123"), testling.getStanza()->getID());
+ }
+
+ private:
+ class MyPayload1 : public Payload
+ {
+ public:
+ MyPayload1() : hasChild(false) {}
+
+ bool hasChild;
+ };
+
+ class MyPayload1Parser : public GenericPayloadParser<MyPayload1>
+ {
+ public:
+ MyPayload1Parser() {}
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap&) {
+ if (element != "mypayload1") {
+ getPayloadInternal()->hasChild = true;
+ }
+ }
+
+ virtual void handleEndElement(const String&, const String&) {}
+ virtual void handleCharacterData(const String&) {}
+ };
+
+ class MyPayload1ParserFactory : public PayloadParserFactory
+ {
+ public:
+ MyPayload1ParserFactory() {}
+
+ PayloadParser* createPayloadParser() { return new MyPayload1Parser(); }
+
+ bool canParse(const String& element, const String&, const AttributeMap&) const {
+ return element == "mypayload1";
+ }
+ };
+
+ class MyPayload2 : public Payload
+ {
+ public:
+ MyPayload2() {}
+ };
+
+ class MyPayload2Parser : public GenericPayloadParser<MyPayload2>
+ {
+ public:
+ MyPayload2Parser() {}
+
+ virtual void handleStartElement(const String&, const String&, const AttributeMap&) {}
+ virtual void handleEndElement(const String&, const String&) {}
+ virtual void handleCharacterData(const String&) {}
+ };
+
+
+ class MyPayload2ParserFactory : public PayloadParserFactory
+ {
+ public:
+ MyPayload2ParserFactory() {}
+
+ PayloadParser* createPayloadParser() { return new MyPayload2Parser(); }
+ bool canParse(const String& element, const String&, const AttributeMap&) const {
+ return element == "mypayload2";
+ }
+ };
+
+ class MyStanza : public Stanza
+ {
+ public:
+ MyStanza() {}
+ };
+
+ class MyStanzaParser : public StanzaParser
+ {
+ public:
+ MyStanzaParser(PayloadParserFactoryCollection* collection) : StanzaParser(collection)
+ {
+ stanza_ = boost::shared_ptr<MyStanza>(new MyStanza());
+ }
+
+ virtual boost::shared_ptr<Element> getElement() const {
+ return stanza_;
+ }
+
+ private:
+ boost::shared_ptr<MyStanza> stanza_;
+ };
+
+ MyPayload1ParserFactory factory1_;
+ MyPayload2ParserFactory factory2_;
+ PayloadParserFactoryCollection* factoryCollection_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StanzaParserTest);
diff --git a/Swiften/Parser/UnitTest/StanzaParserTester.h b/Swiften/Parser/UnitTest/StanzaParserTester.h
new file mode 100644
index 0000000..cbd484f
--- /dev/null
+++ b/Swiften/Parser/UnitTest/StanzaParserTester.h
@@ -0,0 +1,11 @@
+#ifndef SWIFTEN_StanzaParserTester_H
+#define SWIFTEN_StanzaParserTester_H
+
+#include "Swiften/Parser/StanzaParser.h"
+#include "Swiften/Parser/UnitTest/ParserTester.h"
+
+namespace Swift {
+ typedef ParserTester<StanzaParser> StanzaParserTester;
+}
+
+#endif
diff --git a/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp
new file mode 100644
index 0000000..7fd0512
--- /dev/null
+++ b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp
@@ -0,0 +1,63 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/StreamFeaturesParser.h"
+#include "Swiften/Parser/UnitTest/ElementParserTester.h"
+
+using namespace Swift;
+
+class StreamFeaturesParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(StreamFeaturesParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST(testParse_Empty);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StreamFeaturesParserTest() {}
+
+ void testParse() {
+ StreamFeaturesParser testling;
+ ElementParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<stream:features xmlns:stream='http://etherx.jabber.org/streams'>"
+ "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"
+ "<compression xmlns=\"http://jabber.org/features/compress\">"
+ "<method>zlib</method>"
+ "<method>lzw</method>"
+ "</compression>"
+ "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
+ "<mechanism>DIGEST-MD5</mechanism>"
+ "<mechanism>PLAIN</mechanism>"
+ "</mechanisms>"
+ "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
+ "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
+ "</stream:features>"));
+
+ StreamFeatures* element = dynamic_cast<StreamFeatures*>(testling.getElement().get());
+ CPPUNIT_ASSERT(element->hasStartTLS());
+ CPPUNIT_ASSERT(element->hasSession());
+ CPPUNIT_ASSERT(element->hasResourceBind());
+ CPPUNIT_ASSERT(element->hasCompressionMethod("zlib"));
+ CPPUNIT_ASSERT(element->hasCompressionMethod("lzw"));
+ CPPUNIT_ASSERT(element->hasAuthenticationMechanisms());
+ CPPUNIT_ASSERT(element->hasAuthenticationMechanism("DIGEST-MD5"));
+ CPPUNIT_ASSERT(element->hasAuthenticationMechanism("PLAIN"));
+ }
+
+ void testParse_Empty() {
+ StreamFeaturesParser testling;
+ ElementParserTester parser(&testling);
+
+ parser.parse("<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>");
+
+ StreamFeatures* element = dynamic_cast<StreamFeatures*>(testling.getElement().get());
+ CPPUNIT_ASSERT(!element->hasStartTLS());
+ CPPUNIT_ASSERT(!element->hasSession());
+ CPPUNIT_ASSERT(!element->hasResourceBind());
+ CPPUNIT_ASSERT(!element->hasAuthenticationMechanisms());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StreamFeaturesParserTest);
diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp
new file mode 100644
index 0000000..6ef1899
--- /dev/null
+++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp
@@ -0,0 +1,229 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <vector>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/XMLParserClient.h"
+#ifdef HAVE_EXPAT
+#include "Swiften/Parser/ExpatParser.h"
+#endif
+#ifdef HAVE_LIBXML
+#include "Swiften/Parser/LibXMLParser.h"
+#endif
+
+using namespace Swift;
+
+template <typename ParserType>
+class XMLParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(XMLParserTest);
+ CPPUNIT_TEST(testParse_NestedElements);
+ CPPUNIT_TEST(testParse_ElementInNamespacedElement);
+ CPPUNIT_TEST(testParse_CharacterData);
+ CPPUNIT_TEST(testParse_NamespacePrefix);
+ CPPUNIT_TEST(testParse_UnhandledXML);
+ CPPUNIT_TEST(testParse_InvalidXML);
+ CPPUNIT_TEST(testParse_InErrorState);
+ CPPUNIT_TEST(testParse_Incremental);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testParse_NestedElements() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse(
+ "<iq type=\"get\">"
+ "<query xmlns='jabber:iq:version'/>"
+ "</iq>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[0].data);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.size());
+ CPPUNIT_ASSERT_EQUAL(String("get"), client_.events[0].attributes["type"]);
+ CPPUNIT_ASSERT_EQUAL(String(), client_.events[0].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[1].data);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.size());
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
+ CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[2].data);
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[2].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[3].data);
+ CPPUNIT_ASSERT_EQUAL(String(), client_.events[3].ns);
+ }
+
+ void testParse_ElementInNamespacedElement() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse(
+ "<query xmlns='jabber:iq:version'>"
+ "<name>Swift</name>"
+ "</query>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[0].data);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.size());
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[0].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("name"), client_.events[1].data);
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type);
+ CPPUNIT_ASSERT_EQUAL(String("Swift"), client_.events[2].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
+ CPPUNIT_ASSERT_EQUAL(String("name"), client_.events[3].data);
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[3].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type);
+ CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[4].data);
+ CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[4].ns);
+ }
+
+ void testParse_CharacterData() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse("<html>bla<i>bli</i>blo</html>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("html"), client_.events[0].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[1].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[2].type);
+ CPPUNIT_ASSERT_EQUAL(String("i"), client_.events[2].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[3].type);
+ CPPUNIT_ASSERT_EQUAL(String("bli"), client_.events[3].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type);
+ CPPUNIT_ASSERT_EQUAL(String("i"), client_.events[4].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[5].type);
+ CPPUNIT_ASSERT_EQUAL(String("blo"), client_.events[5].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[6].type);
+ CPPUNIT_ASSERT_EQUAL(String("html"), client_.events[6].data);
+ }
+
+ void testParse_NamespacePrefix() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse("<p:x xmlns:p='bla'><p:y/></p:x>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("x"), client_.events[0].data);
+ CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[0].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("y"), client_.events[1].data);
+ CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[1].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
+ CPPUNIT_ASSERT_EQUAL(String("y"), client_.events[2].data);
+ CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[2].ns);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
+ CPPUNIT_ASSERT_EQUAL(String("x"), client_.events[3].data);
+ CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[3].ns);
+ }
+
+ void testParse_UnhandledXML() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse("<iq><!-- Testing --></iq>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[0].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[1].data);
+ }
+
+ void testParse_InvalidXML() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>"));
+ }
+
+ void testParse_InErrorState() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>"));
+ CPPUNIT_ASSERT(!testling.parse("<iq/>"));
+ }
+
+ void testParse_Incremental() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse("<iq"));
+ CPPUNIT_ASSERT(testling.parse("></iq>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size());
+
+ CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[0].data);
+
+ CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[1].data);
+ }
+
+ private:
+ class Client : public XMLParserClient {
+ public:
+ enum Type { StartElement, EndElement, CharacterData };
+ struct Event {
+ Event(
+ Type type,
+ const String& data,
+ const String& ns,
+ const AttributeMap& attributes)
+ : type(type), data(data), ns(ns), attributes(attributes) {}
+ Event(Type type, const String& data, const String& ns = String())
+ : type(type), data(data), ns(ns) {}
+
+ Type type;
+ String data;
+ String ns;
+ AttributeMap attributes;
+ };
+
+ Client() {}
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ events.push_back(Event(StartElement, element, ns, attributes));
+ }
+
+ virtual void handleEndElement(const String& element, const String& ns) {
+ events.push_back(Event(EndElement, element, ns));
+ }
+
+ virtual void handleCharacterData(const String& data) {
+ events.push_back(Event(CharacterData, data));
+ }
+
+ std::vector<Event> events;
+ } client_;
+};
+
+#ifdef HAVE_EXPAT
+CPPUNIT_TEST_SUITE_REGISTRATION(XMLParserTest<ExpatParser>);
+#endif
+#ifdef HAVE_LIBXML
+CPPUNIT_TEST_SUITE_REGISTRATION(XMLParserTest<LibXMLParser>);
+#endif
diff --git a/Swiften/Parser/UnitTest/XMPPParserTest.cpp b/Swiften/Parser/UnitTest/XMPPParserTest.cpp
new file mode 100644
index 0000000..ecdd565
--- /dev/null
+++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp
@@ -0,0 +1,186 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <vector>
+
+#include "Swiften/Elements/ProtocolHeader.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/XMPPParser.h"
+#include "Swiften/Parser/ElementParser.h"
+#include "Swiften/Parser/XMPPParserClient.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Elements/IQ.h"
+#include "Swiften/Elements/Message.h"
+#include "Swiften/Elements/StreamFeatures.h"
+#include "Swiften/Elements/UnknownElement.h"
+
+using namespace Swift;
+
+class XMPPParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(XMPPParserTest);
+ CPPUNIT_TEST(testParse_SimpleSession);
+ CPPUNIT_TEST(testParse_SimpleClientFromServerSession);
+ CPPUNIT_TEST(testParse_Presence);
+ CPPUNIT_TEST(testParse_IQ);
+ CPPUNIT_TEST(testParse_Message);
+ CPPUNIT_TEST(testParse_StreamFeatures);
+ CPPUNIT_TEST(testParse_UnknownElement);
+ CPPUNIT_TEST(testParse_StrayCharacterData);
+ CPPUNIT_TEST(testParse_InvalidStreamStart);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ XMPPParserTest() {}
+
+ void testParse_SimpleSession() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>"));
+ CPPUNIT_ASSERT(testling.parse("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' >"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+ CPPUNIT_ASSERT(testling.parse("<iq/>"));
+ CPPUNIT_ASSERT(testling.parse("</stream:stream>"));
+
+ CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("example.com"), client_.events[0].to);
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type);
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type);
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type);
+ CPPUNIT_ASSERT_EQUAL(Client::StreamEnd, client_.events[4].type);
+ }
+
+ void testParse_SimpleClientFromServerSession() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>"));
+ CPPUNIT_ASSERT(testling.parse("<stream:stream from='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='aeab'>"));
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type);
+ CPPUNIT_ASSERT_EQUAL(String("example.com"), client_.events[0].from);
+ CPPUNIT_ASSERT_EQUAL(String("aeab"), client_.events[0].id);
+ }
+
+
+ void testParse_Presence() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type);
+ CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[1].element.get()));
+ }
+
+ void testParse_IQ() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<iq/>"));
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type);
+ CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[1].element.get()));
+ }
+
+ void testParse_Message() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<message/>"));
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type);
+ CPPUNIT_ASSERT(dynamic_cast<Message*>(client_.events[1].element.get()));
+ }
+
+ void testParse_StreamFeatures() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<stream:features/>"));
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type);
+ CPPUNIT_ASSERT(dynamic_cast<StreamFeatures*>(client_.events[1].element.get()));
+ }
+
+ void testParse_UnknownElement() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+ CPPUNIT_ASSERT(testling.parse("<foo/>"));
+ CPPUNIT_ASSERT(testling.parse("<bar/>"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+
+ CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type);
+ CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[2].element.get()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type);
+ CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[3].element.get()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[4].type);
+ CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[4].element.get()));
+ }
+
+ void testParse_StrayCharacterData() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"));
+ CPPUNIT_ASSERT(testling.parse("<presence/>"));
+ CPPUNIT_ASSERT(testling.parse("bla"));
+ CPPUNIT_ASSERT(testling.parse("<iq/>"));
+
+ CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(client_.events.size()));
+ CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type);
+ CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[2].element.get()));
+ }
+
+ void testParse_InvalidStreamStart() {
+ XMPPParser testling(&client_, &factories_);
+
+ CPPUNIT_ASSERT(!testling.parse("<tream>"));
+ }
+
+ private:
+ class Client : public XMPPParserClient {
+ public:
+ enum Type { StreamStart, ElementEvent, StreamEnd };
+ struct Event {
+ Event(Type type, boost::shared_ptr<Element> element)
+ : type(type), element(element) {}
+ Event(Type type, const String& from, const String& to, const String& id) : type(type), from(from), to(to), id(id) {}
+
+ Event(Type type) : type(type) {}
+
+ Type type;
+ String from;
+ String to;
+ String id;
+ boost::shared_ptr<Element> element;
+ };
+
+ Client() {}
+
+ void handleStreamStart(const ProtocolHeader& header) {
+ events.push_back(Event(StreamStart, header.getFrom(), header.getTo(), header.getID()));
+ }
+
+ void handleElement(boost::shared_ptr<Element> element) {
+ events.push_back(Event(ElementEvent, element));
+ }
+
+ void handleStreamEnd() {
+ events.push_back(Event(StreamEnd));
+ }
+
+ std::vector<Event> events;
+ } client_;
+ PayloadParserFactoryCollection factories_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(XMPPParserTest);
diff --git a/Swiften/Parser/UnknownElementParser.h b/Swiften/Parser/UnknownElementParser.h
new file mode 100644
index 0000000..c016664
--- /dev/null
+++ b/Swiften/Parser/UnknownElementParser.h
@@ -0,0 +1,14 @@
+#ifndef SWIFTEN_UnknownElementParser_H
+#define SWIFTEN_UnknownElementParser_H
+
+#include "Swiften/Parser/GenericElementParser.h"
+#include "Swiften/Elements/UnknownElement.h"
+
+namespace Swift {
+ class UnknownElementParser : public GenericElementParser<UnknownElement> {
+ public:
+ UnknownElementParser() : GenericElementParser<UnknownElement>() {}
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/UnknownPayloadParser.h b/Swiften/Parser/UnknownPayloadParser.h
new file mode 100644
index 0000000..ad56885
--- /dev/null
+++ b/Swiften/Parser/UnknownPayloadParser.h
@@ -0,0 +1,25 @@
+#ifndef SWIFTEN_UNKNOWNPAYLOADPARSER_H
+#define SWIFTEN_UNKNOWNPAYLOADPARSER_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Parser/PayloadParser.h"
+
+namespace Swift {
+ class String;
+
+ class UnknownPayloadParser : public PayloadParser {
+ public:
+ UnknownPayloadParser() {}
+
+ virtual void handleStartElement(const String&, const String&, const AttributeMap&) {}
+ virtual void handleEndElement(const String&, const String&) {}
+ virtual void handleCharacterData(const String&) {}
+
+ virtual boost::shared_ptr<Payload> getPayload() const {
+ return boost::shared_ptr<Payload>();
+ }
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/XMLParser.cpp b/Swiften/Parser/XMLParser.cpp
new file mode 100644
index 0000000..a827e99
--- /dev/null
+++ b/Swiften/Parser/XMLParser.cpp
@@ -0,0 +1,11 @@
+#include "Swiften/Parser/XMLParser.h"
+
+namespace Swift {
+
+XMLParser::XMLParser(XMLParserClient* client) : client_(client) {
+}
+
+XMLParser::~XMLParser() {
+}
+
+}
diff --git a/Swiften/Parser/XMLParser.h b/Swiften/Parser/XMLParser.h
new file mode 100644
index 0000000..7ed90db
--- /dev/null
+++ b/Swiften/Parser/XMLParser.h
@@ -0,0 +1,25 @@
+#ifndef SWIFTEN_XMLParser_H
+#define SWIFTEN_XMLParser_H
+
+namespace Swift {
+ class String;
+ class XMLParserClient;
+
+ class XMLParser {
+ public:
+ XMLParser(XMLParserClient* client);
+ virtual ~XMLParser();
+
+ virtual bool parse(const String& data) = 0;
+
+ protected:
+ XMLParserClient* getClient() const {
+ return client_;
+ }
+
+ private:
+ XMLParserClient* client_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/XMLParserClient.cpp b/Swiften/Parser/XMLParserClient.cpp
new file mode 100644
index 0000000..53a103f
--- /dev/null
+++ b/Swiften/Parser/XMLParserClient.cpp
@@ -0,0 +1,9 @@
+#include "Swiften/Parser/XMLParserClient.h"
+
+namespace Swift {
+
+XMLParserClient::~XMLParserClient() {
+}
+
+}
+
diff --git a/Swiften/Parser/XMLParserClient.h b/Swiften/Parser/XMLParserClient.h
new file mode 100644
index 0000000..7179ac6
--- /dev/null
+++ b/Swiften/Parser/XMLParserClient.h
@@ -0,0 +1,19 @@
+#ifndef XMLPARSERCLIENT_H
+#define XMLPARSERCLIENT_H
+
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class String;
+
+ class XMLParserClient {
+ public:
+ virtual ~XMLParserClient();
+
+ virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) = 0;
+ virtual void handleEndElement(const String& element, const String& ns) = 0;
+ virtual void handleCharacterData(const String& data) = 0;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/XMLParserFactory.cpp b/Swiften/Parser/XMLParserFactory.cpp
new file mode 100644
index 0000000..e21bb5c
--- /dev/null
+++ b/Swiften/Parser/XMLParserFactory.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/Parser/XMLParserFactory.h"
+
+namespace Swift {
+
+XMLParserFactory::~XMLParserFactory() {
+}
+
+}
diff --git a/Swiften/Parser/XMLParserFactory.h b/Swiften/Parser/XMLParserFactory.h
new file mode 100644
index 0000000..8d67b17
--- /dev/null
+++ b/Swiften/Parser/XMLParserFactory.h
@@ -0,0 +1,16 @@
+#ifndef SWIFTEN_XMLParserFactory_H
+#define SWIFTEN_XMLParserFactory_H
+
+namespace Swift {
+ class XMLParser;
+ class XMLParserClient;
+
+ class XMLParserFactory {
+ public:
+ virtual ~XMLParserFactory();
+
+ virtual XMLParser* createXMLParser(XMLParserClient*) = 0;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp
new file mode 100644
index 0000000..83de263
--- /dev/null
+++ b/Swiften/Parser/XMPPParser.cpp
@@ -0,0 +1,159 @@
+#include "Swiften/Parser/XMPPParser.h"
+
+#include <iostream>
+#include <cassert>
+
+#include "Swiften/Elements/ProtocolHeader.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Parser/XMLParser.h"
+#include "Swiften/Parser/PlatformXMLParserFactory.h"
+#include "Swiften/Parser/XMPPParserClient.h"
+#include "Swiften/Parser/XMPPParser.h"
+#include "Swiften/Parser/ElementParser.h"
+#include "Swiften/Parser/PresenceParser.h"
+#include "Swiften/Parser/IQParser.h"
+#include "Swiften/Parser/MessageParser.h"
+#include "Swiften/Parser/StreamFeaturesParser.h"
+#include "Swiften/Parser/AuthRequestParser.h"
+#include "Swiften/Parser/AuthSuccessParser.h"
+#include "Swiften/Parser/AuthFailureParser.h"
+#include "Swiften/Parser/AuthChallengeParser.h"
+#include "Swiften/Parser/AuthResponseParser.h"
+#include "Swiften/Parser/StartTLSParser.h"
+#include "Swiften/Parser/StartTLSFailureParser.h"
+#include "Swiften/Parser/CompressParser.h"
+#include "Swiften/Parser/CompressFailureParser.h"
+#include "Swiften/Parser/CompressedParser.h"
+#include "Swiften/Parser/UnknownElementParser.h"
+#include "Swiften/Parser/TLSProceedParser.h"
+
+// TODO: Whenever an error occurs in the handlers, stop the parser by returing
+// a bool value, and stopping the XML parser
+
+namespace Swift {
+
+XMPPParser::XMPPParser(
+ XMPPParserClient* client,
+ PayloadParserFactoryCollection* payloadParserFactories) :
+ xmlParser_(0),
+ client_(client),
+ payloadParserFactories_(payloadParserFactories),
+ currentDepth_(0),
+ currentElementParser_(0),
+ parseErrorOccurred_(false) {
+ xmlParser_ = PlatformXMLParserFactory().createXMLParser(this);
+}
+
+XMPPParser::~XMPPParser() {
+ delete currentElementParser_;
+ delete xmlParser_;
+}
+
+bool XMPPParser::parse(const String& data) {
+ bool xmlParseResult = xmlParser_->parse(data);
+ return xmlParseResult && !parseErrorOccurred_;
+}
+
+void XMPPParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+ if (!inStream()) {
+ if (element == "stream" && ns == "http://etherx.jabber.org/streams") {
+ ProtocolHeader header;
+ header.setFrom(attributes.getAttribute("from"));
+ header.setTo(attributes.getAttribute("to"));
+ header.setID(attributes.getAttribute("id"));
+ header.setVersion(attributes.getAttribute("version"));
+ client_->handleStreamStart(header);
+ }
+ else {
+ parseErrorOccurred_ = true;
+ }
+ }
+ else {
+ if (!inElement()) {
+ assert(!currentElementParser_);
+ delete currentElementParser_;
+ currentElementParser_ = createElementParser(element, ns);
+ }
+ currentElementParser_->handleStartElement(element, ns, attributes);
+ }
+ ++currentDepth_;
+}
+
+void XMPPParser::handleEndElement(const String& element, const String& ns) {
+ assert(inStream());
+ if (inElement()) {
+ assert(currentElementParser_);
+ currentElementParser_->handleEndElement(element, ns);
+ --currentDepth_;
+ if (!inElement()) {
+ client_->handleElement(currentElementParser_->getElement());
+ delete currentElementParser_;
+ currentElementParser_ = 0;
+ }
+ }
+ else {
+ assert(element == "stream");
+ --currentDepth_;
+ client_->handleStreamEnd();
+ }
+}
+
+void XMPPParser::handleCharacterData(const String& data) {
+ if (currentElementParser_) {
+ currentElementParser_->handleCharacterData(data);
+ }
+ //else {
+ // std::cerr << "XMPPParser: Ignoring stray character data: " << data << std::endl;
+ //}
+}
+
+ElementParser* XMPPParser::createElementParser(const String& element, const String& ns) {
+ if (element == "presence") {
+ return new PresenceParser(payloadParserFactories_);
+ }
+ else if (element == "iq") {
+ return new IQParser(payloadParserFactories_);
+ }
+ else if (element == "message") {
+ return new MessageParser(payloadParserFactories_);
+ }
+ else if (element == "features" && ns == "http://etherx.jabber.org/streams") {
+ return new StreamFeaturesParser();
+ }
+ else if (element == "auth") {
+ return new AuthRequestParser();
+ }
+ else if (element == "success") {
+ return new AuthSuccessParser();
+ }
+ else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") {
+ return new AuthFailureParser();
+ }
+ else if (element == "challenge" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") {
+ return new AuthChallengeParser();
+ }
+ else if (element == "response" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") {
+ return new AuthResponseParser();
+ }
+ else if (element == "starttls") {
+ return new StartTLSParser();
+ }
+ else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-tls") {
+ return new StartTLSFailureParser();
+ }
+ else if (element == "compress") {
+ return new CompressParser();
+ }
+ else if (element == "compressed") {
+ return new CompressedParser();
+ }
+ else if (element == "failure" && ns == "http://jabber.org/protocol/compress") {
+ return new CompressFailureParser();
+ }
+ else if (element == "proceed") {
+ return new TLSProceedParser();
+ }
+ return new UnknownElementParser();
+}
+
+}
diff --git a/Swiften/Parser/XMPPParser.h b/Swiften/Parser/XMPPParser.h
new file mode 100644
index 0000000..9e1109d
--- /dev/null
+++ b/Swiften/Parser/XMPPParser.h
@@ -0,0 +1,54 @@
+#ifndef SWIFTEN_XMPPPARSER_H
+#define SWIFTEN_XMPPPARSER_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include "Swiften/Parser/XMLParserClient.h"
+#include "Swiften/Parser/AttributeMap.h"
+
+namespace Swift {
+ class XMLParser;
+ class XMPPParserClient;
+ class String;
+ class ElementParser;
+ class PayloadParserFactoryCollection;
+
+ class XMPPParser : public XMLParserClient, boost::noncopyable {
+ public:
+ XMPPParser(
+ XMPPParserClient* parserClient,
+ PayloadParserFactoryCollection* payloadParserFactories);
+ ~XMPPParser();
+
+ bool parse(const String&);
+
+ private:
+ virtual void handleStartElement(
+ const String& element,
+ const String& ns,
+ const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String& ns);
+ virtual void handleCharacterData(const String& data);
+
+ bool inStream() const {
+ return currentDepth_ > 0;
+ }
+
+ bool inElement() const {
+ return currentDepth_ > 1;
+ }
+
+ ElementParser* createElementParser(const String& element, const String& xmlns);
+
+ private:
+ XMLParser* xmlParser_;
+ XMPPParserClient* client_;
+ PayloadParserFactoryCollection* payloadParserFactories_;
+ int currentDepth_;
+ ElementParser* currentElementParser_;
+ bool parseErrorOccurred_;
+ };
+}
+
+#endif
diff --git a/Swiften/Parser/XMPPParserClient.cpp b/Swiften/Parser/XMPPParserClient.cpp
new file mode 100644
index 0000000..66ea917
--- /dev/null
+++ b/Swiften/Parser/XMPPParserClient.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/Parser/XMPPParserClient.h"
+
+namespace Swift {
+
+XMPPParserClient::~XMPPParserClient() {
+}
+
+}
diff --git a/Swiften/Parser/XMPPParserClient.h b/Swiften/Parser/XMPPParserClient.h
new file mode 100644
index 0000000..b8f8e46
--- /dev/null
+++ b/Swiften/Parser/XMPPParserClient.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Elements/Element.h"
+
+namespace Swift {
+ class String;
+ class ProtocolHeader;
+
+ class XMPPParserClient {
+ public:
+ virtual ~XMPPParserClient();
+
+ virtual void handleStreamStart(const ProtocolHeader&) = 0;
+ virtual void handleElement(boost::shared_ptr<Element>) = 0;
+ virtual void handleStreamEnd() = 0;
+ };
+}