http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/ChunkHeader.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/ChunkHeader.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/ChunkHeader.java new file mode 100644 index 0000000..7f01adf --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/ChunkHeader.java @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.primitives.UnsignedInteger; +import com.google.common.primitives.UnsignedLong; +import org.apache.nifi.logging.ComponentLog; +import org.apache.nifi.processors.evtx.parser.bxml.NameStringNode; +import org.apache.nifi.processors.evtx.parser.bxml.TemplateNode; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.CRC32; + +/** + * A Chunk is a self-contained group of templates, strings, and nodes + */ +public class ChunkHeader extends Block { + public static final String ELF_CHNK = "ElfChnk"; + private final String magicString; + private final UnsignedLong fileFirstRecordNumber; + private final UnsignedLong fileLastRecordNumber; + private final UnsignedLong logFirstRecordNumber; + private final UnsignedLong logLastRecordNumber; + private final UnsignedInteger headerSize; + private final UnsignedInteger lastRecordOffset; + private final int nextRecordOffset; + private final UnsignedInteger dataChecksum; + private final String unused; + private final UnsignedInteger headerChecksum; + private final Map<Integer, NameStringNode> nameStrings; + private final Map<Integer, TemplateNode> templateNodes; + private final int chunkNumber; + private final ComponentLog log; + private UnsignedLong recordNumber; + + public ChunkHeader(BinaryReader binaryReader, ComponentLog log, long headerOffset, int chunkNumber) throws IOException { + super(binaryReader, headerOffset); + this.log = log; + this.chunkNumber = chunkNumber; + CRC32 crc32 = new CRC32(); + crc32.update(binaryReader.peekBytes(120)); + + magicString = binaryReader.readString(8); + fileFirstRecordNumber = binaryReader.readQWord(); + fileLastRecordNumber = binaryReader.readQWord(); + logFirstRecordNumber = binaryReader.readQWord(); + logLastRecordNumber = binaryReader.readQWord(); + headerSize = binaryReader.readDWord(); + lastRecordOffset = binaryReader.readDWord(); + nextRecordOffset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid next record offset."); + dataChecksum = binaryReader.readDWord(); + unused = binaryReader.readString(68); + + if (!ELF_CHNK.equals(magicString)) { + throw new IOException("Invalid magic string " + this); + } + + headerChecksum = binaryReader.readDWord(); + + // These are included into the checksum + crc32.update(binaryReader.peekBytes(384)); + + if (crc32.getValue() != headerChecksum.longValue()) { + throw new IOException("Invalid checksum " + this); + } + if (lastRecordOffset.compareTo(UnsignedInteger.valueOf(Integer.MAX_VALUE)) > 0) { + throw new IOException("Last record offset too big to fit into signed integer"); + } + + nameStrings = new HashMap<>(); + for (int i = 0; i < 64; i++) { + int offset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid offset."); + while (offset > 0) { + NameStringNode nameStringNode = new NameStringNode(new BinaryReader(binaryReader, offset), this); + nameStrings.put(offset, nameStringNode); + offset = NumberUtil.intValueMax(nameStringNode.getNextOffset(), Integer.MAX_VALUE, "Invalid offset."); + } + } + + templateNodes = new HashMap<>(); + for (int i = 0; i < 32; i++) { + int offset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid offset."); + while (offset > 0) { + int token = new BinaryReader(binaryReader, offset - 10).read(); + if (token != 0x0c) { + log.warn("Unexpected token when parsing template at offset " + offset); + break; + } + BinaryReader templateReader = new BinaryReader(binaryReader, offset - 4); + int pointer = NumberUtil.intValueMax(templateReader.readDWord(), Integer.MAX_VALUE, "Invalid pointer."); + if (offset != pointer) { + log.warn("Invalid pointer when parsing template at offset " + offset); + break; + } + TemplateNode templateNode = new TemplateNode(templateReader, this); + templateNodes.put(offset, templateNode); + offset = templateNode.getNextOffset(); + } + } + crc32 = new CRC32(); + crc32.update(binaryReader.peekBytes(nextRecordOffset - 512)); + if (crc32.getValue() != dataChecksum.longValue()) { + throw new IOException("Invalid data checksum " + this); + } + recordNumber = fileFirstRecordNumber.minus(UnsignedLong.ONE); + } + + public NameStringNode addNameStringNode(int offset, BinaryReader binaryReader) throws IOException { + NameStringNode nameStringNode = new NameStringNode(binaryReader, this); + nameStrings.put(offset, nameStringNode); + return nameStringNode; + } + + public TemplateNode addTemplateNode(int offset, BinaryReader binaryReader) throws IOException { + TemplateNode templateNode = new TemplateNode(binaryReader, this); + templateNodes.put(offset, templateNode); + return templateNode; + } + + public TemplateNode getTemplateNode(int offset) { + return templateNodes.get(offset); + } + + @Override + public String toString() { + return "ChunkHeader{" + + "magicString='" + magicString + '\'' + + ", fileFirstRecordNumber=" + fileFirstRecordNumber + + ", fileLastRecordNumber=" + fileLastRecordNumber + + ", logFirstRecordNumber=" + logFirstRecordNumber + + ", logLastRecordNumber=" + logLastRecordNumber + + ", headerSize=" + headerSize + + ", lastRecordOffset=" + lastRecordOffset + + ", nextRecordOffset=" + nextRecordOffset + + ", dataChecksum=" + dataChecksum + + ", unused='" + unused + '\'' + + ", headerChecksum=" + headerChecksum + + '}'; + } + + public boolean hasNext() { + return fileLastRecordNumber.compareTo(recordNumber) > 0; + } + + public String getString(int offset) { + NameStringNode nameStringNode = nameStrings.get(offset); + if (nameStringNode == null) { + return null; + } + return nameStringNode.getString(); + } + + @VisibleForTesting + Map<Integer, NameStringNode> getNameStrings() { + return Collections.unmodifiableMap(nameStrings); + } + + @VisibleForTesting + Map<Integer, TemplateNode> getTemplateNodes() { + return Collections.unmodifiableMap(templateNodes); + } + + public int getChunkNumber() { + return chunkNumber; + } + + public Record next() throws IOException { + if (!hasNext()) { + return null; + } + try { + Record record = new Record(getBinaryReader(), this); + recordNumber = record.getRecordNum(); + return record; + } catch (IOException e) { + recordNumber = fileLastRecordNumber; + throw e; + } + } +}
http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeader.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeader.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeader.java new file mode 100644 index 0000000..8610fe9 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeader.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +import com.google.common.primitives.UnsignedInteger; +import com.google.common.primitives.UnsignedLong; +import org.apache.nifi.logging.ComponentLog; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.CRC32; + +/** + * FileHeader at the top of an Evtx file has metadata about the chunks of the file as well as top-level metadata + */ +public class FileHeader extends Block { + public static final int CHUNK_SIZE = 65536; + public static final String ELF_FILE = "ElfFile"; + private final String magicString; + private final UnsignedLong oldestChunk; + private final UnsignedLong currentChunkNumber; + private final UnsignedLong nextRecordNumber; + private final UnsignedInteger headerSize; + private final int minorVersion; + private final int majorVersion; + private final int headerChunkSize; + private final int chunkCount; + private final String unused1; + private final UnsignedInteger flags; + private final UnsignedInteger checksum; + private final InputStream inputStream; + private final ComponentLog log; + private long currentOffset; + private int count = 1; + + public FileHeader(InputStream inputStream, ComponentLog log) throws IOException { + super(new BinaryReader(inputStream, 4096)); + this.log = log; + // Bytes will be checksummed + BinaryReader binaryReader = getBinaryReader(); + CRC32 crc32 = new CRC32(); + crc32.update(binaryReader.peekBytes(120)); + + magicString = binaryReader.readString(8); + if (!ELF_FILE.equals(magicString)) { + throw new IOException("Invalid magic string. Expected " + ELF_FILE + " got " + magicString); + } + oldestChunk = binaryReader.readQWord(); + currentChunkNumber = binaryReader.readQWord(); + nextRecordNumber = binaryReader.readQWord(); + headerSize = binaryReader.readDWord(); + minorVersion = binaryReader.readWord(); + majorVersion = binaryReader.readWord(); + headerChunkSize = binaryReader.readWord(); + chunkCount = binaryReader.readWord(); + unused1 = binaryReader.readString(76); + + // Not part of checksum + flags = binaryReader.readDWord(); + checksum = binaryReader.readDWord(); + + if (crc32.getValue() != checksum.longValue()) { + throw new IOException("Invalid checksum"); + } + NumberUtil.intValueExpected(minorVersion, 1, "Invalid minor version."); + NumberUtil.intValueExpected(majorVersion, 3, "Invalid minor version."); + NumberUtil.intValueExpected(headerChunkSize, 4096, "Invalid header chunk size."); + this.inputStream = inputStream; + currentOffset = 4096; + + init(); + } + + @Override + protected int getHeaderLength() { + return 4096; + } + + public String getMagicString() { + return magicString; + } + + public UnsignedLong getOldestChunk() { + return oldestChunk; + } + + public UnsignedLong getCurrentChunkNumber() { + return currentChunkNumber; + } + + public UnsignedLong getNextRecordNumber() { + return nextRecordNumber; + } + + public UnsignedInteger getHeaderSize() { + return headerSize; + } + + public int getMinorVersion() { + return minorVersion; + } + + public int getMajorVersion() { + return majorVersion; + } + + public int getHeaderChunkSize() { + return headerChunkSize; + } + + public int getChunkCount() { + return chunkCount; + } + + public String getUnused1() { + return unused1; + } + + public UnsignedInteger getFlags() { + return flags; + } + + public UnsignedInteger getChecksum() { + return checksum; + } + + /** + * Tests whether there are more chunks + * @return true iff there are chunks left + */ + public boolean hasNext() { + return count < chunkCount; + } + + /** + * Returns the next chunkHeader or null if there are no more + * + * @return chunkHeader + * @throws MalformedChunkException if there is an error reading the chunk header + * @throws IOException if there is an exception creating the BinaryReader + */ + public ChunkHeader next() throws MalformedChunkException, IOException { + if (count <= chunkCount) { + long currentOffset = this.currentOffset; + this.currentOffset += CHUNK_SIZE; + BinaryReader binaryReader = new BinaryReader(inputStream, CHUNK_SIZE); + try { + return new ChunkHeader(binaryReader, log, currentOffset, count++); + } catch (IOException e) { + throw new MalformedChunkException("Malformed chunk, unable to parse", e, currentOffset, count - 1, binaryReader.getBytes()); + } + } else { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeaderFactory.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeaderFactory.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeaderFactory.java new file mode 100644 index 0000000..a2dbbeb --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/FileHeaderFactory.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +import org.apache.nifi.logging.ComponentLog; + +import java.io.IOException; +import java.io.InputStream; + +public interface FileHeaderFactory { + FileHeader create(InputStream inputStream, ComponentLog componentLog) throws IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/MalformedChunkException.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/MalformedChunkException.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/MalformedChunkException.java new file mode 100644 index 0000000..ab67208 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/MalformedChunkException.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +/** + * Exception when a chunk is malformed. + * Chunks are independent within the file so we should be able to safely continue processing the remaining chunks. + */ +public class MalformedChunkException extends Exception { + private final long offset; + private final int chunkNum; + private byte[] badChunk; + + public MalformedChunkException(String message, Throwable cause, long offset, int chunkNum, byte[] badChunk) { + super(message, cause); + this.offset = offset; + this.chunkNum = chunkNum; + this.badChunk = badChunk; + } + + public byte[] getBadChunk() { + return badChunk; + } + + public int getChunkNum() { + return chunkNum; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/NumberUtil.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/NumberUtil.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/NumberUtil.java new file mode 100644 index 0000000..8f5aeb3 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/NumberUtil.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +import com.google.common.primitives.UnsignedInteger; + +import java.io.IOException; + +/** + * Util methods for conveniently checking numbers + */ +public class NumberUtil { + public static final String EXPECTED_TEXT = " Expected %s got %s."; + + /** + * Throws an exception if the Number isn't what was expected, returning the number if it was + * + * @param number number + * @param expected expected value + * @param errorMessage error message (can be Java format string) + * @param args args for error message format string + * @return the value if it was what was expected + * @throws IOException if the value isn't what was expected + */ + public static int intValueExpected(Number number, int expected, String errorMessage, Object... args) throws IOException { + int result = number.intValue(); + if (result != expected) { + throw createException(errorMessage, args, expected, result); + } + return result; + } + + /** + * Throws an exception if the UnsignedInteger is greater than a given int, returning the int value otherwise + * + * @param unsignedInteger the number + * @param max the maximum value + * @param errorMessage error message (can be Java format string) + * @param args args for error message format string + * @return the value + * @throws IOException if the value is greater than max + */ + public static int intValueMax(UnsignedInteger unsignedInteger, int max, String errorMessage, Object... args) throws IOException { + if (unsignedInteger.compareTo(UnsignedInteger.valueOf(max)) > 0) { + throw createException(errorMessage, args, "< " + max, unsignedInteger); + } + return unsignedInteger.intValue(); + } + + private static IOException createException(String errorMessage, Object[] args, Object expected, Object actual) { + return new IOException(String.format(errorMessage, args) + String.format(EXPECTED_TEXT, expected, actual)); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/Record.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/Record.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/Record.java new file mode 100644 index 0000000..4580c9f --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/Record.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser; + +import com.google.common.primitives.UnsignedLong; +import org.apache.nifi.processors.evtx.parser.bxml.RootNode; + +import java.io.IOException; +import java.util.Date; + +/** + * Individual event, pretty much a wrapper for the RootNode + */ +public class Record extends Block { + private final int magicNumber; + private final int size; + private final UnsignedLong recordNum; + private final Date timestamp; + private final RootNode rootNode; + private final int size2; + + public Record(BinaryReader binaryReader, ChunkHeader chunkHeader) throws IOException { + super(binaryReader, chunkHeader.getOffset() + binaryReader.getPosition()); + magicNumber = NumberUtil.intValueExpected(binaryReader.readDWord(), 10794, "Invalid magic number."); + size = NumberUtil.intValueMax(binaryReader.readDWord(), 0x10000, "Invalid size."); + recordNum = binaryReader.readQWord(); + timestamp = binaryReader.readFileTime(); + rootNode = new RootNode(binaryReader, chunkHeader, null); + int desiredPosition = getInitialPosition() + size - 4; + int skipAmount = desiredPosition - binaryReader.getPosition(); + if (skipAmount > 0) { + binaryReader.skip(skipAmount); + } + size2 = NumberUtil.intValueExpected(binaryReader.readDWord(), size, "Size 2 doesn't match."); + } + + @Override + public String toString() { + return "Record{" + + "magicNumber=" + magicNumber + + ", size=" + size + + ", recordNum=" + recordNum + + ", timestamp=" + timestamp + + ", rootNode=" + rootNode + + ", size2=" + size2 + + '}'; + } + + public UnsignedLong getRecordNum() { + return recordNum; + } + + public RootNode getRootNode() { + return rootNode; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/AttributeNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/AttributeNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/AttributeNode.java new file mode 100644 index 0000000..10aef94 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/AttributeNode.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; + +/** + * Node representing an xml attribute + */ +public class AttributeNode extends BxmlNodeWithTokenAndString { + public AttributeNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + } + + @Override + protected int getMaxChildren() { + return 1; + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } + + public String getAttributeName() { + return getStringValue(); + } + + public BxmlNode getValue() { + return getChildren().get(0); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNode.java new file mode 100644 index 0000000..ec25d82 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNode.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.Block; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Base class that helps initialization by creating children, skipping bytes where necessary + */ +public abstract class BxmlNode extends Block { + public static final int END_OF_STREAM_TOKEN = 0x00; + public static final int OPEN_START_ELEMENT_TOKEN = 0x01; + public static final int CLOSE_START_ELEMENT_TOKEN = 0x02; + public static final int CLOSE_EMPTY_ELEMENT_TOKEN = 0x03; + public static final int CLOSE_ELEMENT_TOKEN = 0x04; + public static final int VALUE_TOKEN = 0x05; + public static final int ATTRIBUTE_TOKEN = 0x06; + public static final int C_DATA_SECTION_TOKEN = 0x07; + public static final int ENTITY_REFERENCE_TOKEN = 0x08; + public static final int PROCESSING_INSTRUCTION_TARGET_TOKEN = 0x0A; + public static final int PROCESSING_INSTRUCTION_DATA_TOKEN = 0x0B; + public static final int TEMPLATE_INSTANCE_TOKEN = 0x0C; + public static final int NORMAL_SUBSTITUTION_TOKEN = 0x0D; + public static final int CONDITIONAL_SUBSTITUTION_TOKEN = 0x0E; + public static final int START_OF_STREAM_TOKEN = 0x0F; + + private static final BxmlNodeFactory[] factories = new BxmlNodeFactory[]{EndOfStreamNode::new, OpenStartElementNode::new, + CloseStartElementNode::new, CloseEmptyElementNode::new, CloseElementNode::new, ValueNode::new, AttributeNode::new, + CDataSectionNode::new, null, EntityReferenceNode::new, ProcessingInstructionTargetNode::new, + ProcessingInstructionDataNode::new, TemplateInstanceNode::new, NormalSubstitutionNode::new, + ConditionalSubstitutionNode::new, StreamStartNode::new}; + private final ChunkHeader chunkHeader; + private final BxmlNode parent; + protected List<BxmlNode> children; + private boolean hasEndOfStream = false; + + protected BxmlNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) { + super(binaryReader, chunkHeader.getOffset() + binaryReader.getPosition()); + this.chunkHeader = chunkHeader; + this.parent = parent; + hasEndOfStream = false; + } + + @Override + protected void init(boolean shouldClearBinaryReader) throws IOException { + super.init(false); + children = Collections.unmodifiableList(initChildren()); + if (shouldClearBinaryReader) { + clearBinaryReader(); + } + } + + protected List<BxmlNode> initChildren() throws IOException { + BinaryReader binaryReader = getBinaryReader(); + List<BxmlNode> result = new ArrayList<>(); + int maxChildren = getMaxChildren(); + int[] endTokens = getEndTokens(); + for (int i = 0; i < maxChildren; i++) { + // Masking flags for location of factory + int token = binaryReader.peek(); + int factoryIndex = token & 0x0F; + if (factoryIndex > factories.length - 1) { + throw new IOException("Invalid token " + factoryIndex); + } + BxmlNodeFactory factory = factories[factoryIndex]; + if (factory == null) { + throw new IOException("Invalid token " + factoryIndex); + } + BxmlNode bxmlNode = factory.create(binaryReader, chunkHeader, this); + result.add(bxmlNode); + if (bxmlNode.hasEndOfStream() || bxmlNode instanceof EndOfStreamNode) { + hasEndOfStream = true; + break; + } + if (Arrays.binarySearch(endTokens, factoryIndex) >= 0) { + break; + } + } + return result; + } + + protected int getMaxChildren() { + return Integer.MAX_VALUE; + } + + protected int[] getEndTokens() { + return new int[]{END_OF_STREAM_TOKEN}; + } + + public List<BxmlNode> getChildren() { + if (!isInitialized()) { + throw new RuntimeException("Need to initialize children"); + } + return children; + } + + public ChunkHeader getChunkHeader() { + return chunkHeader; + } + + public BxmlNode getParent() { + return parent; + } + + public boolean hasEndOfStream() { + return hasEndOfStream; + } + + public abstract void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeFactory.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeFactory.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeFactory.java new file mode 100644 index 0000000..2631fec --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeFactory.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; + +public interface BxmlNodeFactory { + BxmlNode create(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithToken.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithToken.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithToken.java new file mode 100644 index 0000000..0db4ed0 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithToken.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; + +/** + * Common supertype for nodes that begin with a token + */ +public abstract class BxmlNodeWithToken extends BxmlNode { + private final int token; + + public BxmlNodeWithToken(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + token = binaryReader.read(); + } + + public int getToken() { + return token; + } + + public int getFlags() { + return getToken() >> 4; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithTokenAndString.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithTokenAndString.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithTokenAndString.java new file mode 100644 index 0000000..d8d937f --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/BxmlNodeWithTokenAndString.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; +import org.apache.nifi.processors.evtx.parser.NumberUtil; + +import java.io.IOException; + +/** + * Common supertype for nodes that have a token first and then a NameStringNode reference + */ +public abstract class BxmlNodeWithTokenAndString extends BxmlNodeWithToken { + private final int stringOffset; + private final String value; + private final int tagLength; + + public BxmlNodeWithTokenAndString(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + stringOffset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid string offset."); + int tagLength = getBaseTagLength(); + if (stringOffset > getOffset() - chunkHeader.getOffset()) { + int initialPosition = binaryReader.getPosition(); + NameStringNode nameStringNode = chunkHeader.addNameStringNode(stringOffset, binaryReader); + tagLength += binaryReader.getPosition() - initialPosition; + value = nameStringNode.getString(); + } else { + value = chunkHeader.getString(stringOffset); + } + this.tagLength = tagLength; + } + + @Override + protected int getHeaderLength() { + return tagLength; + } + + protected int getBaseTagLength() { + return 5; + } + + public int getStringOffset() { + return stringOffset; + } + + public String getStringValue() { + return value; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CDataSectionNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CDataSectionNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CDataSectionNode.java new file mode 100644 index 0000000..06022cd --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CDataSectionNode.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * CData section + */ +public class CDataSectionNode extends BxmlNodeWithToken { + private final int stringLength; + private final String cdata; + + public CDataSectionNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + if (getFlags() != 0) { + throw new IOException("Invalid flags"); + } + if (getToken() != C_DATA_SECTION_TOKEN) { + throw new IOException("Invalid CDataSectionToken"); + } + stringLength = binaryReader.readWord(); + cdata = binaryReader.readWString(stringLength - 2); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + public String getCdata() { + return cdata; + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseElementNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseElementNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseElementNode.java new file mode 100644 index 0000000..7b2706d --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseElementNode.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Close tag + */ +public class CloseElementNode extends BxmlNodeWithToken { + public CloseElementNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + if ((getFlags() & 0x0F) != 0) { + throw new IOException("Invalid flag"); + } + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseEmptyElementNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseEmptyElementNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseEmptyElementNode.java new file mode 100644 index 0000000..8b22497 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseEmptyElementNode.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Close tag + */ +public class CloseEmptyElementNode extends BxmlNodeWithToken { + public CloseEmptyElementNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseStartElementNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseStartElementNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseStartElementNode.java new file mode 100644 index 0000000..1466718 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/CloseStartElementNode.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Close tag + */ +public class CloseStartElementNode extends BxmlNodeWithToken { + public CloseStartElementNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + if ((getFlags() & 0x0F) != 0) { + throw new IOException("Invalid flag"); + } + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ConditionalSubstitutionNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ConditionalSubstitutionNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ConditionalSubstitutionNode.java new file mode 100644 index 0000000..e9c7358 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ConditionalSubstitutionNode.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Template node marked for substitution with the value the root node has at the given index + */ +public class ConditionalSubstitutionNode extends BxmlNodeWithToken { + private final int index; + private final int type; + + public ConditionalSubstitutionNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + index = binaryReader.readWord(); + type = binaryReader.read(); + if (getFlags() != 0) { + throw new IOException("Invalid flags"); + } + if (getToken() != CONDITIONAL_SUBSTITUTION_TOKEN) { + throw new IOException("Invalid token"); + } + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + public int getIndex() { + return index; + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EndOfStreamNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EndOfStreamNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EndOfStreamNode.java new file mode 100644 index 0000000..25b8298 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EndOfStreamNode.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Node denoting the end of a template + */ +public class EndOfStreamNode extends BxmlNodeWithToken { + public EndOfStreamNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EntityReferenceNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EntityReferenceNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EntityReferenceNode.java new file mode 100644 index 0000000..868651a --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/EntityReferenceNode.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * An escape string node + */ +public class EntityReferenceNode extends BxmlNodeWithTokenAndString { + public EntityReferenceNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } + + public String getValue() { + return "&" + getStringValue() + ";"; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NameStringNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NameStringNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NameStringNode.java new file mode 100644 index 0000000..b92f603 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NameStringNode.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import com.google.common.primitives.UnsignedInteger; +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * The strings are stored separately to conserve space + */ +public class NameStringNode extends BxmlNode { + private final UnsignedInteger nextOffset; + private final int hash; + private final String string; + private final int stringLength; + + public NameStringNode(BinaryReader binaryReader, ChunkHeader chunkHeader) throws IOException { + super(binaryReader, chunkHeader, null); + nextOffset = binaryReader.readDWord(); + hash = binaryReader.readWord(); + stringLength = binaryReader.readWord(); + string = binaryReader.readWString(stringLength); + binaryReader.skip(2); + init(); + } + + public UnsignedInteger getNextOffset() { + return nextOffset; + } + + public int getHash() { + return hash; + } + + public String getString() { + return string; + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NormalSubstitutionNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NormalSubstitutionNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NormalSubstitutionNode.java new file mode 100644 index 0000000..b8e0631 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/NormalSubstitutionNode.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Template node marked for substitution with the value the root node has at the given index + */ +public class NormalSubstitutionNode extends BxmlNodeWithToken { + private final int index; + private final int type; + + public NormalSubstitutionNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + index = binaryReader.readWord(); + type = binaryReader.read(); + if (getFlags() != 0) { + throw new IOException("Invalid flags"); + } + if (getToken() != NORMAL_SUBSTITUTION_TOKEN) { + throw new IOException("Invalid token"); + } + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + public int getIndex() { + return index; + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/OpenStartElementNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/OpenStartElementNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/OpenStartElementNode.java new file mode 100644 index 0000000..55e54eb --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/OpenStartElementNode.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import com.google.common.primitives.UnsignedInteger; +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; +import org.apache.nifi.processors.evtx.parser.NumberUtil; + +import java.io.IOException; + +/** + * Open tag in the template xml + */ +public class OpenStartElementNode extends BxmlNodeWithToken { + private final int unknown; + private final UnsignedInteger size; + private final int stringOffset; + private final String tagName; + private final int tagLength; + + public OpenStartElementNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + if ((getFlags() & 0x0b) != 0) { + throw new IOException("Invalid flag detected"); + } + unknown = binaryReader.readWord(); + size = binaryReader.readDWord(); + stringOffset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid string offset."); + int tagLength = 11; + if ((getFlags() & 0x04) > 0) { + tagLength += 4; + } + String string = getChunkHeader().getString(stringOffset); + if (stringOffset > getOffset() - chunkHeader.getOffset()) { + int initialPosition = binaryReader.getPosition(); + NameStringNode nameStringNode = chunkHeader.addNameStringNode(stringOffset, binaryReader); + tagLength += binaryReader.getPosition() - initialPosition; + tagName = nameStringNode.getString(); + } else { + tagName = string; + } + this.tagLength = tagLength; + init(); + } + + public String getTagName() { + return tagName; + } + + @Override + protected int getHeaderLength() { + return tagLength; + } + + @Override + protected int[] getEndTokens() { + return new int[]{CLOSE_EMPTY_ELEMENT_TOKEN, CLOSE_ELEMENT_TOKEN}; + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionDataNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionDataNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionDataNode.java new file mode 100644 index 0000000..1583ad0 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionDataNode.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class ProcessingInstructionDataNode extends BxmlNodeWithToken { + private final int stringLength; + private final int tagLength; + private final String data; + + public ProcessingInstructionDataNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + stringLength = binaryReader.readWord(); + tagLength = 3 + (2 * stringLength); + if (stringLength > 0) { + data = binaryReader.readWString(stringLength); + } else { + data = ""; + } + init(); + } + + public String getValue() { + return data + "?>"; + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionTargetNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionTargetNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionTargetNode.java new file mode 100644 index 0000000..c47274b --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/ProcessingInstructionTargetNode.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class ProcessingInstructionTargetNode extends BxmlNodeWithTokenAndString { + public ProcessingInstructionTargetNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } + + public String getValue() { + return "<?" + super.getStringValue(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/RootNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/RootNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/RootNode.java new file mode 100644 index 0000000..23108de --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/RootNode.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; +import org.apache.nifi.processors.evtx.parser.NumberUtil; +import org.apache.nifi.processors.evtx.parser.bxml.value.VariantTypeNode; +import org.apache.nifi.processors.evtx.parser.bxml.value.VariantTypeNodeFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Node that contains children and substitutions + */ +public class RootNode extends BxmlNode { + private final int substitutionCount; + private final List<VariantTypeNode> substitutions; + + public RootNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + init(); + substitutionCount = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid substitution count."); + List<VariantTypeSizeAndFactory> substitutionVariantFactories = new ArrayList<>(substitutionCount); + for (long i = 0; i < substitutionCount; i++) { + try { + int substitionSize = binaryReader.readWord(); + int substitutionType = binaryReader.readWord(); + substitutionVariantFactories.add(new VariantTypeSizeAndFactory(substitionSize, ValueNode.factories.get(substitutionType))); + } catch (Exception e) { + throw new IOException(e); + } + } + List<VariantTypeNode> substitutions = new ArrayList<>(); + for (VariantTypeSizeAndFactory substitutionVariantFactory : substitutionVariantFactories) { + substitutions.add(substitutionVariantFactory.factory.create(binaryReader, chunkHeader, this, substitutionVariantFactory.size)); + } + this.substitutions = Collections.unmodifiableList(substitutions); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } + + public List<VariantTypeNode> getSubstitutions() { + return substitutions; + } + + @Override + public String toString() { + return "RootNode{" + getChildren() + "}"; + } + + public class VariantTypeSizeAndFactory { + private final int size; + private final VariantTypeNodeFactory factory; + + public VariantTypeSizeAndFactory(int size, VariantTypeNodeFactory factory) { + this.size = size; + this.factory = factory; + } + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/StreamStartNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/StreamStartNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/StreamStartNode.java new file mode 100644 index 0000000..cda5669 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/StreamStartNode.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; +import org.apache.nifi.processors.evtx.parser.NumberUtil; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Node denoting the beginning of a stream (generally present before the TemplateInstanceNode) + */ +public class StreamStartNode extends BxmlNodeWithToken { + private final int unknown; + private final int unknown2; + + public StreamStartNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + if (getFlags() != 0) { + throw new IOException("Invalid flags"); + } + if (getToken() != START_OF_STREAM_TOKEN) { + throw new IOException("Invalid token " + getToken()); + } + unknown = NumberUtil.intValueExpected(binaryReader.read(), 1, "Unexpected value for unknown field."); + unknown2 = NumberUtil.intValueExpected(binaryReader.readWord(), 1, "Unexpected value for unknown field 2"); + init(); + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a5fecda5/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/TemplateInstanceNode.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/TemplateInstanceNode.java b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/TemplateInstanceNode.java new file mode 100644 index 0000000..0bfa417 --- /dev/null +++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/java/org/apache/nifi/processors/evtx/parser/bxml/TemplateInstanceNode.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.processors.evtx.parser.bxml; + +import com.google.common.primitives.UnsignedInteger; +import org.apache.nifi.processors.evtx.parser.BinaryReader; +import org.apache.nifi.processors.evtx.parser.BxmlNodeVisitor; +import org.apache.nifi.processors.evtx.parser.ChunkHeader; +import org.apache.nifi.processors.evtx.parser.NumberUtil; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * Instance of a Template + */ +public class TemplateInstanceNode extends BxmlNodeWithToken { + + private final int unknown; + private final UnsignedInteger templateId; + private final int templateOffset; + private final boolean isResident; + private final TemplateNode templateNode; + private final int templateLength; + + public TemplateInstanceNode(BinaryReader binaryReader, ChunkHeader chunkHeader, BxmlNode parent) throws IOException { + super(binaryReader, chunkHeader, parent); + unknown = binaryReader.read(); + templateId = binaryReader.readDWord(); + templateOffset = NumberUtil.intValueMax(binaryReader.readDWord(), Integer.MAX_VALUE, "Invalid template offset."); + if (templateOffset > getOffset() - chunkHeader.getOffset()) { + isResident = true; + int initialPosition = binaryReader.getPosition(); + templateNode = chunkHeader.addTemplateNode(templateOffset, binaryReader); + templateLength = binaryReader.getPosition() - initialPosition; + } else { + isResident = false; + templateNode = chunkHeader.getTemplateNode(templateOffset); + templateLength = 0; + } + + if (templateNode != null && !templateId.equals(templateNode.getTemplateId())) { + throw new IOException("Invalid template id"); + } + init(); + } + + @Override + protected int getHeaderLength() { + return 10 + templateLength; + } + + public TemplateNode getTemplateNode() { + return templateNode; + } + + @Override + protected List<BxmlNode> initChildren() throws IOException { + return Collections.emptyList(); + } + + @Override + public boolean hasEndOfStream() { + return super.hasEndOfStream() || templateNode.hasEndOfStream(); + } + + @Override + public void accept(BxmlNodeVisitor bxmlNodeVisitor) throws IOException { + bxmlNodeVisitor.visit(this); + } +}
