From 0630c01cf274a9de6b67856b8c00b1503b39353e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be> Date: Sun, 5 Sep 2010 13:01:20 +0200 Subject: Don't lose unknown roster content. Resolves: #555 diff --git a/Swiften/Elements/RosterItemPayload.h b/Swiften/Elements/RosterItemPayload.h index 9120e12..84b2887 100644 --- a/Swiften/Elements/RosterItemPayload.h +++ b/Swiften/Elements/RosterItemPayload.h @@ -37,12 +37,18 @@ namespace Swift { void setSubscriptionRequested() { ask_ = true; } bool getSubscriptionRequested() const { return ask_; } + const String& getUnknownContent() const { return unknownContent_; } + void addUnknownContent(const String& c) { + unknownContent_ += c; + } + private: JID jid_; String name_; Subscription subscription_; std::vector<String> groups_; bool ask_; + String unknownContent_; }; } diff --git a/Swiften/Parser/PayloadParsers/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp index b35c035..c3a35b6 100644 --- a/Swiften/Parser/PayloadParsers/RosterParser.cpp +++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp @@ -5,13 +5,14 @@ */ #include "Swiften/Parser/PayloadParsers/RosterParser.h" +#include "Swiften/Parser/SerializingParser.h" namespace Swift { -RosterParser::RosterParser() : level_(TopLevel) { +RosterParser::RosterParser() : level_(TopLevel), unknownContentParser_(0) { } -void RosterParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) { +void RosterParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) { if (level_ == PayloadLevel) { if (element == "item") { inItem_ = true; @@ -46,11 +47,19 @@ void RosterParser::handleStartElement(const String& element, const String&, cons if (element == "group") { currentText_ = ""; } + else { + assert(!unknownContentParser_); + unknownContentParser_ = new SerializingParser(); + unknownContentParser_->handleStartElement(element, ns, attributes); + } + } + else if (unknownContentParser_) { + unknownContentParser_->handleStartElement(element, ns, attributes); } ++level_; } -void RosterParser::handleEndElement(const String& element, const String&) { +void RosterParser::handleEndElement(const String& element, const String& ns) { --level_; if (level_ == PayloadLevel) { if (inItem_) { @@ -59,14 +68,27 @@ void RosterParser::handleEndElement(const String& element, const String&) { } } else if (level_ == ItemLevel) { - if (element == "group") { + if (unknownContentParser_) { + unknownContentParser_->handleEndElement(element, ns); + currentItem_.addUnknownContent(unknownContentParser_->getResult()); + unknownContentParser_ = NULL; + } + else if (element == "group") { currentItem_.addGroup(currentText_); } } + else if (unknownContentParser_) { + unknownContentParser_->handleEndElement(element, ns); + } } void RosterParser::handleCharacterData(const String& data) { - currentText_ += data; + if (unknownContentParser_) { + unknownContentParser_->handleCharacterData(data); + } + else { + currentText_ += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/RosterParser.h b/Swiften/Parser/PayloadParsers/RosterParser.h index a039ff4..4a28618 100644 --- a/Swiften/Parser/PayloadParsers/RosterParser.h +++ b/Swiften/Parser/PayloadParsers/RosterParser.h @@ -11,6 +11,8 @@ #include "Swiften/Parser/GenericPayloadParser.h" namespace Swift { + class SerializingParser; + class RosterParser : public GenericPayloadParser<RosterPayload> { public: RosterParser(); @@ -29,6 +31,7 @@ namespace Swift { bool inItem_; RosterItemPayload currentItem_; String currentText_; + SerializingParser* unknownContentParser_; }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp index e085d58..aea9dc4 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp @@ -16,6 +16,7 @@ class RosterParserTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RosterParserTest); CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_ItemWithUnknownContent); CPPUNIT_TEST_SUITE_END(); public: @@ -51,6 +52,30 @@ class RosterParserTest : public CppUnit::TestFixture CPPUNIT_ASSERT(!items[1].getSubscriptionRequested()); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size()); } + + void testParse_ItemWithUnknownContent() { + 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>" + " <foo xmlns=\"http://example.com\"><bar>Baz</bar></foo>" + " <group>Group 2</group>" + " <baz><fum>foo</fum></baz>" + " </item>" + "</query>"); + + RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); + const RosterPayload::RosterItemPayloads& items = payload->getItems(); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), items.size()); + CPPUNIT_ASSERT_EQUAL(String("Group 1"), items[0].getGroups()[0]); + CPPUNIT_ASSERT_EQUAL(String("Group 2"), items[0].getGroups()[1]); + CPPUNIT_ASSERT_EQUAL(String( + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" + ), items[0].getUnknownContent()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterParserTest); diff --git a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp index fc3c03a..b56f404 100644 --- a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp @@ -10,6 +10,7 @@ #include "Swiften/Base/foreach.h" #include "Swiften/Serializer/XML/XMLTextNode.h" +#include "Swiften/Serializer/XML/XMLRawTextNode.h" #include "Swiften/Serializer/XML/XMLElement.h" namespace Swift { @@ -42,6 +43,11 @@ String RosterSerializer::serializePayload(boost::shared_ptr<RosterPayload> roste itemElement->addNode(groupElement); } + if (!item.getUnknownContent().isEmpty()) { + itemElement->addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(item.getUnknownContent()))); + } + + queryElement.addNode(itemElement); } diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp index fdf93a9..bf30db8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp @@ -15,6 +15,7 @@ class RosterSerializerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RosterSerializerTest); CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_ItemWithUnknownContent); CPPUNIT_TEST_SUITE_END(); public: @@ -49,6 +50,33 @@ class RosterSerializerTest : public CppUnit::TestFixture CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); } + + void testSerialize_ItemWithUnknownContent() { + RosterSerializer testling; + boost::shared_ptr<RosterPayload> roster(new RosterPayload()); + + RosterItemPayload item; + item.setJID(JID("baz@blo.com")); + item.setName("Baz"); + item.addGroup("Group 1"); + item.addGroup("Group 2"); + item.addUnknownContent(String( + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>")); + roster->addItem(item); + + String expectedResult = + "<query xmlns=\"jabber:iq:roster\">" + "<item jid=\"baz@blo.com\" name=\"Baz\" subscription=\"none\">" + "<group>Group 1</group>" + "<group>Group 2</group>" + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" + "</item>" + "</query>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterSerializerTest); -- cgit v0.10.2-6-g49f6