OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include "third_party/libjingle_xmpp/xmllite/xmlparser.h" |
| 12 |
| 13 #include <string> |
| 14 #include <vector> |
| 15 |
| 16 #include "third_party/libjingle_xmpp/xmllite/xmlconstants.h" |
| 17 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h" |
| 18 #include "third_party/libjingle_xmpp/xmllite/xmlnsstack.h" |
| 19 #include "third_party/libjingle_xmpp/xmllite/xmlnsstack.h" |
| 20 #include "third_party/webrtc/base/common.h" |
| 21 |
| 22 namespace buzz { |
| 23 |
| 24 |
| 25 static void |
| 26 StartElementCallback(void * userData, const char *name, const char **atts) { |
| 27 (static_cast<XmlParser *>(userData))->ExpatStartElement(name, atts); |
| 28 } |
| 29 |
| 30 static void |
| 31 EndElementCallback(void * userData, const char *name) { |
| 32 (static_cast<XmlParser *>(userData))->ExpatEndElement(name); |
| 33 } |
| 34 |
| 35 static void |
| 36 CharacterDataCallback(void * userData, const char *text, int len) { |
| 37 (static_cast<XmlParser *>(userData))->ExpatCharacterData(text, len); |
| 38 } |
| 39 |
| 40 static void |
| 41 XmlDeclCallback(void * userData, const char * ver, const char * enc, int st) { |
| 42 (static_cast<XmlParser *>(userData))->ExpatXmlDecl(ver, enc, st); |
| 43 } |
| 44 |
| 45 XmlParser::XmlParser(XmlParseHandler *pxph) : |
| 46 pxph_(pxph), sentError_(false) { |
| 47 expat_ = XML_ParserCreate(NULL); |
| 48 XML_SetUserData(expat_, this); |
| 49 XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback); |
| 50 XML_SetCharacterDataHandler(expat_, CharacterDataCallback); |
| 51 XML_SetXmlDeclHandler(expat_, XmlDeclCallback); |
| 52 } |
| 53 |
| 54 void |
| 55 XmlParser::Reset() { |
| 56 if (!XML_ParserReset(expat_, NULL)) { |
| 57 XML_ParserFree(expat_); |
| 58 expat_ = XML_ParserCreate(NULL); |
| 59 } |
| 60 XML_SetUserData(expat_, this); |
| 61 XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback); |
| 62 XML_SetCharacterDataHandler(expat_, CharacterDataCallback); |
| 63 XML_SetXmlDeclHandler(expat_, XmlDeclCallback); |
| 64 context_.Reset(); |
| 65 sentError_ = false; |
| 66 } |
| 67 |
| 68 static bool |
| 69 XmlParser_StartsWithXmlns(const char *name) { |
| 70 return name[0] == 'x' && |
| 71 name[1] == 'm' && |
| 72 name[2] == 'l' && |
| 73 name[3] == 'n' && |
| 74 name[4] == 's'; |
| 75 } |
| 76 |
| 77 void |
| 78 XmlParser::ExpatStartElement(const char *name, const char **atts) { |
| 79 if (context_.RaisedError() != XML_ERROR_NONE) |
| 80 return; |
| 81 const char **att; |
| 82 context_.StartElement(); |
| 83 for (att = atts; *att; att += 2) { |
| 84 if (XmlParser_StartsWithXmlns(*att)) { |
| 85 if ((*att)[5] == '\0') { |
| 86 context_.StartNamespace("", *(att + 1)); |
| 87 } |
| 88 else if ((*att)[5] == ':') { |
| 89 if (**(att + 1) == '\0') { |
| 90 // In XML 1.0 empty namespace illegal with prefix (not in 1.1) |
| 91 context_.RaiseError(XML_ERROR_SYNTAX); |
| 92 return; |
| 93 } |
| 94 context_.StartNamespace((*att) + 6, *(att + 1)); |
| 95 } |
| 96 } |
| 97 } |
| 98 context_.SetPosition(XML_GetCurrentLineNumber(expat_), |
| 99 XML_GetCurrentColumnNumber(expat_), |
| 100 XML_GetCurrentByteIndex(expat_)); |
| 101 pxph_->StartElement(&context_, name, atts); |
| 102 } |
| 103 |
| 104 void |
| 105 XmlParser::ExpatEndElement(const char *name) { |
| 106 if (context_.RaisedError() != XML_ERROR_NONE) |
| 107 return; |
| 108 context_.EndElement(); |
| 109 context_.SetPosition(XML_GetCurrentLineNumber(expat_), |
| 110 XML_GetCurrentColumnNumber(expat_), |
| 111 XML_GetCurrentByteIndex(expat_)); |
| 112 pxph_->EndElement(&context_, name); |
| 113 } |
| 114 |
| 115 void |
| 116 XmlParser::ExpatCharacterData(const char *text, int len) { |
| 117 if (context_.RaisedError() != XML_ERROR_NONE) |
| 118 return; |
| 119 context_.SetPosition(XML_GetCurrentLineNumber(expat_), |
| 120 XML_GetCurrentColumnNumber(expat_), |
| 121 XML_GetCurrentByteIndex(expat_)); |
| 122 pxph_->CharacterData(&context_, text, len); |
| 123 } |
| 124 |
| 125 void |
| 126 XmlParser::ExpatXmlDecl(const char * ver, const char * enc, int standalone) { |
| 127 if (context_.RaisedError() != XML_ERROR_NONE) |
| 128 return; |
| 129 |
| 130 if (ver && std::string("1.0") != ver) { |
| 131 context_.RaiseError(XML_ERROR_SYNTAX); |
| 132 return; |
| 133 } |
| 134 |
| 135 if (standalone == 0) { |
| 136 context_.RaiseError(XML_ERROR_SYNTAX); |
| 137 return; |
| 138 } |
| 139 |
| 140 if (enc && !((enc[0] == 'U' || enc[0] == 'u') && |
| 141 (enc[1] == 'T' || enc[1] == 't') && |
| 142 (enc[2] == 'F' || enc[2] == 'f') && |
| 143 enc[3] == '-' && enc[4] =='8')) { |
| 144 context_.RaiseError(XML_ERROR_INCORRECT_ENCODING); |
| 145 return; |
| 146 } |
| 147 |
| 148 } |
| 149 |
| 150 bool |
| 151 XmlParser::Parse(const char *data, size_t len, bool isFinal) { |
| 152 if (sentError_) |
| 153 return false; |
| 154 |
| 155 if (XML_Parse(expat_, data, static_cast<int>(len), isFinal) != |
| 156 XML_STATUS_OK) { |
| 157 context_.SetPosition(XML_GetCurrentLineNumber(expat_), |
| 158 XML_GetCurrentColumnNumber(expat_), |
| 159 XML_GetCurrentByteIndex(expat_)); |
| 160 context_.RaiseError(XML_GetErrorCode(expat_)); |
| 161 } |
| 162 |
| 163 if (context_.RaisedError() != XML_ERROR_NONE) { |
| 164 sentError_ = true; |
| 165 pxph_->Error(&context_, context_.RaisedError()); |
| 166 return false; |
| 167 } |
| 168 |
| 169 return true; |
| 170 } |
| 171 |
| 172 XmlParser::~XmlParser() { |
| 173 XML_ParserFree(expat_); |
| 174 } |
| 175 |
| 176 void |
| 177 XmlParser::ParseXml(XmlParseHandler *pxph, std::string text) { |
| 178 XmlParser parser(pxph); |
| 179 parser.Parse(text.c_str(), text.length(), true); |
| 180 } |
| 181 |
| 182 XmlParser::ParseContext::ParseContext() : |
| 183 xmlnsstack_(), |
| 184 raised_(XML_ERROR_NONE), |
| 185 line_number_(0), |
| 186 column_number_(0), |
| 187 byte_index_(0) { |
| 188 } |
| 189 |
| 190 void |
| 191 XmlParser::ParseContext::StartNamespace(const char *prefix, const char *ns) { |
| 192 xmlnsstack_.AddXmlns(*prefix ? prefix : STR_EMPTY, ns); |
| 193 } |
| 194 |
| 195 void |
| 196 XmlParser::ParseContext::StartElement() { |
| 197 xmlnsstack_.PushFrame(); |
| 198 } |
| 199 |
| 200 void |
| 201 XmlParser::ParseContext::EndElement() { |
| 202 xmlnsstack_.PopFrame(); |
| 203 } |
| 204 |
| 205 QName |
| 206 XmlParser::ParseContext::ResolveQName(const char* qname, bool isAttr) { |
| 207 const char *c; |
| 208 for (c = qname; *c; ++c) { |
| 209 if (*c == ':') { |
| 210 const std::pair<std::string, bool> result = |
| 211 xmlnsstack_.NsForPrefix(std::string(qname, c - qname)); |
| 212 if (!result.second) |
| 213 return QName(); |
| 214 return QName(result.first, c + 1); |
| 215 } |
| 216 } |
| 217 if (isAttr) |
| 218 return QName(STR_EMPTY, qname); |
| 219 |
| 220 std::pair<std::string, bool> result = xmlnsstack_.NsForPrefix(STR_EMPTY); |
| 221 if (!result.second) |
| 222 return QName(); |
| 223 |
| 224 return QName(result.first, qname); |
| 225 } |
| 226 |
| 227 void |
| 228 XmlParser::ParseContext::Reset() { |
| 229 xmlnsstack_.Reset(); |
| 230 raised_ = XML_ERROR_NONE; |
| 231 } |
| 232 |
| 233 void |
| 234 XmlParser::ParseContext::SetPosition(int line, int column, |
| 235 long byte_index) { |
| 236 line_number_ = line; |
| 237 column_number_ = column; |
| 238 byte_index_ = byte_index; |
| 239 } |
| 240 |
| 241 void |
| 242 XmlParser::ParseContext::GetPosition(unsigned long * line, |
| 243 unsigned long * column, |
| 244 unsigned long * byte_index) { |
| 245 if (line != NULL) { |
| 246 *line = static_cast<unsigned long>(line_number_); |
| 247 } |
| 248 |
| 249 if (column != NULL) { |
| 250 *column = static_cast<unsigned long>(column_number_); |
| 251 } |
| 252 |
| 253 if (byte_index != NULL) { |
| 254 *byte_index = static_cast<unsigned long>(byte_index_); |
| 255 } |
| 256 } |
| 257 |
| 258 XmlParser::ParseContext::~ParseContext() { |
| 259 } |
| 260 |
| 261 } // namespace buzz |
OLD | NEW |