bool MetadataWalker::for_each()

in extensions/windows-event-log/wel/MetadataWalker.cpp [34:107]


bool MetadataWalker::for_each(pugi::xml_node &node) {
  // don't shortcut resolution here so that we can log attributes.
  const auto idUpdate = [&](const std::string &input) {
    if (resolve_) {
      auto resolved = user_id_to_username_fn_(input);
      replaced_identifiers_[input] = resolved;
      return resolved;
    }

    replaced_identifiers_[input] = input;
    return input;
  };
  for (pugi::xml_attribute attr : node.attributes())  {
    if (regex_ && utils::regexMatch(attr.name(), *regex_)) {
      updateAttributeValue(attr, attr.name(), idUpdate);
    }
  }

  const std::string node_name = node.name();
  if (node_name == "Data") {
    for (pugi::xml_attribute attr : node.attributes())  {
      if (regex_ && utils::regexMatch(attr.name(), *regex_)) {
        updateText(node, attr.name(), idUpdate);
      }

      if (regex_ && utils::regexMatch(attr.value(), *regex_)) {
        updateText(node, attr.value(), idUpdate);
      }
    }

    if (resolve_) {
      std::string nodeText = node.text().get();
      std::vector<std::string> ids = getIdentifiers(nodeText);
      for (const auto &id : ids) {
        auto  resolved = user_id_to_username_fn_(id);
        std::string replacement = "%{" + id + "}";
        replaced_identifiers_[id] = resolved;
        replaced_identifiers_[replacement] = resolved;
        nodeText = utils::StringUtils::replaceAll(nodeText, replacement, resolved);
      }
      node.text().set(nodeText.c_str());
    }
  } else if (node_name == "TimeCreated") {
    metadata_["TimeCreated"] = node.attribute("SystemTime").value();
  } else if (node_name == "EventRecordID") {
    metadata_["EventRecordID"] = node.text().get();
  } else if (node_name == "Provider") {
    metadata_["Provider"] = node.attribute("Name").value();
  } else if (node_name == "EventID") {
    metadata_["EventID"] = node.text().get();
  } else {
    static std::map<std::string, EVT_FORMAT_MESSAGE_FLAGS> formatFlagMap = {
        {"Channel", EvtFormatMessageChannel}, {"Keywords", EvtFormatMessageKeyword}, {"Level", EvtFormatMessageLevel},
        {"Opcode", EvtFormatMessageOpcode}, {"Task", EvtFormatMessageTask}
    };
    auto it = formatFlagMap.find(node_name);
    if (it != formatFlagMap.end()) {
      std::function<std::string(const std::string &)> updateFunc = [&](const std::string &input) -> std::string {
        if (resolve_) {
          auto resolved = windows_event_log_metadata_.getEventData(it->second);
          if (!resolved.empty()) {
            return resolved;
          }
        }
        return input;
      };
      updateText(node, node.name(), std::move(updateFunc));
    } else {
      // no conversion is required here, so let the node fall through
    }
  }

  return true;
}