diff options
Diffstat (limited to 'Swiften/Parser')
119 files changed, 4142 insertions, 0 deletions
diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h new file mode 100644 index 0000000..6662b98 --- /dev/null +++ b/Swiften/Parser/AttributeMap.h @@ -0,0 +1,25 @@ +#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; + } + } + }; +} + +#endif 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/AuthSuccessParser.h b/Swiften/Parser/AuthSuccessParser.h new file mode 100644 index 0000000..bb6515d --- /dev/null +++ b/Swiften/Parser/AuthSuccessParser.h @@ -0,0 +1,14 @@ +#ifndef SWIFTEN_AUTHSUCCESSPARSER_H +#define SWIFTEN_AUTHSUCCESSPARSER_H + +#include "Swiften/Parser/GenericElementParser.h" +#include "Swiften/Elements/AuthSuccess.h" + +namespace Swift { + class AuthSuccessParser : public GenericElementParser<AuthSuccess> { + public: + AuthSuccessParser() : GenericElementParser<AuthSuccess>() {} + }; +} + +#endif 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..6d23c93 --- /dev/null +++ b/Swiften/Parser/ExpatParser.cpp @@ -0,0 +1,66 @@ +#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); + 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..8f14f21 --- /dev/null +++ b/Swiften/Parser/LibXMLParser.cpp @@ -0,0 +1,63 @@ +#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** attributes) { + AttributeMap attributeValues; + const xmlChar** currentAttribute = attributes; + if (currentAttribute) { + while (*currentAttribute) { + attributeValues[String(reinterpret_cast<const char*>(*currentAttribute))] = String(reinterpret_cast<const char*>(*(currentAttribute+1))); + currentAttribute += 2; + } + } + static_cast<XMLParserClient*>(client)->handleStartElement(reinterpret_cast<const char*>(name), attributeValues); +} + +static void handleEndElement(void *client, const xmlChar* name) { + static_cast<XMLParserClient*>(client)->handleEndElement(reinterpret_cast<const char*>(name)); +} + +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*, ... ) { +} + +static void handleWarning(void*, const char*, ... ) { +} + + + +LibXMLParser::LibXMLParser(XMLParserClient* client) : XMLParser(client) { + memset(&handler_, 0, sizeof(handler_) ); + handler_.initialized = XML_SAX2_MAGIC; + handler_.startElement = &handleStartElement; + handler_.endElement = &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..f8faef6 --- /dev/null +++ b/Swiften/Parser/LibXMLParser.h @@ -0,0 +1,23 @@ +#ifndef SWIFTEN_LibXMLParser_H +#define SWIFTEN_LibXMLParser_H + +#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_; + }; +} + +#endif diff --git a/Swiften/Parser/Makefile.inc b/Swiften/Parser/Makefile.inc new file mode 100644 index 0000000..f47ae29 --- /dev/null +++ b/Swiften/Parser/Makefile.inc @@ -0,0 +1,32 @@ +SWIFTEN_SOURCES += \ + Swiften/Parser/XMLParser.cpp \ + Swiften/Parser/XMLParserClient.cpp \ + Swiften/Parser/XMLParserFactory.cpp \ + Swiften/Parser/PlatformXMLParserFactory.cpp \ + Swiften/Parser/XMPPParser.cpp \ + Swiften/Parser/XMPPParserClient.cpp \ + Swiften/Parser/MessageParser.cpp \ + Swiften/Parser/IQParser.cpp \ + Swiften/Parser/PresenceParser.cpp \ + Swiften/Parser/StreamFeaturesParser.cpp \ + Swiften/Parser/CompressParser.cpp \ + Swiften/Parser/AuthRequestParser.cpp \ + Swiften/Parser/StanzaParser.cpp \ + Swiften/Parser/ElementParser.cpp \ + Swiften/Parser/PayloadParser.cpp \ + Swiften/Parser/PayloadParserFactory.cpp \ + Swiften/Parser/PayloadParserFactoryCollection.cpp \ + Swiften/Parser/SerializingParser.cpp + +ifeq ($(HAVE_LIBXML),yes) +SWIFTEN_SOURCES += \ + Swiften/Parser/LibXMLParser.cpp +endif + +ifeq ($(HAVE_EXPAT),yes) +SWIFTEN_SOURCES += \ + Swiften/Parser/ExpatParser.cpp +endif + +include Swiften/Parser/PayloadParsers/Makefile.inc +include Swiften/Parser/UnitTest/Makefile.inc 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..f361ce8 --- /dev/null +++ b/Swiften/Parser/PayloadParserFactoryCollection.cpp @@ -0,0 +1,27 @@ +#include <boost/bind.hpp> +#include <algorithm> + +#include "Swiften/Parser/PayloadParserFactoryCollection.h" +#include "Swiften/Parser/PayloadParserFactory.h" + +namespace Swift { + +PayloadParserFactoryCollection::PayloadParserFactoryCollection() { +} + +void PayloadParserFactoryCollection::addFactory(PayloadParserFactory* factory) { + factories_.push_back(factory); +} + +void PayloadParserFactoryCollection::removeFactory(PayloadParserFactory* factory) { + factories_.erase(remove(factories_.begin(), factories_.end(), factory), factories_.end()); +} + +PayloadParserFactory* PayloadParserFactoryCollection::getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes) { + std::vector<PayloadParserFactory*>::const_iterator i = std::find_if( + factories_.begin(), factories_.end(), + boost::bind(&PayloadParserFactory::canParse, _1, element, ns, attributes)); + return (i != factories_.end() ? *i : NULL); +} + +} diff --git a/Swiften/Parser/PayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParserFactoryCollection.h new file mode 100644 index 0000000..fad94c3 --- /dev/null +++ b/Swiften/Parser/PayloadParserFactoryCollection.h @@ -0,0 +1,25 @@ +#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); + PayloadParserFactory* getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes); + + private: + std::vector<PayloadParserFactory*> factories_; + }; +} + +#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/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..13380c8 --- /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(Error::Continue); + } + else if (type == "modify") { + getPayloadInternal()->setType(Error::Modify); + } + else if (type == "auth") { + getPayloadInternal()->setType(Error::Auth); + } + else if (type == "wait") { + getPayloadInternal()->setType(Error::Wait); + } + else { + getPayloadInternal()->setType(Error::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(Error::BadRequest); + } + else if (element == "conflict") { + getPayloadInternal()->setCondition(Error::Conflict); + } + else if (element == "feature-not-implemented") { + getPayloadInternal()->setCondition(Error::FeatureNotImplemented); + } + else if (element == "forbidden") { + getPayloadInternal()->setCondition(Error::Forbidden); + } + else if (element == "gone") { + getPayloadInternal()->setCondition(Error::Gone); + } + else if (element == "internal-server-error") { + getPayloadInternal()->setCondition(Error::InternalServerError); + } + else if (element == "item-not-found") { + getPayloadInternal()->setCondition(Error::ItemNotFound); + } + else if (element == "jid-malformed") { + getPayloadInternal()->setCondition(Error::JIDMalformed); + } + else if (element == "not-acceptable") { + getPayloadInternal()->setCondition(Error::NotAcceptable); + } + else if (element == "not-allowed") { + getPayloadInternal()->setCondition(Error::NotAllowed); + } + else if (element == "not-authorized") { + getPayloadInternal()->setCondition(Error::NotAuthorized); + } + else if (element == "payment-required") { + getPayloadInternal()->setCondition(Error::PaymentRequired); + } + else if (element == "recipient-unavailable") { + getPayloadInternal()->setCondition(Error::RecipientUnavailable); + } + else if (element == "redirect") { + getPayloadInternal()->setCondition(Error::Redirect); + } + else if (element == "registration-required") { + getPayloadInternal()->setCondition(Error::RegistrationRequired); + } + else if (element == "remote-server-not-found") { + getPayloadInternal()->setCondition(Error::RemoteServerNotFound); + } + else if (element == "remote-server-timeout") { + getPayloadInternal()->setCondition(Error::RemoteServerTimeout); + } + else if (element == "resource-constraint") { + getPayloadInternal()->setCondition(Error::ResourceConstraint); + } + else if (element == "service-unavailable") { + getPayloadInternal()->setCondition(Error::ServiceUnavailable); + } + else if (element == "subscription-required") { + getPayloadInternal()->setCondition(Error::SubscriptionRequired); + } + else if (element == "unexpected-request") { + getPayloadInternal()->setCondition(Error::UnexpectedRequest); + } + else { + getPayloadInternal()->setCondition(Error::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..76db205 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ErrorParser.h @@ -0,0 +1,26 @@ +#ifndef SWIFTEN_ErrorParser_H +#define SWIFTEN_ErrorParser_H + +#include "Swiften/Elements/Error.h" +#include "Swiften/Parser/GenericPayloadParser.h" + +namespace Swift { + class ErrorParser : public GenericPayloadParser<Error> { + 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..fb2fea7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -0,0 +1,46 @@ +#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/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/DiscoInfoParserFactory.h" +#include "Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h" +#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.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 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())); + foreach(shared_ptr<PayloadParserFactory> factory, factories_) { + addFactory(factory.get()); + } +} + +FullPayloadParserFactoryCollection::~FullPayloadParserFactoryCollection() { + 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..3c383ec --- /dev/null +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h @@ -0,0 +1,21 @@ +#ifndef SWIFTEN_FULLPAYLOADPARSERFACTORYCOLLECTION_H +#define SWIFTEN_FULLPAYLOADPARSERFACTORYCOLLECTION_H + +#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_; + }; +} + +#endif diff --git a/Swiften/Parser/PayloadParsers/Makefile.inc b/Swiften/Parser/PayloadParsers/Makefile.inc new file mode 100644 index 0000000..828dc5e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/Makefile.inc @@ -0,0 +1,15 @@ +SWIFTEN_SOURCES += \ + Swiften/Parser/PayloadParsers/BodyParser.cpp \ + Swiften/Parser/PayloadParsers/PriorityParser.cpp \ + Swiften/Parser/PayloadParsers/StatusParser.cpp \ + Swiften/Parser/PayloadParsers/StatusShowParser.cpp \ + Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp \ + Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp \ + Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp \ + Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp \ + Swiften/Parser/PayloadParsers/ErrorParser.cpp \ + Swiften/Parser/PayloadParsers/RosterParser.cpp \ + Swiften/Parser/PayloadParsers/ResourceBindParser.cpp \ + Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp + +include Swiften/Parser/PayloadParsers/UnitTest/Makefile.inc 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/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..d571f0b --- /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..ec31235 --- /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/UnitTest/BodyParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp new file mode 100644 index 0000000..c747452 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp @@ -0,0 +1,29 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/BodyParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class BodyParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(BodyParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + BodyParserTest() {} + + void testParse() { + BodyParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<body>foo<baz>bar</baz>fum</body>")); + + Body* payload = dynamic_cast<Body*>(testling.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..5aed12f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp @@ -0,0 +1,48 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class DiscoInfoParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DiscoInfoParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + DiscoInfoParserTest() {} + + void testParse() { + DiscoInfoParser testling; + PayloadParserTester parser(&testling); + + 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*>(testling.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..719702d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp @@ -0,0 +1,35 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/ErrorParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class ErrorParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ErrorParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + ErrorParserTest() {} + + void testParse() { + ErrorParser testling; + PayloadParserTester parser(&testling); + + 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>")); + + Error* payload = dynamic_cast<Error*>(testling.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(Error::BadRequest, payload->getCondition()); + CPPUNIT_ASSERT_EQUAL(Error::Modify, payload->getType()); + CPPUNIT_ASSERT_EQUAL(String("boo"), payload->getText()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ErrorParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/Makefile.inc b/Swiften/Parser/PayloadParsers/UnitTest/Makefile.inc new file mode 100644 index 0000000..f4d4cf9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/Makefile.inc @@ -0,0 +1,12 @@ +UNITTEST_SOURCES += \ + Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp \ + Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h new file mode 100644 index 0000000..bac33bf --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h @@ -0,0 +1,10 @@ +#ifndef SWIFTEN_PayloadParserTester_H +#define SWIFTEN_PayloadParserTester_H + +#include "Swiften/Parser/UnitTest/ParserTester.h" + +namespace Swift { + typedef ParserTester<PayloadParser> PayloadParserTester; +} + +#endif diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp new file mode 100644 index 0000000..a186ebd --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp @@ -0,0 +1,29 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/PriorityParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class PriorityParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(PriorityParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + PriorityParserTest() {} + + void testParse() { + PriorityParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<priority>-120</priority>")); + + Priority* payload = dynamic_cast<Priority*>(testling.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(-120, payload->getPriority()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PriorityParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp new file mode 100644 index 0000000..67cb9cc --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp @@ -0,0 +1,40 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/ResourceBindParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.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() { + ResourceBindParser testling; + PayloadParserTester parser(&testling); + + 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*>(testling.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(JID("somenode@example.com/someresource"), payload->getJID()); + } + + void testParse_Resource() { + ResourceBindParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>someresource</resource></bind>")); + + ResourceBind* payload = dynamic_cast<ResourceBind*>(testling.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..7f0fc64 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp @@ -0,0 +1,51 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/RosterParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/XMLPayloadParser.h" + +using namespace Swift; + +class RosterParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RosterParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + RosterParserTest() {} + + void testParse() { + RosterParser testling; + XMLPayloadParser parser(&testling); + 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*>(testling.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..5da3fbd --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp @@ -0,0 +1,46 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/SecurityLabelParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class SecurityLabelParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(SecurityLabelParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + SecurityLabelParserTest() {} + + void testParse() { + SecurityLabelParser testling; + PayloadParserTester parser(&testling); + + 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*>(testling.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..0021c0d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp @@ -0,0 +1,46 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class SecurityLabelsCatalogParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(SecurityLabelsCatalogParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + SecurityLabelsCatalogParserTest() {} + + void testParse() { + SecurityLabelsCatalogParser testling; + PayloadParserTester parser(&testling); + + 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*>(testling.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..0ff1d00 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp @@ -0,0 +1,36 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class SoftwareVersionParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(SoftwareVersionParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + SoftwareVersionParserTest() {} + + void testParse() { + SoftwareVersionParser testling; + PayloadParserTester parser(&testling); + + 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*>(testling.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..f1fa7b1 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp @@ -0,0 +1,29 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/StatusParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" + +using namespace Swift; + +class StatusParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(StatusParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + StatusParserTest() {} + + void testParse() { + StatusParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<status>foo<baz>bar</baz>fum</status>")); + + Status* payload = dynamic_cast<Status*>(testling.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..d89fdc5 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp @@ -0,0 +1,73 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/StatusShowParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.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() { + StatusShowParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<show>invalid</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(testling.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::Online == payload->getType()); + } + + void testParse_Away() { + StatusShowParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<show>away</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(testling.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::Away == payload->getType()); + } + + void testParse_FFC() { + StatusShowParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<show>chat</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(testling.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::FFC == payload->getType()); + } + + void testParse_XA() { + StatusShowParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<show>xa</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(testling.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::XA == payload->getType()); + } + + void testParse_DND() { + StatusShowParser testling; + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<show>dnd</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(testling.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::DND == payload->getType()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(StatusShowParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/XMLPayloadParser.h b/Swiften/Parser/PayloadParsers/UnitTest/XMLPayloadParser.h new file mode 100644 index 0000000..2b893c4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/XMLPayloadParser.h @@ -0,0 +1,42 @@ +#ifndef SWIFTEN_XMLPayloadParser_H +#define SWIFTEN_XMLPayloadParser_H + +#include "Swiften/Parser/PayloadParser.h" +#include "Swiften/Parser/XMLParserClient.h" +#include "Swiften/Parser/XMLParser.h" +#include "Swiften/Parser/PlatformXMLParserFactory.h" + +namespace Swift { + class XMLPayloadParser : public XMLParserClient { + public: + XMLPayloadParser(PayloadParser* payloadParser) : + payloadParser_(payloadParser) { + xmlParser_ = PlatformXMLParserFactory().createXMLParser(this); + } + + ~XMLPayloadParser() { + delete xmlParser_; + } + + bool parse(const String& data) { + return xmlParser_->parse(data); + } + + virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) { + payloadParser_->handleStartElement(element, ns, attributes); + } + + virtual void handleEndElement(const String& element, const String& ns) { + payloadParser_->handleEndElement(element, ns); + } + + virtual void handleCharacterData(const String& data) { + payloadParser_->handleCharacterData(data); + } + + private: + XMLParser* xmlParser_; + PayloadParser* payloadParser_; + }; +} +#endif diff --git a/Swiften/Parser/PlatformXMLParserFactory.cpp b/Swiften/Parser/PlatformXMLParserFactory.cpp new file mode 100644 index 0000000..14557d1 --- /dev/null +++ b/Swiften/Parser/PlatformXMLParserFactory.cpp @@ -0,0 +1,28 @@ +#include "Swiften/Parser/PlatformXMLParserFactory.h" + +#include <cassert> + +#ifdef HAVE_SWIFTEN_CONFIG_H +#include "Swiften/config.h" +#endif +#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/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/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/Makefile.inc b/Swiften/Parser/UnitTest/Makefile.inc new file mode 100644 index 0000000..4f9c59e --- /dev/null +++ b/Swiften/Parser/UnitTest/Makefile.inc @@ -0,0 +1,9 @@ +UNITTEST_SOURCES += \ + Swiften/Parser/UnitTest/XMPPParserTest.cpp \ + Swiften/Parser/UnitTest/StanzaParserTest.cpp \ + Swiften/Parser/UnitTest/MessageParserTest.cpp \ + Swiften/Parser/UnitTest/PresenceParserTest.cpp \ + Swiften/Parser/UnitTest/IQParserTest.cpp \ + Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp \ + Swiften/Parser/UnitTest/SerializingParserTest.cpp \ + Swiften/Parser/UnitTest/XMLParserTest.cpp 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/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<&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<&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..a26b31b --- /dev/null +++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp @@ -0,0 +1,194 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <vector> + +#ifdef HAVE_CONFIG_H +#include "Swiften/config.h" +#endif +#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_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: + XMLParserTest() {} + + 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(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].attributes.size()); + CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].attributes["xmlns"]); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[2].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[3].data); + } + + 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("p:x"), client_.events[0].data); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(String("p:y"), client_.events[1].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(String("p:y"), client_.events[2].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(String("p:x"), client_.events[3].data); + } + + 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 AttributeMap& attributes) + : type(type), data(data), attributes(attributes) {} + Event(Type type, const String& data) + : type(type), data(data) {} + + Type type; + String data; + AttributeMap attributes; + }; + + Client() {} + + virtual void handleStartElement(const String& element, const AttributeMap& attributes) { + events.push_back(Event(StartElement, element, attributes)); + } + + virtual void handleEndElement(const String& element) { + events.push_back(Event(EndElement, element)); + } + + 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..787828c --- /dev/null +++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp @@ -0,0 +1,166 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <vector> + +#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_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(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_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) : type(type) {} + + Type type; + boost::shared_ptr<Element> element; + }; + + Client() {} + + void handleStreamStart() { + events.push_back(Event(StreamStart)); + } + + 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..e05cbca --- /dev/null +++ b/Swiften/Parser/XMPPParser.cpp @@ -0,0 +1,145 @@ +#include "Swiften/Parser/XMPPParser.h" + +#include <iostream> +#include <cassert> + +#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/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") { + client_->handleStreamStart(); + } + 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 == "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..abecc71 --- /dev/null +++ b/Swiften/Parser/XMPPParserClient.h @@ -0,0 +1,20 @@ +#ifndef SWIFTEN_XMPPPARSERCLIENT_H +#define SWIFTEN_XMPPPARSERCLIENT_H + +#include <boost/shared_ptr.hpp> + +#include "Swiften/Elements/Element.h" + +namespace Swift { + class XMPPParserClient + { + public: + virtual ~XMPPParserClient(); + + virtual void handleStreamStart() = 0; + virtual void handleElement(boost::shared_ptr<Element>) = 0; + virtual void handleStreamEnd() = 0; + }; +} + +#endif |