diff options
Diffstat (limited to 'Swiften/Parser/BOSHBodyExtractor.cpp')
-rw-r--r-- | Swiften/Parser/BOSHBodyExtractor.cpp | 216 |
1 files changed, 108 insertions, 108 deletions
diff --git a/Swiften/Parser/BOSHBodyExtractor.cpp b/Swiften/Parser/BOSHBodyExtractor.cpp index e0a37df..c5723be 100644 --- a/Swiften/Parser/BOSHBodyExtractor.cpp +++ b/Swiften/Parser/BOSHBodyExtractor.cpp @@ -16,124 +16,124 @@ namespace Swift { class BOSHBodyParserClient : public XMLParserClient { - public: - BOSHBodyParserClient(BOSHBodyExtractor* bodyExtractor) : bodyExtractor(bodyExtractor) { - } + public: + BOSHBodyParserClient(BOSHBodyExtractor* bodyExtractor) : bodyExtractor(bodyExtractor) { + } - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - bodyExtractor->body->attributes = attributes; - } + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + bodyExtractor->body->attributes = attributes; + } - virtual void handleEndElement(const std::string&, const std::string&) { - } + virtual void handleEndElement(const std::string&, const std::string&) { + } - virtual void handleCharacterData(const std::string&) { - } + virtual void handleCharacterData(const std::string&) { + } - private: - BOSHBodyExtractor* bodyExtractor; + private: + BOSHBodyExtractor* bodyExtractor; }; inline bool isWhitespace(unsigned char c) { - return c == ' ' || c == '\n' || c == '\t' || c == '\r'; + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; } BOSHBodyExtractor::BOSHBodyExtractor(XMLParserFactory* parserFactory, const ByteArray& data) { - // Look for the opening body element - ByteArray::const_iterator i = data.begin(); - while (i < data.end() && isWhitespace(*i)) { - ++i; - } - if (std::distance(i, data.end()) < 6 || *i != '<' || *(i+1) != 'b' || *(i+2) != 'o' || *(i+3) != 'd' || *(i+4) != 'y' || !(isWhitespace(*(i+5)) || *(i+5) == '>' || *(i+5) == '/')) { - return; - } - i += 5; - - // Parse until end of element - bool inSingleQuote = false; - bool inDoubleQuote = false; - bool endStartTagSeen = false; - bool endElementSeen = false; - for (; i != data.end(); ++i) { - char c = static_cast<char>(*i); - if (inSingleQuote) { - if (c == '\'') { - inSingleQuote = false; - } - } - else if (inDoubleQuote) { - if (c == '"') { - inDoubleQuote = false; - } - } - else if (c == '\'') { - inSingleQuote = true; - } - else if (c == '"') { - inDoubleQuote = true; - } - else if (c == '/') { - if (i + 1 == data.end() || *(i+1) != '>') { - return; - } - else { - endElementSeen = true; - endStartTagSeen = true; - i += 2; - break; - } - } - else if (c == '>') { - endStartTagSeen = true; - i += 1; - break; - } - } - - if (!endStartTagSeen) { - return; - } - - // Look for the end of the element - ByteArray::const_reverse_iterator j = data.rbegin(); - if (!endElementSeen) { - while (isWhitespace(*j) && j < data.rend()) { - ++j; - } - - if (j == data.rend() || *j != '>') { - return; - } - ++j; - - while (j < data.rend() && isWhitespace(*j)) { - ++j; - } - - if (std::distance(j, data.rend()) < 6 || *(j+5) != '<' || *(j+4) != '/' || *(j+3) != 'b' || *(j+2) != 'o' || *(j+1) != 'd' || *j != 'y') { - return; - } - j += 6; - } - - body = BOSHBody(); - if (!endElementSeen) { - body->content = std::string( - reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), - boost::numeric_cast<size_t>(std::distance(i, j.base()))); - } - - // Parse the body element - BOSHBodyParserClient parserClient(this); - boost::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient)); - if (!parser->parse(std::string( - reinterpret_cast<const char*>(vecptr(data)), - boost::numeric_cast<size_t>(std::distance(data.begin(), i))))) { - /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at - the correct higher layer */ - body = boost::optional<BOSHBody>(); - return; - } + // Look for the opening body element + ByteArray::const_iterator i = data.begin(); + while (i < data.end() && isWhitespace(*i)) { + ++i; + } + if (std::distance(i, data.end()) < 6 || *i != '<' || *(i+1) != 'b' || *(i+2) != 'o' || *(i+3) != 'd' || *(i+4) != 'y' || !(isWhitespace(*(i+5)) || *(i+5) == '>' || *(i+5) == '/')) { + return; + } + i += 5; + + // Parse until end of element + bool inSingleQuote = false; + bool inDoubleQuote = false; + bool endStartTagSeen = false; + bool endElementSeen = false; + for (; i != data.end(); ++i) { + char c = static_cast<char>(*i); + if (inSingleQuote) { + if (c == '\'') { + inSingleQuote = false; + } + } + else if (inDoubleQuote) { + if (c == '"') { + inDoubleQuote = false; + } + } + else if (c == '\'') { + inSingleQuote = true; + } + else if (c == '"') { + inDoubleQuote = true; + } + else if (c == '/') { + if (i + 1 == data.end() || *(i+1) != '>') { + return; + } + else { + endElementSeen = true; + endStartTagSeen = true; + i += 2; + break; + } + } + else if (c == '>') { + endStartTagSeen = true; + i += 1; + break; + } + } + + if (!endStartTagSeen) { + return; + } + + // Look for the end of the element + ByteArray::const_reverse_iterator j = data.rbegin(); + if (!endElementSeen) { + while (isWhitespace(*j) && j < data.rend()) { + ++j; + } + + if (j == data.rend() || *j != '>') { + return; + } + ++j; + + while (j < data.rend() && isWhitespace(*j)) { + ++j; + } + + if (std::distance(j, data.rend()) < 6 || *(j+5) != '<' || *(j+4) != '/' || *(j+3) != 'b' || *(j+2) != 'o' || *(j+1) != 'd' || *j != 'y') { + return; + } + j += 6; + } + + body = BOSHBody(); + if (!endElementSeen) { + body->content = std::string( + reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), + boost::numeric_cast<size_t>(std::distance(i, j.base()))); + } + + // Parse the body element + BOSHBodyParserClient parserClient(this); + boost::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient)); + if (!parser->parse(std::string( + reinterpret_cast<const char*>(vecptr(data)), + boost::numeric_cast<size_t>(std::distance(data.begin(), i))))) { + /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at + the correct higher layer */ + body = boost::optional<BOSHBody>(); + return; + } } } |