summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2015-02-20 09:06:33 (GMT)
committerTobias Markmann <tm@ayena.de>2015-02-20 16:51:51 (GMT)
commit88758e2b2a24372386b8d3d5fa5390414cc8ec0f (patch)
tree8bb7183c1cc7d47715a23a9be1b414cc9c09d90f /Swiften/Parser/PayloadParsers
parent9b4314424ee2daff9031a0027f2d8de3a84ed48e (diff)
downloadswift-88758e2b2a24372386b8d3d5fa5390414cc8ec0f.zip
swift-88758e2b2a24372386b8d3d5fa5390414cc8ec0f.tar.bz2
Add elements/parsers/serializers/tests for Message Carbons (XEP-0280)
In addition this patch adds an element, a parser and a serializer for the <thread/> element from XMPP IM. Test-Information: Implemented unit tests pass as expected. Change-Id: I0a14c778c2c0bf65f4b405c9878c741449bfe142
Diffstat (limited to 'Swiften/Parser/PayloadParsers')
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp26
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsDisableParser.h23
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp26
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsEnableParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp26
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h22
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp45
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h35
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp45
-rw-r--r--Swiften/Parser/PayloadParsers/CarbonsSentParser.h35
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp14
-rw-r--r--Swiften/Parser/PayloadParsers/SubjectParser.cpp4
-rw-r--r--Swiften/Parser/PayloadParsers/ThreadParser.cpp39
-rw-r--r--Swiften/Parser/PayloadParsers/ThreadParser.h27
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp127
15 files changed, 514 insertions, 2 deletions
diff --git a/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp
new file mode 100644
index 0000000..7e26f3b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/CarbonsDisableParser.h>
+
+namespace Swift {
+
+ CarbonsDisableParser::CarbonsDisableParser() : GenericPayloadParser<CarbonsDisable>() {
+ }
+
+ CarbonsDisableParser::~CarbonsDisableParser() {
+ }
+
+ void CarbonsDisableParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) {
+ }
+
+ void CarbonsDisableParser::handleEndElement(const std::string&, const std::string&) {
+ }
+
+ void CarbonsDisableParser::handleCharacterData(const std::string&) {
+ }
+
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h
new file mode 100644
index 0000000..56f6787
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsDisable.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+ class SWIFTEN_API CarbonsDisableParser : public GenericPayloadParser<CarbonsDisable> {
+ public:
+ CarbonsDisableParser();
+ virtual ~CarbonsDisableParser();
+
+ virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string&, const std::string&);
+ virtual void handleCharacterData(const std::string&);
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp
new file mode 100644
index 0000000..52bf6d7
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/CarbonsEnableParser.h>
+
+namespace Swift {
+
+ CarbonsEnableParser::CarbonsEnableParser() : GenericPayloadParser<CarbonsEnable>() {
+ }
+
+ CarbonsEnableParser::~CarbonsEnableParser() {
+ }
+
+ void CarbonsEnableParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) {
+ }
+
+ void CarbonsEnableParser::handleEndElement(const std::string&, const std::string&) {
+ }
+
+ void CarbonsEnableParser::handleCharacterData(const std::string&) {
+ }
+
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h
new file mode 100644
index 0000000..d0e5771
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsEnable.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+ class SWIFTEN_API CarbonsEnableParser : public GenericPayloadParser<CarbonsEnable> {
+ public:
+ CarbonsEnableParser();
+ virtual ~CarbonsEnableParser();
+ virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string&, const std::string&);
+ virtual void handleCharacterData(const std::string&);
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp
new file mode 100644
index 0000000..888edf1
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h>
+
+namespace Swift {
+
+ CarbonsPrivateParser::CarbonsPrivateParser() : GenericPayloadParser<CarbonsPrivate>() {
+ }
+
+ CarbonsPrivateParser::~CarbonsPrivateParser() {
+ }
+
+ void CarbonsPrivateParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) {
+ }
+
+ void CarbonsPrivateParser::handleEndElement(const std::string&, const std::string&) {
+ }
+
+ void CarbonsPrivateParser::handleCharacterData(const std::string&) {
+ }
+
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h
new file mode 100644
index 0000000..2797808
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsPrivate.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+ class SWIFTEN_API CarbonsPrivateParser : public GenericPayloadParser<CarbonsPrivate> {
+ public:
+ CarbonsPrivateParser();
+ virtual ~CarbonsPrivateParser();
+ virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string&, const std::string&);
+ virtual void handleCharacterData(const std::string&);
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp
new file mode 100644
index 0000000..267c541
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h>
+
+namespace Swift {
+ CarbonsReceivedParser::CarbonsReceivedParser(PayloadParserFactoryCollection* factories) : GenericPayloadParser<CarbonsReceived>(), factories_(factories), level_(TopLevel) {
+ }
+
+ CarbonsReceivedParser::~CarbonsReceivedParser() {
+ }
+
+ void CarbonsReceivedParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
+ if (level_ == PayloadLevel) {
+ if (element == "forwarded") {
+ forwardedParser_ = boost::dynamic_pointer_cast<ForwardedParser>(boost::make_shared<ForwardedParser>(factories_));
+ }
+ }
+ if (forwardedParser_) {
+ forwardedParser_->handleStartElement(element, ns, attributes);
+ }
+ ++level_;
+ }
+
+ void CarbonsReceivedParser::handleEndElement(const std::string& element, const std::string& ns) {
+ --level_;
+ if (forwardedParser_ && level_ >= PayloadLevel) {
+ forwardedParser_->handleEndElement(element, ns);
+ }
+ if (forwardedParser_ && level_ == PayloadLevel) {
+ /* done parsing nested stanza */
+ getPayloadInternal()->setForwarded(forwardedParser_->getPayloadInternal());
+ forwardedParser_.reset();
+ }
+ }
+
+ void CarbonsReceivedParser::handleCharacterData(const std::string& data) {
+ if (forwardedParser_) {
+ forwardedParser_->handleCharacterData(data);
+ }
+ }
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h
new file mode 100644
index 0000000..6aa6326
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsReceived.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Parser/PayloadParsers/ForwardedParser.h>
+
+namespace Swift {
+ class SWIFTEN_API CarbonsReceivedParser : public GenericPayloadParser<CarbonsReceived> {
+ public:
+ CarbonsReceivedParser(PayloadParserFactoryCollection* factories);
+ virtual ~CarbonsReceivedParser();
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string&);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+
+
+ private:
+ PayloadParserFactoryCollection* factories_;
+ boost::shared_ptr<ForwardedParser> forwardedParser_;
+ int level_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp
new file mode 100644
index 0000000..b430249
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/CarbonsSentParser.h>
+
+namespace Swift {
+ CarbonsSentParser::CarbonsSentParser(PayloadParserFactoryCollection* factories) : GenericPayloadParser<CarbonsSent>(), factories_(factories), level_(TopLevel) {
+ }
+
+ CarbonsSentParser::~CarbonsSentParser() {
+ }
+
+ void CarbonsSentParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
+ if (level_ == PayloadLevel) {
+ if (element == "forwarded") {
+ forwardedParser_ = boost::dynamic_pointer_cast<ForwardedParser>(boost::make_shared<ForwardedParser>(factories_));
+ }
+ }
+ if (forwardedParser_) {
+ forwardedParser_->handleStartElement(element, ns, attributes);
+ }
+ ++level_;
+ }
+
+ void CarbonsSentParser::handleEndElement(const std::string& element, const std::string& ns) {
+ --level_;
+ if (forwardedParser_ && level_ >= PayloadLevel) {
+ forwardedParser_->handleEndElement(element, ns);
+ }
+ if (forwardedParser_ && level_ == PayloadLevel) {
+ /* done parsing nested stanza */
+ getPayloadInternal()->setForwarded(forwardedParser_->getPayloadInternal());
+ forwardedParser_.reset();
+ }
+ }
+
+ void CarbonsSentParser::handleCharacterData(const std::string& data) {
+ if (forwardedParser_) {
+ forwardedParser_->handleCharacterData(data);
+ }
+ }
+}
diff --git a/Swiften/Parser/PayloadParsers/CarbonsSentParser.h b/Swiften/Parser/PayloadParsers/CarbonsSentParser.h
new file mode 100644
index 0000000..91c3292
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CarbonsSentParser.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsSent.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Parser/PayloadParsers/ForwardedParser.h>
+
+namespace Swift {
+ class SWIFTEN_API CarbonsSentParser : public GenericPayloadParser<CarbonsSent> {
+ public:
+ CarbonsSentParser(PayloadParserFactoryCollection* factories);
+ virtual ~CarbonsSentParser();
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string&);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1
+ };
+
+
+ private:
+ PayloadParserFactoryCollection* factories_;
+ boost::shared_ptr<ForwardedParser> forwardedParser_;
+ int level_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index da2f596..d791819 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -20,6 +20,11 @@
#include <Swiften/Parser/PayloadParsers/BodyParser.h>
#include <Swiften/Parser/PayloadParsers/BytestreamsParser.h>
#include <Swiften/Parser/PayloadParsers/CapsInfoParser.h>
+#include <Swiften/Parser/PayloadParsers/CarbonsDisableParser.h>
+#include <Swiften/Parser/PayloadParsers/CarbonsEnableParser.h>
+#include <Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h>
+#include <Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h>
+#include <Swiften/Parser/PayloadParsers/CarbonsSentParser.h>
#include <Swiften/Parser/PayloadParsers/ChatStateParserFactory.h>
#include <Swiften/Parser/PayloadParsers/CommandParser.h>
#include <Swiften/Parser/PayloadParsers/DelayParser.h>
@@ -38,6 +43,7 @@
#include <Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h>
#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h>
#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h>
+#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>
#include <Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h>
#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h>
#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h>
@@ -77,9 +83,9 @@
#include <Swiften/Parser/PayloadParsers/StatusShowParser.h>
#include <Swiften/Parser/PayloadParsers/StorageParser.h>
#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h>
-#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>
#include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h>
#include <Swiften/Parser/PayloadParsers/SubjectParser.h>
+#include <Swiften/Parser/PayloadParsers/ThreadParser.h>
#include <Swiften/Parser/PayloadParsers/UserLocationParser.h>
#include <Swiften/Parser/PayloadParsers/UserTuneParser.h>
#include <Swiften/Parser/PayloadParsers/VCardParser.h>
@@ -99,6 +105,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<LastParser> >("query", "jabber:iq:last"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BodyParser> >("body"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<SubjectParser> >("subject"));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<ThreadParser> >("thread"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<PriorityParser> >("priority"));
factories_.push_back(boost::make_shared<ErrorParserFactory>(this));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<DelayParser> >("delay", "urn:xmpp:delay"));
@@ -159,6 +166,11 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MAMQueryParser> >("query", "urn:xmpp:mam:0"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MAMFinParser> >("fin", "urn:xmpp:mam:0"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<IsodeIQDelegationParser> >("delegate", "http://isode.com/iq_delegation", this));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<CarbonsEnableParser> >("enable", "urn:xmpp:carbons:2"));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<CarbonsDisableParser> >("disable", "urn:xmpp:carbons:2"));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<CarbonsReceivedParser> >("received", "urn:xmpp:carbons:2", this));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<CarbonsSentParser> >("sent", "urn:xmpp:carbons:2", this));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<CarbonsPrivateParser> >("private", "urn:xmpp:carbons:2"));
foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
addFactory(factory.get());
diff --git a/Swiften/Parser/PayloadParsers/SubjectParser.cpp b/Swiften/Parser/PayloadParsers/SubjectParser.cpp
index b756953..7b2d885 100644
--- a/Swiften/Parser/PayloadParsers/SubjectParser.cpp
+++ b/Swiften/Parser/PayloadParsers/SubjectParser.cpp
@@ -23,7 +23,9 @@ void SubjectParser::handleEndElement(const std::string&, const std::string&) {
}
void SubjectParser::handleCharacterData(const std::string& data) {
- text_ += data;
+ if (level_ == 1) {
+ text_ += data;
+ }
}
}
diff --git a/Swiften/Parser/PayloadParsers/ThreadParser.cpp b/Swiften/Parser/PayloadParsers/ThreadParser.cpp
new file mode 100644
index 0000000..0d0aca8
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ThreadParser.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/ThreadParser.h>
+
+#include <boost/optional.hpp>
+
+namespace Swift {
+
+ThreadParser::ThreadParser() : level_(0) {
+}
+
+ThreadParser::~ThreadParser() {
+}
+
+void ThreadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
+ ++level_;
+ if (element == "thread") {
+ getPayloadInternal()->setParent(attributes.getAttributeValue("parent").get_value_or(""));
+ }
+}
+
+void ThreadParser::handleEndElement(const std::string&, const std::string&) {
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setText(text_);
+ }
+}
+
+void ThreadParser::handleCharacterData(const std::string& data) {
+ if (level_ == 1) {
+ text_ += data;
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/ThreadParser.h b/Swiften/Parser/PayloadParsers/ThreadParser.h
new file mode 100644
index 0000000..270ea99
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/ThreadParser.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/Thread.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+ class SWIFTEN_API ThreadParser : public GenericPayloadParser<Thread> {
+ public:
+ ThreadParser();
+ virtual ~ThreadParser();
+
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ int level_;
+ std::string text_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp
new file mode 100644
index 0000000..6fd38bc
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/Thread.h>
+#include <Swiften/Elements/CarbonsEnable.h>
+#include <Swiften/Elements/CarbonsDisable.h>
+#include <Swiften/Elements/CarbonsReceived.h>
+#include <Swiften/Elements/CarbonsSent.h>
+#include <Swiften/Elements/CarbonsPrivate.h>
+#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h>
+
+using namespace Swift;
+
+class CarbonsParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(CarbonsParserTest);
+ CPPUNIT_TEST(testParseExample3);
+ CPPUNIT_TEST(testParseExample6);
+ CPPUNIT_TEST(testParseExample12);
+ CPPUNIT_TEST(testParseExample14);
+ CPPUNIT_TEST(testParseExample15);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ CarbonsParserTest() {}
+
+ /*
+ * Test parsing of example 3 in XEP-0280.
+ */
+ void testParseExample3() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<enable xmlns='urn:xmpp:carbons:2' />"));
+
+ CarbonsEnable::ref enable = parser.getPayload<CarbonsEnable>();
+ CPPUNIT_ASSERT(enable);
+ }
+
+ /*
+ * Test parsing of example 6 in XEP-0280.
+ */
+ void testParseExample6() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<disable xmlns='urn:xmpp:carbons:2' />"));
+
+ CarbonsDisable::ref disable = parser.getPayload<CarbonsDisable>();
+ CPPUNIT_ASSERT(disable);
+ }
+
+ /*
+ * Test parsing of example 12 in XEP-0280.
+ */
+ void testParseExample12() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<received xmlns='urn:xmpp:carbons:2'>"
+ "<forwarded xmlns='urn:xmpp:forward:0'>"
+ "<message xmlns='jabber:client'"
+ " from='juliet@capulet.example/balcony'"
+ " to='romeo@montague.example/garden'"
+ " type='chat'>"
+ "<body>What man art thou that, thus bescreen'd in night, so stumblest on my counsel?</body>"
+ "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>"
+ "</message>"
+ "</forwarded>"
+ "</received>"));
+
+ CarbonsReceived::ref received = parser.getPayload<CarbonsReceived>();
+ CPPUNIT_ASSERT(received);
+
+ boost::shared_ptr<Forwarded> forwarded = received->getForwarded();
+ CPPUNIT_ASSERT(forwarded);
+
+ boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(forwarded->getStanza());
+ CPPUNIT_ASSERT(message);
+ CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.example/balcony"), message->getFrom());
+
+ boost::shared_ptr<Thread> thread = message->getPayload<Thread>();
+ CPPUNIT_ASSERT(thread);
+ CPPUNIT_ASSERT_EQUAL(std::string("0e3141cd80894871a68e6fe6b1ec56fa"), thread->getText());
+ }
+
+ /*
+ * Test parsing of example 14 in XEP-0280.
+ */
+ void testParseExample14() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<sent xmlns='urn:xmpp:carbons:2'>"
+ "<forwarded xmlns='urn:xmpp:forward:0'>"
+ "<message xmlns='jabber:client'"
+ " to='juliet@capulet.example/balcony'"
+ " from='romeo@montague.example/home'"
+ " type='chat'>"
+ "<body>Neither, fair saint, if either thee dislike.</body>"
+ "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>"
+ "</message>"
+ "</forwarded>"
+ "</sent>"));
+
+ CarbonsSent::ref sent = parser.getPayload<CarbonsSent>();
+ CPPUNIT_ASSERT(sent);
+
+ boost::shared_ptr<Forwarded> forwarded = sent->getForwarded();
+ CPPUNIT_ASSERT(forwarded);
+
+ boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(forwarded->getStanza());
+ CPPUNIT_ASSERT(message);
+ CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.example/balcony"), message->getTo());
+ }
+
+ /*
+ * Test parsing of example 15 in XEP-0280.
+ */
+ void testParseExample15() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<private xmlns='urn:xmpp:carbons:2'/>"));
+
+ CPPUNIT_ASSERT(parser.getPayload<CarbonsPrivate>());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CarbonsParserTest);