diff options
Diffstat (limited to 'Swiften/Parser')
28 files changed, 482 insertions, 64 deletions
diff --git a/Swiften/Parser/AttributeMap.cpp b/Swiften/Parser/AttributeMap.cpp index 1aeaf99..d508157 100644 --- a/Swiften/Parser/AttributeMap.cpp +++ b/Swiften/Parser/AttributeMap.cpp @@ -8,27 +8,18 @@ #include <algorithm> #include <boost/optional.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> using namespace Swift; - -namespace { - struct AttributeIs { - AttributeIs(const Attribute& attribute) : attribute(attribute) { - } - - bool operator()(const AttributeMap::Entry& o) const { - return o.getAttribute() == attribute; - } - - Attribute attribute; - }; -} +namespace lambda = boost::lambda; AttributeMap::AttributeMap() { } std::string AttributeMap::getAttribute(const std::string& attribute, const std::string& ns) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ns))); + AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), + lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, ns)); if (i == attributes.end()) { return ""; } @@ -38,7 +29,8 @@ std::string AttributeMap::getAttribute(const std::string& attribute, const std:: } bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultValue) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); + AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), + lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, "")); if (i == attributes.end()) { return defaultValue; } @@ -48,7 +40,8 @@ bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultVa } boost::optional<std::string> AttributeMap::getAttributeValue(const std::string& attribute) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); + AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), + lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, "")); if (i == attributes.end()) { return boost::optional<std::string>(); } diff --git a/Swiften/Parser/BOSHBodyExtractor.cpp b/Swiften/Parser/BOSHBodyExtractor.cpp index eeebe8a..715a448 100644 --- a/Swiften/Parser/BOSHBodyExtractor.cpp +++ b/Swiften/Parser/BOSHBodyExtractor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/Parser/BOSHBodyExtractor.h> #include <boost/shared_ptr.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/XMLParser.h> @@ -33,7 +34,7 @@ class BOSHBodyParserClient : public XMLParserClient { BOSHBodyExtractor* bodyExtractor; }; -inline bool isWhitespace(char c) { +inline bool isWhitespace(unsigned char c) { return c == ' ' || c == '\n' || c == '\t' || c == '\r'; } @@ -117,13 +118,17 @@ BOSHBodyExtractor::BOSHBodyExtractor(XMLParserFactory* parserFactory, const Byte body = BOSHBody(); if (!endElementSeen) { - body->content = std::string(reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), std::distance(i, j.base())); + body->content = std::string( + reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), + boost::numeric_cast<size_t>(std::distance(i, j.base()))); } // Parse the body element BOSHBodyParserClient parserClient(this); boost::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient)); - if (!parser->parse(std::string(reinterpret_cast<const char*>(vecptr(data)), std::distance(data.begin(), i)))) { + if (!parser->parse(std::string( + reinterpret_cast<const char*>(vecptr(data)), + boost::numeric_cast<size_t>(std::distance(data.begin(), i))))) { /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at the correct higher layer */ body = boost::optional<BOSHBody>(); diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index 8222ae0..8b7bf82 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp @@ -9,10 +9,13 @@ #include <iostream> #include <string> #include <expat.h> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/String.h> #include <Swiften/Parser/XMLParserClient.h> +#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" + namespace Swift { static const char NAMESPACE_SEPARATOR = '\x01'; @@ -52,7 +55,8 @@ static void handleEndElement(void* parser, const XML_Char* name) { } static void handleCharacterData(void* parser, const XML_Char* data, int len) { - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(data, len)); + assert(len >= 0); + static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(data, static_cast<size_t>(len))); } static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) { @@ -77,7 +81,7 @@ ExpatParser::~ExpatParser() { } bool ExpatParser::parse(const std::string& data) { - bool success = XML_Parse(p->parser_, data.c_str(), data.size(), false) == XML_STATUS_OK; + bool success = XML_Parse(p->parser_, data.c_str(), boost::numeric_cast<int>(data.size()), false) == XML_STATUS_OK; /*if (!success) { std::cout << "ERROR: " << XML_ErrorString(XML_GetErrorCode(p->parser_)) << " while parsing " << data << std::endl; }*/ diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp index caba716..e4938e1 100644 --- a/Swiften/Parser/LibXMLParser.cpp +++ b/Swiften/Parser/LibXMLParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/Parser/LibXMLParser.h> #include <iostream> +#include <boost/numeric/conversion/cast.hpp> #include <cassert> #include <cstring> #include <libxml/parser.h> @@ -32,7 +33,11 @@ static void handleStartElement(void* parser, const xmlChar* name, const xmlChar* if (attributes[i+2]) { attributeNS = std::string(reinterpret_cast<const char*>(attributes[i+2])); } - attributeValues.addAttribute(std::string(reinterpret_cast<const char*>(attributes[i])), attributeNS, std::string(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3])); + attributeValues.addAttribute( + std::string(reinterpret_cast<const char*>(attributes[i])), + attributeNS, + std::string(reinterpret_cast<const char*>(attributes[i+3]), + boost::numeric_cast<size_t>(attributes[i+4]-attributes[i+3]))); } static_cast<XMLParser*>(parser)->getClient()->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues); } @@ -42,7 +47,7 @@ static void handleEndElement(void *parser, const xmlChar* name, const xmlChar*, } static void handleCharacterData(void* parser, const xmlChar* data, int len) { - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), len)); + static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), boost::numeric_cast<size_t>(len))); } static void handleError(void*, const char* /*m*/, ... ) { @@ -86,7 +91,7 @@ LibXMLParser::~LibXMLParser() { } bool LibXMLParser::parse(const std::string& data) { - if (xmlParseChunk(p->context_, data.c_str(), data.size(), false) == XML_ERR_OK) { + if (xmlParseChunk(p->context_, data.c_str(), boost::numeric_cast<int>(data.size()), false) == XML_ERR_OK) { return true; } xmlError* error = xmlCtxtGetLastError(p->context_); diff --git a/Swiften/Parser/PayloadParsers/BlockParser.h b/Swiften/Parser/PayloadParsers/BlockParser.h index cd727ad..6ee47a2 100644 --- a/Swiften/Parser/PayloadParsers/BlockParser.h +++ b/Swiften/Parser/PayloadParsers/BlockParser.h @@ -7,13 +7,14 @@ #pragma once #include <Swiften/Elements/Nickname.h> +#include <Swiften/JID/JID.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { template<typename BLOCK_ELEMENT> class BlockParser : public GenericPayloadParser<BLOCK_ELEMENT> { public: - BlockParser() : GenericPayloadParser<BLOCK_ELEMENT>() { + BlockParser() : GenericPayloadParser<BLOCK_ELEMENT>(), level(0) { } virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { diff --git a/Swiften/Parser/PayloadParsers/BytestreamsParser.h b/Swiften/Parser/PayloadParsers/BytestreamsParser.h index 4785913..5c151c2 100644 --- a/Swiften/Parser/PayloadParsers/BytestreamsParser.h +++ b/Swiften/Parser/PayloadParsers/BytestreamsParser.h @@ -24,7 +24,7 @@ namespace Swift { private: enum Level { TopLevel = 0, - PayloadLevel = 1, + PayloadLevel = 1 }; int level; }; diff --git a/Swiften/Parser/PayloadParsers/FormParser.h b/Swiften/Parser/PayloadParsers/FormParser.h index a3e2524..ec480a5 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.h +++ b/Swiften/Parser/PayloadParsers/FormParser.h @@ -85,7 +85,7 @@ namespace Swift { name##FormFieldParseHelper() : baseParser##FieldParseHelper() { \ field = name##FormField::create(); \ } \ - }; + } SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Boolean, Bool); SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Fixed, String); diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index a40e8f6..1797e45 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -67,6 +67,7 @@ #include <Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h> #include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h> #include <Swiften/Parser/PayloadParsers/WhiteboardParser.h> +#include <Swiften/Parser/PayloadParsers/IdleParser.h> using namespace boost; @@ -128,6 +129,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { factories_.push_back(boost::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard")); factories_.push_back(boost::make_shared<DeliveryReceiptParserFactory>()); factories_.push_back(boost::make_shared<DeliveryReceiptRequestParserFactory>()); + factories_.push_back(boost::make_shared<GenericPayloadParserFactory<IdleParser> >("idle", "urn:xmpp:idle:1")); foreach(shared_ptr<PayloadParserFactory> factory, factories_) { addFactory(factory.get()); diff --git a/Swiften/Parser/PayloadParsers/IBBParser.h b/Swiften/Parser/PayloadParsers/IBBParser.h index d899475..59011b4 100644 --- a/Swiften/Parser/PayloadParsers/IBBParser.h +++ b/Swiften/Parser/PayloadParsers/IBBParser.h @@ -23,7 +23,7 @@ namespace Swift { private: enum Level { - TopLevel = 0, + TopLevel = 0 }; int level; std::string currentText; diff --git a/Swiften/Parser/PayloadParsers/IdleParser.cpp b/Swiften/Parser/PayloadParsers/IdleParser.cpp new file mode 100644 index 0000000..51aa34b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IdleParser.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/IdleParser.h> + +#include <Swiften/Base/DateTime.h> + +namespace Swift { + +IdleParser::IdleParser() : level_(0) { +} + +void IdleParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const AttributeMap& attributes) { + if (level_ == 0) { + boost::posix_time::ptime since = stringToDateTime(attributes.getAttribute("since")); + getPayloadInternal()->setSince(since); + } + ++level_; +} + +void IdleParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void IdleParser::handleCharacterData(const std::string&) { + +} + +} diff --git a/Swiften/Parser/PayloadParsers/IdleParser.h b/Swiften/Parser/PayloadParsers/IdleParser.h new file mode 100644 index 0000000..38001b2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IdleParser.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/Idle.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class IdleParser : public GenericPayloadParser<Idle> { + public: + IdleParser(); + + 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_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h index ae8d36c..1f85c85 100644 --- a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h @@ -27,7 +27,7 @@ namespace Swift { private: enum Level { TopLevel = 0, - PayloadLevel = 1, + PayloadLevel = 1 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h index 93560c6..7ea22b4 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h @@ -26,7 +26,7 @@ class JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFi enum CurrentParseElement { UnknownElement, RequestElement, - OfferElement, + OfferElement }; PayloadParserFactoryCollection* factories; diff --git a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp index a3dfd12..d140368 100644 --- a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #include <boost/lexical_cast.hpp> #include <boost/optional.hpp> @@ -18,9 +24,12 @@ namespace Swift { void JingleIBBTransportMethodPayloadParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { try { - getPayloadInternal()->setBlockSize(boost::lexical_cast<int>(attributes.getAttributeValue("block-size").get_value_or("0"))); - } catch (boost::bad_lexical_cast &) { - getPayloadInternal()->setBlockSize(0); + boost::optional<std::string> blockSize = attributes.getAttributeValue("block-size"); + if (blockSize) { + getPayloadInternal()->setBlockSize(boost::lexical_cast<unsigned int>(*blockSize)); + } + } + catch (boost::bad_lexical_cast &) { } getPayloadInternal()->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); ++level; diff --git a/Swiften/Parser/PayloadParsers/JingleParser.h b/Swiften/Parser/PayloadParsers/JingleParser.h index 188ead9..c7bd58c 100644 --- a/Swiften/Parser/PayloadParsers/JingleParser.h +++ b/Swiften/Parser/PayloadParsers/JingleParser.h @@ -29,5 +29,5 @@ class JingleParser : public GenericPayloadParser<JinglePayload> { boost::shared_ptr<PayloadParser> currentPayloadParser; }; -}; +} diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h index 006e0d9..d456eb8 100644 --- a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h @@ -28,7 +28,7 @@ namespace Swift { enum Level { TopLevel = 0, PayloadLevel = 1, - ItemLevel = 2, + ItemLevel = 2 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp index 0a13844..cc69348 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp @@ -35,7 +35,7 @@ void StreamInitiationFileInfoParser::handleStartElement(const std::string& eleme } else { parseDescription = false; if (element == "range") { - int offset = 0; + boost::uintmax_t offset = 0; try { offset = boost::lexical_cast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or("0")); } catch (boost::bad_lexical_cast &) { diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp index fd3d019..20bad8c 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -40,7 +40,7 @@ void StreamInitiationParser::handleStartElement(const std::string& element, cons currentFile = StreamInitiationFileInfo(); currentFile.setName(attributes.getAttribute("name")); try { - currentFile.setSize(boost::lexical_cast<int>(attributes.getAttribute("size"))); + currentFile.setSize(boost::lexical_cast<unsigned long long>(attributes.getAttribute("size"))); } catch (boost::bad_lexical_cast&) { } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h index c2ffd07..f7350cd 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h @@ -29,7 +29,7 @@ namespace Swift { TopLevel = 0, PayloadLevel = 1, FileOrFeatureLevel = 2, - FormOrDescriptionLevel = 3, + FormOrDescriptionLevel = 3 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp new file mode 100644 index 0000000..ddd3a88 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/PayloadParsers/BlockParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +#include <Swiften/Elements/BlockPayload.h> +#include <Swiften/Elements/UnblockPayload.h> +#include <Swiften/Elements/BlockListPayload.h> + +using namespace Swift; + +class BlockParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(BlockParserTest); + CPPUNIT_TEST(testExample4); + CPPUNIT_TEST(testExample6); + CPPUNIT_TEST(testExample10); + CPPUNIT_TEST_SUITE_END(); + + public: + BlockParserTest() {} + + void testExample4() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<blocklist xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "<item jid='iago@shakespeare.lit'/>" + "</blocklist>")); + + BlockListPayload* payload = dynamic_cast<BlockListPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(2 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + CPPUNIT_ASSERT_EQUAL(JID("iago@shakespeare.lit"), payload->getItems()[1]); + } + + void testExample6() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<block xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "</block>")); + + BlockPayload* payload = dynamic_cast<BlockPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(1 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + } + + void testExample10() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<unblock xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "</unblock>")); + + UnblockPayload* payload = dynamic_cast<UnblockPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(1 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BlockParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp new file mode 100644 index 0000000..74da474 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Idle.h> +#include <Swiften/Base/DateTime.h> + +using namespace Swift; + +class IdleParserTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(IdleParserTest); + CPPUNIT_TEST(testParse_XepWhatever_Example1); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_XepWhatever_Example1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<presence from='juliet@capulet.com/balcony'>\n" + "<show>away</show>\n" + "<idle xmlns='urn:xmpp:idle:1' since='1969-07-21T02:56:15Z'/>\n" + "</presence>\n" + )); + + Presence::ref presence = parser.getPayload<Presence>(); + CPPUNIT_ASSERT(presence); + Idle::ref idle = presence->getPayload<Idle>(); + CPPUNIT_ASSERT(idle); + CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == idle->getSince()); + } +}; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp index 8719a5d..8c8601a 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp @@ -121,7 +121,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(4096, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(4096U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); } @@ -158,7 +158,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); } @@ -191,7 +191,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("bt8a71h6"), transportPaylod->getSessionID()); } @@ -468,7 +468,7 @@ class JingleParserTest : public CppUnit::TestFixture { StreamInitiationFileInfo file = content->getDescription<JingleFileTransferDescription>()->getRequests()[0]; CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash()); - CPPUNIT_ASSERT_EQUAL(static_cast<boost::uintmax_t>(270336), file.getRangeOffset()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long long>(270336), file.getRangeOffset()); CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests()); } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp index f1e6635..eda2547 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp @@ -7,6 +7,8 @@ #include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> +#include <boost/date_time/posix_time/posix_time.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -48,8 +50,36 @@ class VCardParserTest : public CppUnit::TestFixture { "<WORK/>" "<X400/>" "</EMAIL>" + "<TEL>" + "<NUMBER>555-6273</NUMBER>" + "<HOME/>" + "<VOICE/>" + "</TEL>" + "<ADR>" + "<LOCALITY>Any Town</LOCALITY>" + "<STREET>Fake Street 123</STREET>" + "<PCODE>12345</PCODE>" + "<CTRY>USA</CTRY>" + "<HOME/>" + "</ADR>" + "<LABEL>" + "<LINE>Fake Street 123</LINE>" + "<LINE>12345 Any Town</LINE>" + "<LINE>USA</LINE>" + "<HOME/>" + "</LABEL>" "<NICKNAME>DreamGirl</NICKNAME>" - "<BDAY>1234</BDAY>" + "<BDAY>1865-05-04</BDAY>" + "<JID>alice@teaparty.lit</JID>" + "<JID>alice@wonderland.lit</JID>" + "<DESC>I once fell down a rabbit hole.</DESC>" + "<ORG>" + "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" + "</ORG>" + "<TITLE>Some Title</TITLE>" + "<ROLE>Main Character</ROLE>" + "<URL>http://wonderland.lit/~alice</URL>" + "<URL>http://teaparty.lit/~alice2</URL>" "<MAILER>mutt</MAILER>" "</vCard>")); @@ -62,7 +92,7 @@ class VCardParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(std::string("Mrs"), payload->getPrefix()); CPPUNIT_ASSERT_EQUAL(std::string("PhD"), payload->getSuffix()); CPPUNIT_ASSERT_EQUAL(std::string("DreamGirl"), payload->getNickname()); - CPPUNIT_ASSERT_EQUAL(std::string("<BDAY xmlns=\"vcard-temp\">1234</BDAY><MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); + CPPUNIT_ASSERT_EQUAL(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)), payload->getBirthday()); CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size())); CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland.lit"), payload->getEMailAddresses()[0].address); CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome); @@ -76,6 +106,45 @@ class VCardParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred); CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork); CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTelephones().size())); + CPPUNIT_ASSERT_EQUAL(std::string("555-6273"), payload->getTelephones()[0].number); + CPPUNIT_ASSERT(payload->getTelephones()[0].isHome); + CPPUNIT_ASSERT(payload->getTelephones()[0].isVoice); + CPPUNIT_ASSERT(!payload->getTelephones()[0].isPreferred); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddresses().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Any Town"), payload->getAddresses()[0].locality); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddresses()[0].street); + CPPUNIT_ASSERT_EQUAL(std::string("12345"), payload->getAddresses()[0].postalCode); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddresses()[0].country); + CPPUNIT_ASSERT(payload->getAddresses()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddressLabels().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddressLabels()[0].lines[0]); + CPPUNIT_ASSERT_EQUAL(std::string("12345 Any Town"), payload->getAddressLabels()[0].lines[1]); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddressLabels()[0].lines[2]); + CPPUNIT_ASSERT(payload->getAddressLabels()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getJIDs().size())); + CPPUNIT_ASSERT_EQUAL(JID("alice@teaparty.lit"), payload->getJIDs()[0]); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), payload->getJIDs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("I once fell down a rabbit hole."), payload->getDescription()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getOrganizations().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland Inc."), payload->getOrganizations()[0].name); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getOrganizations()[0].units.size())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTitles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Some Title"), payload->getTitles()[0]); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getRoles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Main Character"), payload->getRoles()[0]); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getURLs().size())); + CPPUNIT_ASSERT_EQUAL(std::string("http://wonderland.lit/~alice"), payload->getURLs()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("http://teaparty.lit/~alice2"), payload->getURLs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("<MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); } void testParse_Photo() { diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp index 553d26a..620a307 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp @@ -6,6 +6,7 @@ #include <Swiften/Parser/PayloadParsers/VCardParser.h> #include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/Parser/SerializingParser.h> @@ -20,6 +21,18 @@ void VCardParser::handleStartElement(const std::string& element, const std::stri if (elementHierarchy == "/vCard/EMAIL") { currentEMailAddress_ = VCard::EMailAddress(); } + if (elementHierarchy == "/vCard/TEL") { + currentTelephone_ = VCard::Telephone(); + } + if (elementHierarchy == "/vCard/ADR") { + currentAddress_ = VCard::Address(); + } + if (elementHierarchy == "/vCard/LABEL") { + currentAddressLabel_ = VCard::AddressLabel(); + } + if (elementHierarchy == "/vCard/ORG") { + currentOrganization_ = VCard::Organization(); + } if (elementStack_.size() == 2) { assert(!unknownContentParser_); unknownContentParser_ = new SerializingParser(); @@ -90,9 +103,160 @@ void VCardParser::handleEndElement(const std::string& element, const std::string else if (elementHierarchy == "/vCard/EMAIL/PREF") { currentEMailAddress_.isPreferred = true; } - else if (elementHierarchy == "/vCard/EMAIL") { + else if (elementHierarchy == "/vCard/EMAIL" && !currentEMailAddress_.address.empty()) { getPayloadInternal()->addEMailAddress(currentEMailAddress_); } + else if (elementHierarchy == "/vCard/BDAY" && !currentText_.empty()) { + getPayloadInternal()->setBirthday(stringToDateTime(currentText_)); + } + else if (elementHierarchy == "/vCard/TEL/NUMBER") { + currentTelephone_.number = currentText_; + } + else if (elementHierarchy == "/vCard/TEL/HOME") { + currentTelephone_.isHome = true; + } + else if (elementHierarchy == "/vCard/TEL/WORK") { + currentTelephone_.isWork = true; + } + else if (elementHierarchy == "/vCard/TEL/VOICE") { + currentTelephone_.isVoice = true; + } + else if (elementHierarchy == "/vCard/TEL/FAX") { + currentTelephone_.isFax = true; + } + else if (elementHierarchy == "/vCard/TEL/PAGER") { + currentTelephone_.isPager = true; + } + else if (elementHierarchy == "/vCard/TEL/MSG") { + currentTelephone_.isMSG = true; + } + else if (elementHierarchy == "/vCard/TEL/CELL") { + currentTelephone_.isCell = true; + } + else if (elementHierarchy == "/vCard/TEL/VIDEO") { + currentTelephone_.isVideo = true; + } + else if (elementHierarchy == "/vCard/TEL/BBS") { + currentTelephone_.isBBS = true; + } + else if (elementHierarchy == "/vCard/TEL/MODEM") { + currentTelephone_.isModem = true; + } + else if (elementHierarchy == "/vCard/TEL/ISDN") { + currentTelephone_.isISDN = true; + } + else if (elementHierarchy == "/vCard/TEL/PCS") { + currentTelephone_.isPCS = true; + } + else if (elementHierarchy == "/vCard/TEL/PREF") { + currentTelephone_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/TEL" && !currentTelephone_.number.empty()) { + getPayloadInternal()->addTelephone(currentTelephone_); + } + else if (elementHierarchy == "/vCard/ADR/HOME") { + currentAddress_.isHome = true; + } + else if (elementHierarchy == "/vCard/ADR/WORK") { + currentAddress_.isWork = true; + } + else if (elementHierarchy == "/vCard/ADR/POSTAL") { + currentAddress_.isPostal = true; + } + else if (elementHierarchy == "/vCard/ADR/PARCEL") { + currentAddress_.isParcel = true; + } + else if (elementHierarchy == "/vCard/ADR/DOM") { + currentAddress_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/ADR/INTL") { + currentAddress_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/ADR/PREF") { + currentAddress_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/ADR/POBOX") { + currentAddress_.poBox = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/EXTADD") { + currentAddress_.addressExtension = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/STREET") { + currentAddress_.street = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/LOCALITY") { + currentAddress_.locality = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/REGION") { + currentAddress_.region = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/PCODE") { + currentAddress_.postalCode = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/CTRY") { + currentAddress_.country = currentText_; + } + else if (elementHierarchy == "/vCard/ADR") { + if (!currentAddress_.poBox.empty() || !currentAddress_.addressExtension.empty() || + !currentAddress_.street.empty() || !currentAddress_.locality.empty() || + !currentAddress_.region.empty() || !currentAddress_.region.empty() || + !currentAddress_.postalCode.empty() || !currentAddress_.country.empty()) { + getPayloadInternal()->addAddress(currentAddress_); + } + } + else if (elementHierarchy == "/vCard/LABEL/HOME") { + currentAddressLabel_.isHome = true; + } + else if (elementHierarchy == "/vCard/LABEL/WORK") { + currentAddressLabel_.isWork = true; + } + else if (elementHierarchy == "/vCard/LABEL/POSTAL") { + currentAddressLabel_.isPostal = true; + } + else if (elementHierarchy == "/vCard/LABEL/PARCEL") { + currentAddressLabel_.isParcel = true; + } + else if (elementHierarchy == "/vCard/LABEL/DOM") { + currentAddressLabel_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/INTL") { + currentAddressLabel_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/PREF") { + currentAddressLabel_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/LABEL/LINE") { + currentAddressLabel_.lines.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/LABEL") { + getPayloadInternal()->addAddressLabel(currentAddressLabel_); + } + else if (elementHierarchy == "/vCard/JID" && !currentText_.empty()) { + getPayloadInternal()->addJID(JID(currentText_)); + } + else if (elementHierarchy == "/vCard/DESC") { + getPayloadInternal()->setDescription(currentText_); + } + else if (elementHierarchy == "/vCard/ORG/ORGNAME") { + currentOrganization_.name = currentText_; + } + else if (elementHierarchy == "/vCard/ORG/ORGUNIT" && !currentText_.empty()) { + currentOrganization_.units.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/ORG") { + if (!currentOrganization_.name.empty() || !currentOrganization_.units.empty()) { + getPayloadInternal()->addOrganization(currentOrganization_); + } + } + else if (elementHierarchy == "/vCard/TITLE" && !currentText_.empty()) { + getPayloadInternal()->addTitle(currentText_); + } + else if (elementHierarchy == "/vCard/ROLE" && !currentText_.empty()) { + getPayloadInternal()->addRole(currentText_); + } + else if (elementHierarchy == "/vCard/URL" && !currentText_.empty()) { + getPayloadInternal()->addURL(currentText_); + } else if (elementStack_.size() == 2 && unknownContentParser_) { getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult()); } diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h index b1c47a3..f10d639 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.h +++ b/Swiften/Parser/PayloadParsers/VCardParser.h @@ -28,6 +28,10 @@ namespace Swift { private: std::vector<std::string> elementStack_; VCard::EMailAddress currentEMailAddress_; + VCard::Telephone currentTelephone_; + VCard::Address currentAddress_; + VCard::AddressLabel currentAddressLabel_; + VCard::Organization currentOrganization_; SerializingParser* unknownContentParser_; std::string currentText_; }; diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index 09d8de9..a480813 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -83,8 +83,8 @@ namespace Swift { std::string pathData = attributes.getAttributeValue("d").get_value_or(""); std::vector<std::pair<int, int> > points; if (pathData[0] == 'M') { - unsigned int pos = 1; - unsigned int npos; + size_t pos = 1; + size_t npos; int x, y; if (pathData[pos] == ' ') { pos++; @@ -163,8 +163,8 @@ namespace Swift { std::string pointsData = attributes.getAttributeValue("points").get_value_or(""); std::vector<std::pair<int, int> > points; - unsigned int pos = 0; - unsigned int npos; + size_t pos = 0; + size_t npos; int x, y; try { while (pos < pointsData.size()) { diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 64e9eb9..068cbd7 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -69,6 +69,7 @@ sources = [ "PayloadParsers/NicknameParser.cpp", "PayloadParsers/ReplaceParser.cpp", "PayloadParsers/LastParser.cpp", + "PayloadParsers/IdleParser.cpp", "PayloadParsers/S5BProxyRequestParser.cpp", "PayloadParsers/DeliveryReceiptParser.cpp", "PayloadParsers/DeliveryReceiptRequestParser.cpp", diff --git a/Swiften/Parser/Tree/ParserElement.cpp b/Swiften/Parser/Tree/ParserElement.cpp index 9d9b9b6..e5f8bc8 100644 --- a/Swiften/Parser/Tree/ParserElement.cpp +++ b/Swiften/Parser/Tree/ParserElement.cpp @@ -9,8 +9,12 @@ #include <Swiften/Parser/Tree/NullParserElement.h> #include <iostream> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> -namespace Swift{ +namespace lambda = boost::lambda; + +namespace Swift { ParserElement::ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) : name_(name), xmlns_(xmlns), attributes_(attributes) { } @@ -28,19 +32,10 @@ void ParserElement::appendCharacterData(const std::string& data) { text_ += data; } -struct DoesntMatch { - public: - DoesntMatch(const std::string& tagName, const std::string& ns) : tagName(tagName), ns(ns) {} - bool operator()(ParserElement::ref element) { return element->getName() != tagName || element->getNamespace() != ns; } - private: - std::string tagName; - std::string ns; -}; - - std::vector<ParserElement::ref> ParserElement::getChildren(const std::string& name, const std::string& xmlns) const { std::vector<ParserElement::ref> result; - std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), DoesntMatch(name, xmlns)); + std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), + lambda::bind(&ParserElement::getName, *lambda::_1) != name || lambda::bind(&ParserElement::getNamespace, *lambda::_1) != xmlns); return result; } |