void VTTCue::determineTextDirection() { DEFINE_STATIC_LOCAL(const String, rtTag, (ASCIILiteral("rt"))); createWebVTTNodeTree(); if (!m_webVTTNodeTree) return; // Apply the Unicode Bidirectional Algorithm's Paragraph Level steps to the // concatenation of the values of each WebVTT Text Object in nodes, in a // pre-order, depth-first traversal, excluding WebVTT Ruby Text Objects and // their descendants. StringBuilder paragraphBuilder; for (Node* node = m_webVTTNodeTree->firstChild(); node; node = NodeTraversal::next(node, m_webVTTNodeTree.get())) { // FIXME: The code does not match the comment above. This does not actually exclude Ruby Text Object descendant. if (!node->isTextNode() || node->localName() == rtTag) continue; paragraphBuilder.append(node->nodeValue()); } String paragraph = paragraphBuilder.toString(); if (!paragraph.length()) return; for (size_t i = 0; i < paragraph.length(); ++i) { UChar current = paragraph[i]; if (!current || isCueParagraphSeparator(current)) return; if (UChar current = paragraph[i]) { UCharDirection charDirection = u_charDirection(current); if (charDirection == U_LEFT_TO_RIGHT) { m_displayDirection = CSSValueLtr; return; } if (charDirection == U_RIGHT_TO_LEFT || charDirection == U_RIGHT_TO_LEFT_ARABIC) { m_displayDirection = CSSValueRtl; return; } } } }
/** * Takes a pointer to an XML node that is assumed to point at a "material" * tag. * It reads the definition and produces a new Material object. * @param element A pointer to an Element node that is a "material" tag * @return A new Material object */ Material MaterialXMLParser::parse(Poco::XML::Element *element) const { using namespace Poco::XML; typedef AutoPtr<NamedNodeMap> NamedNodeMapPtr; NamedNodeMapPtr attrs = element->attributes(); const auto id = attrs->getNamedItem(ID_ATT); if (!id || id->nodeValue().empty()) { throw std::invalid_argument("MaterialXMLReader::read() - No 'id' tag found " "or emptry string provided."); } attrs->removeNamedItem(ID_ATT); MaterialBuilder builder; builder.setName(id->nodeValue()); const auto nattrs = attrs->length(); for (unsigned long i = 0; i < nattrs; ++i) { Node *node = attrs->item(i); addToBuilder(&builder, node->nodeName(), node->nodeValue()); } return builder.build(); }
static CSSValueID determineTextDirection(DocumentFragment* vttRoot) { DEFINE_STATIC_LOCAL(const String, rtTag, ("rt")); ASSERT(vttRoot); // Apply the Unicode Bidirectional Algorithm's Paragraph Level steps to the // concatenation of the values of each WebVTT Text Object in nodes, in a // pre-order, depth-first traversal, excluding WebVTT Ruby Text Objects and // their descendants. TextDirection textDirection = LTR; for (Node* node = vttRoot->firstChild(); node; node = NodeTraversal::next(*node, vttRoot)) { if (!node->isTextNode() || node->localName() == rtTag) continue; bool hasStrongDirectionality; textDirection = determineDirectionality(node->nodeValue(), hasStrongDirectionality); if (hasStrongDirectionality) break; } return isLeftToRightDirection(textDirection) ? CSSValueLtr : CSSValueRtl; }
void TextTrackCue::determineTextDirection() { DEFINE_STATIC_LOCAL(const String, rtTag, (ASCIILiteral("rt"))); createWebVTTNodeTree(); // Apply the Unicode Bidirectional Algorithm's Paragraph Level steps to the // concatenation of the values of each WebVTT Text Object in nodes, in a // pre-order, depth-first traversal, excluding WebVTT Ruby Text Objects and // their descendants. StringBuilder paragraphBuilder; for (Node* node = m_webVTTNodeTree->firstChild(); node; node = NodeTraversal::next(node, m_webVTTNodeTree.get())) { if (!node->isTextNode() || node->localName() == rtTag) continue; paragraphBuilder.append(node->nodeValue()); } String paragraph = paragraphBuilder.toString(); if (!paragraph.length()) return; for (size_t i = 0; i < paragraph.length(); ++i) { UChar current = paragraph[i]; if (!current || isCueParagraphSeparator(current)) return; if (UChar current = paragraph[i]) { WTF::Unicode::Direction charDirection = WTF::Unicode::direction(current); if (charDirection == WTF::Unicode::LeftToRight) { m_displayDirection = CSSValueLtr; return; } if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) { m_displayDirection = CSSValueRtl; return; } } } }
void Element::normalize() { Node* pCur = firstChild(); while (pCur) { if (pCur->nodeType() == Node::ELEMENT_NODE) { pCur->normalize(); } else if (pCur->nodeType() == Node::TEXT_NODE) { Node* pNext = pCur->nextSibling(); while (pNext && pNext->nodeType() == Node::TEXT_NODE) { static_cast<Text*>(pCur)->appendData(pNext->nodeValue()); removeChild(pNext); pNext = pCur->nextSibling(); } } pCur = pCur->nextSibling(); } }
String SmartClip::extractTextFromNode(Node* node) { // Science has proven that no text nodes are ever positioned at y == -99999. int prevYPos = -99999; StringBuilder result; for (Node* currentNode = node; currentNode; currentNode = NodeTraversal::next(*currentNode, node)) { RenderStyle* style = currentNode->computedStyle(); if (style && style->userSelect() == SELECT_NONE) continue; if (Node* nodeFromFrame = nodeInsideFrame(currentNode)) result.append(extractTextFromNode(nodeFromFrame)); IntRect nodeRect = currentNode->pixelSnappedBoundingBox(); if (currentNode->renderer() && !nodeRect.isEmpty()) { if (currentNode->isTextNode()) { String nodeValue = currentNode->nodeValue(); // It's unclear why we blacklist solitary "\n" node values. // Maybe we're trying to ignore <br> tags somehow? if (nodeValue == "\n") nodeValue = ""; if (nodeRect.y() != prevYPos) { prevYPos = nodeRect.y(); result.append('\n'); } result.append(nodeValue); } } } return result.toString(); }
float Tree::value() { return nodePtr->nodeValue(); }
JSValue* JSNode::getValueProperty(ExecState* exec, int token) const { switch (token) { case NodeNameAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->nodeName()); } case NodeValueAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->nodeValue()); } case NodeTypeAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsNumber(exec, imp->nodeType()); } case ParentNodeAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->parentNode())); } case ChildNodesAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->childNodes())); } case FirstChildAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->firstChild())); } case LastChildAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->lastChild())); } case PreviousSiblingAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->previousSibling())); } case NextSiblingAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->nextSibling())); } case AttributesAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->attributes())); } case OwnerDocumentAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->ownerDocument())); } case NamespaceURIAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->namespaceURI()); } case PrefixAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->prefix()); } case LocalNameAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->localName()); } case BaseURIAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->baseURI()); } case TextContentAttrNum: { Node* imp = static_cast<Node*>(impl()); return jsStringOrNull(exec, imp->textContent()); } case ParentElementAttrNum: { Node* imp = static_cast<Node*>(impl()); return toJS(exec, WTF::getPtr(imp->parentElement())); } case ConstructorAttrNum: return getConstructor(exec); } return 0; }
String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove) { OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); // We stop searching after we've seen this many chars const unsigned int charsSearchedThreshold = 500; // This is the absolute max we search. We allow a little more slop than // charsSearchedThreshold, to make it more likely that we'll search whole nodes. const unsigned int maxCharsSearched = 600; // If the starting element is within a table, the cell that contains it HTMLTableCellElement* startingTableCell = 0; bool searchedCellAbove = false; if (resultDistance) *resultDistance = notFound; if (resultIsInCellAbove) *resultIsInCellAbove = false; // walk backwards in the node tree, until another element, or form, or end of tree int unsigned lengthSearched = 0; Node* n; for (n = element->traversePreviousNode(); n && lengthSearched < charsSearchedThreshold; n = n->traversePreviousNode()) { if (n->hasTagName(formTag) || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())) { // We hit another form element or the start of the form - bail out break; } else if (n->hasTagName(tdTag) && !startingTableCell) { startingTableCell = static_cast<HTMLTableCellElement*>(n); } else if (n->hasTagName(trTag) && startingTableCell) { String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); if (!result.isEmpty()) { if (resultIsInCellAbove) *resultIsInCellAbove = true; return result; } searchedCellAbove = true; } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { // For each text chunk, run the regexp String nodeString = n->nodeValue(); // add 100 for slop, to make it more likely that we'll search whole nodes if (lengthSearched + nodeString.length() > maxCharsSearched) nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); int pos = regExp->searchRev(nodeString); if (pos >= 0) { if (resultDistance) *resultDistance = lengthSearched; return nodeString.substring(pos, regExp->matchedLength()); } lengthSearched += nodeString.length(); } } // If we started in a cell, but bailed because we found the start of the form or the // previous element, we still might need to search the row above us for a label. if (startingTableCell && !searchedCellAbove) { String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); if (!result.isEmpty()) { if (resultIsInCellAbove) *resultIsInCellAbove = true; return result; } } return String(); }
static v8::Handle<v8::Value> nodeValueAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Node.nodeValue._get"); Node* imp = V8Node::toNative(info.Holder()); return v8StringOrNull(imp->nodeValue()); }
JSValue JSNamedNodeMap::setNamedItemNS(ExecState* exec, const ArgList& args) { NamedNodeMap* imp = static_cast<NamedNodeMap*>(impl()); ExceptionCode ec = 0; Node* newNode = toNode(args.at(0)); if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) return jsNull(); } JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItemNS(newNode, ec))); setDOMException(exec, ec); return result; }
void ElementTest::testNodeByPathNS() { /* <ns1:root xmlns:ns1="urn:ns1"> <ns1:elem1> <ns2:elemA xmlns:ns2="urn:ns2"/> <ns3:elemA xmlns:ns3="urn:ns2"/> </ns1:elem1> <ns1:elem2> <ns2:elemB ns2:attr1="value1" xmlns:ns2="urn:ns2"/> <ns2:elemB ns2:attr1="value2" xmlns:ns2="urn:ns2"/> <ns2:elemB ns2:attr1="value3" xmlns:ns2="urn:ns2"/> <ns2:elemC ns2:attr1="value1" xmlns:ns2="urn:ns2"> <ns2:elemC1 ns2:attr1="value1"/> <ns2:elemC2/> </ns2:elemC> <ns2:elemC ns2:attr1="value2" xmlns:ns2="urn:ns2"/> </ns1:elem2> </ns1:root> */ AutoPtr<Document> pDoc = new Document; AutoPtr<Element> pRoot = pDoc->createElementNS("urn:ns1", "ns1:root"); AutoPtr<Element> pElem1 = pDoc->createElementNS("urn:ns1", "ns1:elem1"); AutoPtr<Element> pElem11 = pDoc->createElementNS("urn:ns2", "ns2:elemA"); AutoPtr<Element> pElem12 = pDoc->createElementNS("urn:ns2", "ns2:elemA"); AutoPtr<Element> pElem2 = pDoc->createElementNS("urn:ns1", "ns1:elem2"); AutoPtr<Element> pElem21 = pDoc->createElementNS("urn:ns2", "ns2:elemB"); AutoPtr<Element> pElem22 = pDoc->createElementNS("urn:ns2", "ns2:elemB"); AutoPtr<Element> pElem23 = pDoc->createElementNS("urn:ns2", "ns2:elemB"); AutoPtr<Element> pElem24 = pDoc->createElementNS("urn:ns2", "ns2:elemC"); AutoPtr<Element> pElem25 = pDoc->createElementNS("urn:ns2", "ns2:elemC"); pElem21->setAttributeNS("urn:ns2", "ns2:attr1", "value1"); pElem22->setAttributeNS("urn:ns2", "ns2:attr1", "value2"); pElem23->setAttributeNS("urn:ns2", "ns2:attr1", "value3"); pElem24->setAttributeNS("urn:ns2", "ns2:attr1", "value1"); pElem25->setAttributeNS("urn:ns2", "ns2:attr1", "value2"); AutoPtr<Element> pElem241 = pDoc->createElementNS("urn:ns2", "elemC1"); AutoPtr<Element> pElem242 = pDoc->createElementNS("urn:ns2", "elemC2"); pElem241->setAttributeNS("urn:ns2", "ns2:attr1", "value1"); pElem24->appendChild(pElem241); pElem24->appendChild(pElem242); pElem1->appendChild(pElem11); pElem1->appendChild(pElem12); pElem2->appendChild(pElem21); pElem2->appendChild(pElem22); pElem2->appendChild(pElem23); pElem2->appendChild(pElem24); pElem2->appendChild(pElem25); pRoot->appendChild(pElem1); pRoot->appendChild(pElem2); pDoc->appendChild(pRoot); Element::NSMap nsMap; nsMap.declarePrefix("ns1", "urn:ns1"); nsMap.declarePrefix("NS2", "urn:ns2"); Node* pNode = pRoot->getNodeByPathNS("/", nsMap); assert (pNode == pRoot); pNode = pRoot->getNodeByPathNS("/ns1:elem1", nsMap); assert (pNode == pElem1); pNode = pDoc->getNodeByPathNS("/ns1:root/ns1:elem1", nsMap); assert (pNode == pElem1); pNode = pRoot->getNodeByPathNS("/ns1:elem2", nsMap); assert (pNode == pElem2); pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA", nsMap); assert (pNode == pElem11); pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[0]", nsMap); assert (pNode == pElem11); pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[1]", nsMap); assert (pNode == pElem12); pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[2]", nsMap); assert (pNode == 0); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB", nsMap); assert (pNode == pElem21); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[0]", nsMap); assert (pNode == pElem21); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[1]", nsMap); assert (pNode == pElem22); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[2]", nsMap); assert (pNode == pElem23); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[3]", nsMap); assert (pNode == 0); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr1]", nsMap); assert (pNode && pNode->nodeValue() == "value1"); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr2]", nsMap); assert (pNode == 0); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr1='value2']", nsMap); assert (pNode == pElem22); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemC[@NS2:attr1='value1']/NS2:elemC1", nsMap); assert (pNode == pElem241); pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemC[@NS2:attr1='value1']/NS2:elemC1[@NS2:attr1]", nsMap); assert (pNode && pNode->nodeValue() == "value1"); pNode = pRoot->getNodeByPathNS("/NS2:elem1", nsMap); assert (pNode == 0); pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value1']", nsMap); assert (pNode == pElem21); pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value2']", nsMap); assert (pNode == pElem22); pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value3']", nsMap); assert (pNode == pElem23); pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value4']", nsMap); assert (pNode == 0); pNode = pDoc->getNodeByPathNS("//[@NS2:attr1='value1']", nsMap); assert (pNode == pElem21); pNode = pDoc->getNodeByPathNS("//[@NS2:attr1='value2']", nsMap); assert (pNode == pElem22); }
void ElementTest::testNodeByPath() { /* <root> <elem1> <elemA/> <elemA/> </elem1> <elem2> <elemB attr1="value1"/> <elemB attr1="value2"/> <elemB attr1="value3"/> <elemC attr1="value1"> <elemC1 attr1="value1"/> <elemC2/> </elemC> <elemC attr1="value2"/> </elem2> </root> */ AutoPtr<Document> pDoc = new Document; AutoPtr<Element> pRoot = pDoc->createElement("root"); AutoPtr<Element> pElem1 = pDoc->createElement("elem1"); AutoPtr<Element> pElem11 = pDoc->createElement("elemA"); AutoPtr<Element> pElem12 = pDoc->createElement("elemA"); AutoPtr<Element> pElem2 = pDoc->createElement("elem2"); AutoPtr<Element> pElem21 = pDoc->createElement("elemB"); AutoPtr<Element> pElem22 = pDoc->createElement("elemB"); AutoPtr<Element> pElem23 = pDoc->createElement("elemB"); AutoPtr<Element> pElem24 = pDoc->createElement("elemC"); AutoPtr<Element> pElem25 = pDoc->createElement("elemC"); pElem21->setAttribute("attr1", "value1"); pElem22->setAttribute("attr1", "value2"); pElem23->setAttribute("attr1", "value3"); pElem24->setAttribute("attr1", "value1"); pElem25->setAttribute("attr1", "value2"); AutoPtr<Element> pElem241 = pDoc->createElement("elemC1"); AutoPtr<Element> pElem242 = pDoc->createElement("elemC2"); pElem241->setAttribute("attr1", "value1"); pElem24->appendChild(pElem241); pElem24->appendChild(pElem242); pElem1->appendChild(pElem11); pElem1->appendChild(pElem12); pElem2->appendChild(pElem21); pElem2->appendChild(pElem22); pElem2->appendChild(pElem23); pElem2->appendChild(pElem24); pElem2->appendChild(pElem25); pRoot->appendChild(pElem1); pRoot->appendChild(pElem2); pDoc->appendChild(pRoot); Node* pNode = pRoot->getNodeByPath("/"); assert (pNode == pRoot); pNode = pRoot->getNodeByPath("/elem1"); assert (pNode == pElem1); pNode = pDoc->getNodeByPath("/root/elem1"); assert (pNode == pElem1); pNode = pRoot->getNodeByPath("/elem2"); assert (pNode == pElem2); pNode = pRoot->getNodeByPath("/elem1/elemA"); assert (pNode == pElem11); pNode = pRoot->getNodeByPath("/elem1/elemA[0]"); assert (pNode == pElem11); pNode = pRoot->getNodeByPath("/elem1/elemA[1]"); assert (pNode == pElem12); pNode = pRoot->getNodeByPath("/elem1/elemA[2]"); assert (pNode == 0); pNode = pRoot->getNodeByPath("/elem2/elemB"); assert (pNode == pElem21); pNode = pRoot->getNodeByPath("/elem2/elemB[0]"); assert (pNode == pElem21); pNode = pRoot->getNodeByPath("/elem2/elemB[1]"); assert (pNode == pElem22); pNode = pRoot->getNodeByPath("/elem2/elemB[2]"); assert (pNode == pElem23); pNode = pRoot->getNodeByPath("/elem2/elemB[3]"); assert (pNode == 0); pNode = pRoot->getNodeByPath("/elem2/elemB[@attr1]"); assert (pNode && pNode->nodeValue() == "value1"); pNode = pRoot->getNodeByPath("/elem2/elemB[@attr2]"); assert (pNode == 0); pNode = pRoot->getNodeByPath("/elem2/elemB[@attr1='value2']"); assert (pNode == pElem22); pNode = pRoot->getNodeByPath("/elem2/elemC[@attr1='value1']/elemC1"); assert (pNode == pElem241); pNode = pRoot->getNodeByPath("/elem2/elemC[@attr1='value1']/elemC1[@attr1]"); assert (pNode && pNode->nodeValue() == "value1"); pNode = pDoc->getNodeByPath("//elemB[@attr1='value1']"); assert (pNode == pElem21); pNode = pDoc->getNodeByPath("//elemB[@attr1='value2']"); assert (pNode == pElem22); pNode = pDoc->getNodeByPath("//elemB[@attr1='value3']"); assert (pNode == pElem23); pNode = pDoc->getNodeByPath("//elemB[@attr1='value4']"); assert (pNode == 0); pNode = pDoc->getNodeByPath("//[@attr1='value1']"); assert (pNode == pElem21); pNode = pDoc->getNodeByPath("//[@attr1='value2']"); assert (pNode == pElem22); }
/** * Parse incomming message (from server). * @param str Incomming server message * @return Message in Command structure */ Command XMLTool::parseXML(string str) { Command cmd; try { DOMParser parser = DOMParser(0); AutoPtr<Document> pDoc = parser.parseString(str); NodeIterator it(pDoc, NodeFilter::SHOW_ELEMENT); Node* pNode = it.nextNode(); NamedNodeMap* attributes = NULL; Node* attribute = NULL; while (pNode) { if (pNode->nodeName().compare("server_adapter") == 0) { if (pNode->hasAttributes()) { attributes = pNode->attributes(); for(unsigned int i = 0; i < attributes->length(); i++) { attribute = attributes->item(i); if (attribute->nodeName().compare("protocol_version") == 0) { cmd.protocol_version = attribute->nodeValue(); } else if (attribute->nodeName().compare("state") == 0) { cmd.state = attribute->nodeValue(); } // FIXME - id attribute is here only for backward compatibility, it should be removed in Q1/2016 else if (attribute->nodeName().compare("euid") == 0 || attribute->nodeName().compare("id") == 0) { cmd.euid = stoull(attribute->nodeValue(), nullptr, 0); } else if (attribute->nodeName().compare("device_id") == 0) { cmd.device_id = atoll(attribute->nodeValue().c_str()); } else if (attribute->nodeName().compare("time") == 0) { cmd.time = atoll(attribute->nodeValue().c_str()); } else { log.error("Unknow attribute for SERVER_ADAPTER : " + fromXMLString(attribute->nodeName())); } } attributes->release(); } } else if (pNode->nodeName().compare("value") == 0) { if(cmd.state == "getparameters" || cmd.state == "parameters"){ string inner = pNode->innerText(); string device_id = ""; if (pNode->hasAttributes()) { attributes = pNode->attributes(); string device_id = ""; for(unsigned int i = 0; i < attributes->length(); i++) { attribute = attributes->item(i); if (attribute->nodeName().compare("device_id") == 0) { device_id = toNumFromString(attribute->nodeValue()); } } attributes->release(); } cmd.params.value.push_back({inner, device_id}); } else { float val = atof(pNode->innerText().c_str()); if (pNode->hasAttributes()) { int module_id = 0; attributes = pNode->attributes(); for(unsigned int i = 0; i < attributes->length(); i++) { attribute = attributes->item(i); if (attribute->nodeName().compare("module_id") == 0) { module_id = toNumFromString(attribute->nodeValue()); } } cmd.values.push_back({module_id, val}); //TODO Hex number is processed wrongly attributes->release(); } } } else if (pNode->nodeName().compare("parameter") == 0) { if (pNode->hasAttributes()) { attributes = pNode->attributes(); for(unsigned int i = 0; i < attributes->length(); i++) { attribute = attributes->item(i); if (attribute->nodeName().compare("param_id") == 0 || attribute->nodeName().compare("id") == 0) { cmd.params.param_id = toNumFromString(attribute->nodeValue()); } else if (attribute->nodeName().compare("euid") == 0) { cmd.params.euid = toNumFromString(attribute->nodeValue()); } } attributes->release(); } } pNode = it.nextNode(); } } catch (Poco::Exception& e) { log.error("Invalid format of incoming message!" + e.displayText()); cmd.state = "error"; } return cmd; }
int ConfigParser::parse(Poco::XML::Document* xmlDocument, NetworkLayout* networkLayout) { Node* configNode = xmlDocument->firstChild(); if(!configNode || (configNode->nodeName()!=XMLConstants::CONFIG_TAG)){ std::cout << "config.xml: No element with name " << XMLConstants::CONFIG_TAG << " at the appropiate place." << std::endl; exit(1); } Node* trafficNode = configNode->firstChild(); if(!trafficNode || (trafficNode->nodeName()!=XMLConstants::TRAFFIC_TAG)){ std::cout << "config.xml: No element with name " << XMLConstants::TRAFFIC_TAG << " at the appropiate place." << std::endl; exit(1); } int numTrafficNodes = 0; //For each traffic block while (trafficNode != 0) { ConfigContent* content = new ConfigContent(); numTrafficNodes++; //initialize non-mandatory content content->tcp_flags = std::vector<Flags>(); content->tcp_flags.push_back(SYN); content->icmp_type = 0; content->icmp_code = -1; content->dumpPath = std::pair<std::string, bool>("", false); content->destIP = IPAddress(); content->sourceIP = IPAddress(); content->inInterface = ""; content->outInterface = ""; content->numPackets = 1; Node* elementNode = trafficNode->firstChild(); while (elementNode != 0){ //elementNode must be an element node with name XMLConstants::SOURCEIPTAG or XMLConstants::SOURCEPORTTAG or ... if( (elementNode->nodeName()!=XMLConstants::SOURCE_IP_TAG) && (elementNode->nodeName()!=XMLConstants::SOURCE_PORT_TAG) && (elementNode->nodeName()!=XMLConstants::DESTINATION_IP_TAG) && (elementNode->nodeName()!=XMLConstants::DESTINATION_PORT_TAG) && (elementNode->nodeName()!=XMLConstants::PROTOCOL_TAG) && (elementNode->nodeName()!=XMLConstants::TCP_FLAGS_TAG) && (elementNode->nodeName()!=XMLConstants::ICMP_TYPE) && (elementNode->nodeName()!=XMLConstants::ICMP_CODE) && (elementNode->nodeName()!=XMLConstants::POLICY_TAG) && (elementNode->nodeName()!=XMLConstants::IN_INTERFACE_TAG) && (elementNode->nodeName()!=XMLConstants::OUT_INTERFACE_TAG) && (elementNode->nodeName()!=XMLConstants::DUMP_TAG) && (elementNode->nodeName()!=XMLConstants::ASCII_DUMP_TAG) && (elementNode->nodeName()!=XMLConstants::NUM_PACKETS)){ std::cout << "config.xml: XML element " << elementNode->nodeName() << " is not supported." << std::endl; exit(1); } Node* textNode = elementNode->firstChild(); if(!textNode){ std::cout << "config.xml: XML elements must contain something else than whitespace."<<std::endl; exit(1); } if (elementNode->nodeName() == XMLConstants::SOURCE_IP_TAG){ std::string ip = textNode->nodeValue(); removeWhitespace(ip); try { content->sourceIP = IPAddress(ip); } catch (Poco::Exception e) { std::cout << "config.xml: Parsed faulty source IP address" << ip << ": '" << e.message() << "'. Terminating." << std::endl; exit(1); } } else if (elementNode->nodeName() == XMLConstants::SOURCE_PORT_TAG) { if ((content->protocol != UDP) && (content->protocol != TCP)){ std::cout << "config.xml: You can only specify a source port if you have already specified the protocol as tcp or udp." << std::endl; exit(1); } content->sourcePort = atoi(textNode->nodeValue().c_str()); } else if (elementNode->nodeName() == XMLConstants::DESTINATION_IP_TAG) { std::string ip = textNode->nodeValue(); removeWhitespace(ip); try { content->destIP = IPAddress(ip); } catch (Poco::Exception e) { std::cout << "config.xml: Parsed faulty destination IP address " << ip << ": '" << e.message() << "'. Terminating." << std::endl; exit(1); } } else if (elementNode->nodeName() == XMLConstants::DESTINATION_PORT_TAG) { if ((content->protocol != UDP) && (content->protocol != TCP)){ std::cout << "config.xml: You can only specify a destination port if you have already specified the protocol as tcp or udp." << std::endl; exit(1); } content->destPort = atoi(textNode->nodeValue().c_str()); } else if (elementNode->nodeName() == XMLConstants::PROTOCOL_TAG) { ProtocolFactory* factory = ProtocolFactory::getInstance(); content->protocol = factory->parse(textNode->nodeValue()); } else if (elementNode->nodeName() == XMLConstants::TCP_FLAGS_TAG) { if (content->protocol != TCP){ std::cout << "config.xml: You can only specify tcp flags if you have already specified the protocol as tcp." << std::endl; exit(1); } Node* flagNode = elementNode->firstChild(); while (flagNode != 0) { Node* textNode = flagNode->firstChild(); if(!textNode){ std::cout << "config.xml: XML elements must contain something else than whitespace."<<std::endl; exit(1); } std::string value = textNode->getNodeValue(); removeWhitespace(value); if(value == "1") { if (flagNode->nodeName()==XMLConstants::URG_FLAG_TAG) { content->tcp_flags.push_back(URG); } else if (flagNode->nodeName()==XMLConstants::ACK_FLAG_TAG) { content->tcp_flags.push_back(ACK); } else if (flagNode->nodeName()==XMLConstants::PSH_FLAG_TAG) { content->tcp_flags.push_back(PSH); } else if (flagNode->nodeName()==XMLConstants::RST_FLAG_TAG) { content->tcp_flags.push_back(RST); } else if (flagNode->nodeName()==XMLConstants::SYN_FLAG_TAG) { content->tcp_flags.push_back(SYN); } else if (flagNode->nodeName()==XMLConstants::FIN_FLAG_TAG) { content->tcp_flags.push_back(FIN); } else { std::cout << "config.xml: XML element " << flagNode->nodeName() << " is not supported." << std::endl; exit(1); } } else if (value == "0") { if (flagNode->nodeName()==XMLConstants::SYN_FLAG_TAG) { for (std::vector<Flags>::iterator it = content->tcp_flags.begin(); it != content->tcp_flags.end(); it++) { if (*it == SYN) { content->tcp_flags.erase(it); } } } } else if ((flagNode->nodeName()!=XMLConstants::URG_FLAG_TAG) && (flagNode->nodeName()!=XMLConstants::ACK_FLAG_TAG) && (flagNode->nodeName()!=XMLConstants::PSH_FLAG_TAG) && (flagNode->nodeName()!=XMLConstants::RST_FLAG_TAG) && (flagNode->nodeName()!=XMLConstants::SYN_FLAG_TAG) && (flagNode->nodeName()!=XMLConstants::FIN_FLAG_TAG)){ std::cout << "config.xml: XML element " << flagNode->nodeName() << " is not supported as a tcp flag." << std::endl; exit(1); } else { std::cout << "config.xml: Content of XML element " << flagNode->nodeName() << " should be 0 or 1." << std::endl; exit(1); } flagNode = flagNode->nextSibling(); } } else if (elementNode->nodeName() == XMLConstants::ICMP_TYPE) { if (content->protocol != ICMP){ std::cout << "config.xml: You can only specify an icmp type if you have already specified the protocol as icmp." << std::endl; exit(1); } content->icmp_type = atoi(textNode->nodeValue().c_str()); } else if (elementNode->nodeName() == XMLConstants::ICMP_CODE) { if (content->protocol != ICMP){ std::cout << "config.xml: You can only specify an icmp code if you have already specified the protocol as icmp." << std::endl; exit(1); } content->icmp_code = atoi(textNode->nodeValue().c_str()); } else if (elementNode->nodeName() == XMLConstants::POLICY_TAG) { PolicyFactory* factory = PolicyFactory::getInstance(); content->policy = factory->parse(textNode->nodeValue()); } else if (elementNode->nodeName() == XMLConstants::IN_INTERFACE_TAG) { std::string inIf = textNode->nodeValue(); removeWhitespace(inIf); if(!networkLayout->hasInterface(inIf)){ std::cout << "config.xml: You can only specify an in-interface that's specified in network_layout.xml" << std::endl; exit(1); } content->inInterface = inIf; } else if (elementNode->nodeName() == XMLConstants::OUT_INTERFACE_TAG) { std::string outIf = textNode->nodeValue(); removeWhitespace(outIf); if(!networkLayout->hasInterface(outIf)){ std::cout << "config.xml: You can only specify an out-interface that's specified in network_layout.xml" << std::endl; exit(1); } content->outInterface = outIf; } else if (elementNode->nodeName() == XMLConstants::DUMP_TAG) { std::string dumpFile = textNode->nodeValue(); removeWhitespace(dumpFile); std::string path = _path + dumpFile; if(!fileExist(path)){ std::cout << "config.xml: The specified dump file " << textNode->nodeValue() << " is not found in the config folder." << std::endl; exit(1); } content->dumpPath = std::pair<std::string, bool>(path, false); } else if (elementNode->nodeName() == XMLConstants::ASCII_DUMP_TAG) { std::string dumpFile = textNode->nodeValue(); removeWhitespace(dumpFile); std::string path = _path + dumpFile; if(!fileExist(path)){ std::cout << "config.xml: The specified ascii dump file " << textNode->nodeValue() << " is not found in the config folder." << std::endl; exit(1); } content->dumpPath = std::pair<std::string, bool>(path, true); } else if (elementNode->nodeName() == XMLConstants::NUM_PACKETS) { content->numPackets = atoi(textNode->nodeValue().c_str()); } elementNode = elementNode->nextSibling(); } if (content->dumpPath.first!="") { //traffic from dump file detected. if(content->inInterface == "" || content->outInterface == ""){ std::cout << "config.xml: If you specify a " << (content->dumpPath.second?XMLConstants::ASCII_DUMP_TAG:XMLConstants::DUMP_TAG) << ", then you must also specify " << XMLConstants::IN_INTERFACE_TAG << "and " << XMLConstants::OUT_INTERFACE_TAG << "." << std::endl; exit(1); } //check existence of in- and out-interfaces. if (!networkLayout->hasInterface(content->inInterface) || !networkLayout->hasInterface(content->outInterface)){ std::cout << "config.xml: The specified default in- and out-interfaces " << content->inInterface << " and " << content->outInterface << " do not exist within network_layout.xml." << std::endl; exit(1); } checkDump(content->dumpPath, content->inInterface, content->outInterface, networkLayout); } else { //src ip and dst ip must be set if ((content->sourceIP.toString() == "0.0.0.0") || (content->destIP.toString()=="0.0.0.0")){ std::cout << "config.xml: No source or destination IP address specified. Otherwise you have to specify a dump file." << std::endl; exit(1); } //No dump file specified if (networkLayout->isInternal(content->sourceIP.toString(), content->destIP.toString())){ //src and dst if must be set if((content->inInterface=="") || (content->outInterface=="")){ std::cout << "config.xml: INTERN: Based on the specified ip addresses " << content->sourceIP.toString() << " and "<< content->destIP.toString() << ", the packet is classified as internal firewall traffic. You must specify the in- and out-interfaces properly." << std::endl; exit(1); } //check existence of in- and out-interfaces. if (!networkLayout->hasInterface(content->inInterface) || !networkLayout->hasInterface(content->outInterface)){ std::cout << "config.xml: INTERN: The specified in- and out-interfaces " << content->inInterface << " and " << content->outInterface << " do not exist within network_layout.xml." << std::endl; exit(1); } //check source and destination if(content->sourceIP.toString() != networkLayout->getIpAddress(content->outInterface)) { std::cout << "config.xml: INTERN: Source ip address " << content->sourceIP.toString() << " does not correspond to the specified out-interface " << content->outInterface << " (" << networkLayout->getIpAddress(content->outInterface)<< ")" << std::endl; exit(1); } if (content->destIP.toString() != networkLayout->getIpAddress(content->inInterface)){ std::cout << "config.xml: INTERN: Destination ip address " << content->destIP.toString() << " does not correspond to the specified in-interface " << content->inInterface << " (" << networkLayout->getIpAddress(content->inInterface)<< ")" << std::endl; exit(1); } } else if (networkLayout->isOutput(content->sourceIP.toString())){ //src if must be set if(content->outInterface == ""){ std::cout << "config.xml: OUTPUT: Based on the specified ip addresses " << content->sourceIP.toString() << " and "<< content->destIP.toString() << ", the packet is classified as firewall output traffic. You must specify the out-interface properly." << std::endl; exit(1); } //check existence of the out-interface. if (!networkLayout->hasInterface(content->outInterface)){ std::cout << "config.xml: OUTPUT: The specified out-interface " << content->outInterface << " does not exist within network_layout.xml." << std::endl; exit(1); } //check source if(content->sourceIP.toString() != networkLayout->getIpAddress(content->outInterface)){ std::cout << "config.xml: OUTPUT: Source ip address " << content->sourceIP.toString() << " does not correspond to the specified out-interface " << content->outInterface << " (" << networkLayout->getIpAddress(content->outInterface)<< ")" << std::endl; exit(1); } } else if (networkLayout->isInput(content->destIP.toString())) { //dst if must be set if(content->inInterface == ""){ std::cout << "config.xml: INPUT: Based on the specified ip addresses " << content->sourceIP.toString() << " and "<< content->destIP.toString() << ", the packet is classified as firewall input traffic. You must specify the in-interface properly." << std::endl; exit(1); } //check existence of the in-interface. if (!networkLayout->hasInterface(content->inInterface)){ std::cout << "config.xml: INPUT: The specified in-interface " << content->inInterface << " does not exist within network_layout.xml." << std::endl; exit(1); } //check destination if(content->destIP.toString() != networkLayout->getIpAddress(content->inInterface)){ std::cout << "config.xml: INPUT: Destination ip address " << content->destIP.toString() << " does not correspond to the specified in-interface " << content->inInterface << " (" << networkLayout->getIpAddress(content->inInterface)<< ")" << std::endl; exit(1); } } else { //forward //src and dst if must be set if((content->inInterface == "") || (content->outInterface == "")){ std::cout << "config.xml: FORWARD: Based on the specified ip addresses " << content->sourceIP.toString() << " and "<< content->destIP.toString() << ", the packet is classified as forward firewall traffic. You must specify the in- and out-interfaces properly." << std::endl; exit(1); } //check existence of in- and out-interfaces. if (!networkLayout->hasInterface(content->inInterface) || !networkLayout->hasInterface(content->outInterface)){ std::cout << "config.xml: FORWARD: The specified in- and out-interfaces " << content->inInterface << " and " << content->outInterface << " do not exist within network_layout.xml." << std::endl; exit(1); } } } _content.push_back(content); trafficNode = trafficNode->nextSibling(); } return numTrafficNodes; }