diff options
Diffstat (limited to 'Swiften/Parser')
6 files changed, 240 insertions, 0 deletions
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index 41bba11..70dd81e 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -28,6 +28,7 @@ #include "Swiften/Parser/PayloadParsers/FormParserFactory.h" #include "Swiften/Parser/PayloadParsers/CommandParserFactory.h" #include "Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParserFactory.h" +#include "Swiften/Parser/PayloadParsers/SearchPayloadParserFactory.h" #include "Swiften/Parser/PayloadParsers/StreamInitiationParserFactory.h" #include "Swiften/Parser/PayloadParsers/BytestreamsParserFactory.h" #include "Swiften/Parser/PayloadParsers/IBBParserFactory.h" @@ -64,6 +65,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { factories_.push_back(shared_ptr<PayloadParserFactory>(new FormParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new CommandParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new InBandRegistrationPayloadParserFactory())); + factories_.push_back(shared_ptr<PayloadParserFactory>(new SearchPayloadParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new StreamInitiationParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new BytestreamsParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory())); diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp new file mode 100644 index 0000000..f2cf1dd --- /dev/null +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Parser/PayloadParsers/SearchPayloadParser.h" +#include "Swiften/Parser/PayloadParsers/FormParserFactory.h" +#include "Swiften/Parser/PayloadParsers/FormParser.h" + +namespace Swift { + +SearchPayloadParser::SearchPayloadParser() : level(TopLevel), formParser(NULL) { + formParserFactory = new FormParserFactory(); +} + +SearchPayloadParser::~SearchPayloadParser() { + delete formParserFactory; +} + +void SearchPayloadParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) { + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (element == "x" && ns == "jabber:x:data") { + assert(!formParser); + formParser = dynamic_cast<FormParser*>(formParserFactory->createPayloadParser()); + } + else if (element == "item") { + assert(!currentItem); + currentItem.reset(SearchPayload::Item()); + currentItem->jid = JID(attributes.getAttribute("jid")); + } + else { + currentText.clear(); + } + } + else if (level == ItemLevel && currentItem) { + currentText.clear(); + } + + if (formParser) { + formParser->handleStartElement(element, ns, attributes); + } + + ++level; +} + +void SearchPayloadParser::handleEndElement(const String& element, const String& ns) { + --level; + + if (formParser) { + formParser->handleEndElement(element, ns); + } + + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (formParser) { + getPayloadInternal()->setForm(formParser->getPayloadInternal()); + delete formParser; + formParser = NULL; + } + else if (element == "item") { + assert(currentItem); + getPayloadInternal()->addItem(*currentItem); + currentItem.reset(); + } + else if (element == "instructions") { + getPayloadInternal()->setInstructions(currentText); + } + else if (element == "nick") { + getPayloadInternal()->setNick(currentText); + } + else if (element == "first") { + getPayloadInternal()->setFirst(currentText); + } + else if (element == "last") { + getPayloadInternal()->setLast(currentText); + } + else if (element == "email") { + getPayloadInternal()->setEMail(currentText); + } + } + else if (level == ItemLevel && currentItem) { + if (element == "nick") { + currentItem->nick = currentText; + } + else if (element == "first") { + currentItem->first = currentText; + } + else if (element == "last") { + currentItem->last = currentText; + } + else if (element == "email") { + currentItem->email = currentText; + } + } +} + +void SearchPayloadParser::handleCharacterData(const String& data) { + if (formParser) { + formParser->handleCharacterData(data); + } + else { + currentText += data; + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h new file mode 100644 index 0000000..55177b0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> + +#include "Swiften/Elements/SearchPayload.h" +#include "Swiften/Parser/GenericPayloadParser.h" + +namespace Swift { + class FormParserFactory; + class FormParser; + + class SearchPayloadParser : public GenericPayloadParser<SearchPayload> { + public: + SearchPayloadParser(); + ~SearchPayloadParser(); + + 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; + FormParserFactory* formParserFactory; + FormParser* formParser; + String currentText; + boost::optional<SearchPayload::Item> currentItem; + }; +} diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/SearchPayloadParserFactory.h new file mode 100644 index 0000000..0f8a6c7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParserFactory.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swiften/Parser/GenericPayloadParserFactory.h" +#include "Swiften/Parser/PayloadParsers/SearchPayloadParser.h" + +namespace Swift { + class SearchPayloadParserFactory : public GenericPayloadParserFactory<SearchPayloadParser> { + public: + SearchPayloadParserFactory() : GenericPayloadParserFactory<SearchPayloadParser>("query", "jabber:iq:search") {} + }; +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp new file mode 100644 index 0000000..1d94c15 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h" +#include "Swiften/Elements/SearchPayload.h" + +using namespace Swift; + +class SearchPayloadParserTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(SearchPayloadParserTest); + CPPUNIT_TEST(testParse_FormRequestResponse); + CPPUNIT_TEST(testParse_Results); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_FormRequestResponse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:search\">" + "<instructions>Foo</instructions>" + "<first/>" + "<last/>" + "</query>" + )); + + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT_EQUAL(String("Foo"), *payload->getInstructions()); + CPPUNIT_ASSERT(payload->getFirst()); + CPPUNIT_ASSERT(payload->getLast()); + CPPUNIT_ASSERT(!payload->getNick()); + } + + void testParse_Results() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:search\">" + "<item jid=\"juliet@capulet.com\">" + "<first>Juliet</first>" + "<last>Capulet</last>" + "<nick>JuliC</nick>" + "<email>juliet@shakespeare.lit</email>" + "</item>" + "<item jid=\"tybalt@shakespeare.lit\">" + "<first>Tybalt</first>" + "<last>Capulet</last>" + "<nick>ty</nick>" + "<email>tybalt@shakespeare.lit</email>" + "</item>" + "</query>" + )); + + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getItems().size())); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.com"), payload->getItems()[0].jid); + CPPUNIT_ASSERT_EQUAL(String("Juliet"), payload->getItems()[0].first); + CPPUNIT_ASSERT_EQUAL(String("Capulet"), payload->getItems()[0].last); + CPPUNIT_ASSERT_EQUAL(String("JuliC"), payload->getItems()[0].nick); + CPPUNIT_ASSERT_EQUAL(String("juliet@shakespeare.lit"), payload->getItems()[0].email); + CPPUNIT_ASSERT_EQUAL(JID("tybalt@shakespeare.lit"), payload->getItems()[1].jid); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(SearchPayloadParserTest); diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 92d5aa9..29398f0 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -30,6 +30,7 @@ sources = [ "PayloadParsers/IBBParser.cpp", "PayloadParsers/CommandParser.cpp", "PayloadParsers/InBandRegistrationPayloadParser.cpp", + "PayloadParsers/SearchPayloadParser.cpp", "PayloadParsers/FullPayloadParserFactoryCollection.cpp", "PayloadParsers/PriorityParser.cpp", "PayloadParsers/PrivateStorageParser.cpp", |