Merge branch '5733-implement-XRY-report-parsing' into 5734-implement-XRY-DSP

This commit is contained in:
U-BASIS\dsmyda 2019-11-14 14:30:44 -05:00
commit f7acbe4cb6
5 changed files with 34 additions and 34 deletions

View File

@ -45,7 +45,7 @@ abstract class AbstractSingleKeyValueParser implements XRYFileParser {
@Override @Override
public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException { public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException {
Path reportPath = reader.getReportPath(); Path reportPath = reader.getReportPath();
logger.log(Level.INFO, String.format("XRY DSP: Processing report at [ %s ]", reportPath.toString())); logger.log(Level.INFO, String.format("[XRY DSP] Processing report at [ %s ]", reportPath.toString()));
while (reader.hasNextEntity()) { while (reader.hasNextEntity()) {
String xryEntity = reader.nextEntity(); String xryEntity = reader.nextEntity();
@ -55,7 +55,7 @@ abstract class AbstractSingleKeyValueParser implements XRYFileParser {
//First line of the entity is the title. //First line of the entity is the title.
if (xryLines.length > 0) { if (xryLines.length > 0) {
logger.log(Level.INFO, String.format("XRY DSP: Processing [ %s ]", xryLines[0])); logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ]", xryLines[0]));
} }
String namespace = ""; String namespace = "";
@ -75,7 +75,7 @@ abstract class AbstractSingleKeyValueParser implements XRYFileParser {
//the start of the line and the first delimiter. //the start of the line and the first delimiter.
int keyDelimiter = xryLine.indexOf(KEY_VALUE_DELIMITER); int keyDelimiter = xryLine.indexOf(KEY_VALUE_DELIMITER);
if (keyDelimiter == -1) { if (keyDelimiter == -1) {
logger.log(Level.SEVERE, String.format("XRY DSP: Expected a key value " logger.log(Level.SEVERE, String.format("[XRY DSP] Expected a key value "
+ "pair on this line (in brackets) [ %s ], but one was not detected." + "pair on this line (in brackets) [ %s ], but one was not detected."
+ " Here is the previous line [ %s ]. What does this mean?", xryLine, xryLines[i - 1])); + " Here is the previous line [ %s ]. What does this mean?", xryLine, xryLines[i - 1]));
continue; continue;
@ -84,14 +84,14 @@ abstract class AbstractSingleKeyValueParser implements XRYFileParser {
String value = xryLine.substring(keyDelimiter + 1).trim(); String value = xryLine.substring(keyDelimiter + 1).trim();
if (!isKey(key)) { if (!isKey(key)) {
logger.log(Level.SEVERE, String.format("XRY DSP: The following key, " logger.log(Level.SEVERE, String.format("[XRY DSP] The following key, "
+ "value pair (in brackets, respectively) [ %s ], [ %s ] was not recognized. Discarding..." + "value pair (in brackets, respectively) [ %s ], [ %s ] was not recognized. Discarding..."
+ " Here is the previous line [ %s ] for context. What does this key mean?", key, value, xryLines[i - 1])); + " Here is the previous line [ %s ] for context. What does this key mean?", key, value, xryLines[i - 1]));
continue; continue;
} }
if (value.isEmpty()) { if (value.isEmpty()) {
logger.log(Level.SEVERE, String.format("XRY DSP: The following key " logger.log(Level.SEVERE, String.format("[XRY DSP] The following key "
+ "(in brackets) [ %s ] was recognized, but the value was empty. Discarding..." + "(in brackets) [ %s ] was recognized, but the value was empty. Discarding..."
+ " Here is the previous line for context [ %s ]. What does this mean?", key, xryLines[i - 1])); + " Here is the previous line for context [ %s ]. What does this mean?", key, xryLines[i - 1]));
continue; continue;

View File

@ -89,10 +89,10 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
try { try {
String dateTime = removeDateTimeLocale(value); String dateTime = removeDateTimeLocale(value);
String normalizedDateTime = dateTime.trim(); String normalizedDateTime = dateTime.trim();
long dateTimeInEpoch = calculateMsSinceEpoch(normalizedDateTime); long dateTimeInEpoch = calculateSecondsSinceEpoch(normalizedDateTime);
return new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START, PARSER_NAME, dateTimeInEpoch); return new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START, PARSER_NAME, dateTimeInEpoch);
} catch (DateTimeParseException ex) { } catch (DateTimeParseException ex) {
logger.log(Level.SEVERE, String.format("XRY DSP: Assumption about the date time " logger.log(Level.SEVERE, String.format("[XRY DSP] Assumption about the date time "
+ "formatting of call logs is not right. Here is the value [ %s ]", value), ex); + "formatting of call logs is not right. Here is the value [ %s ]", value), ex);
return null; return null;
} }
@ -167,9 +167,9 @@ final class XRYCallsFileParser extends AbstractSingleKeyValueParser {
* @param dateTime * @param dateTime
* @return * @return
*/ */
private long calculateMsSinceEpoch(String dateTime) { private long calculateSecondsSinceEpoch(String dateTime) {
LocalDateTime localDateTime = LocalDateTime.parse(dateTime, DATE_TIME_PARSER); LocalDateTime localDateTime = LocalDateTime.parse(dateTime, DATE_TIME_PARSER);
//Assume dates have no offset. //Assume dates have no offset.
return localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(); return localDateTime.toInstant(ZoneOffset.UTC).getEpochSecond();
} }
} }

View File

@ -83,7 +83,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
@Override @Override
public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException { public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException {
Path reportPath = reader.getReportPath(); Path reportPath = reader.getReportPath();
logger.log(Level.INFO, String.format("XRY DSP: Processing report at [ %s ]", reportPath.toString())); logger.log(Level.INFO, String.format("[XRY DSP] Processing report at [ %s ]", reportPath.toString()));
while (reader.hasNextEntity()) { while (reader.hasNextEntity()) {
String xryEntity = reader.nextEntity(); String xryEntity = reader.nextEntity();
@ -93,7 +93,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
//First line of the entity is the title. //First line of the entity is the title.
if (xryLines.length > 0) { if (xryLines.length > 0) {
logger.log(Level.INFO, String.format("XRY DSP: Processing [ %s ]", xryLines[0])); logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ]", xryLines[0]));
} }
for (int i = 1; i < xryLines.length; i++) { for (int i = 1; i < xryLines.length; i++) {
@ -101,7 +101,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
//Expecting to see a "Data" key. //Expecting to see a "Data" key.
if (!hasDataKey(xryLine)) { if (!hasDataKey(xryLine)) {
logger.log(Level.SEVERE, String.format("XRY DSP: Expected a 'Data' key " logger.log(Level.SEVERE, String.format("[XRY DSP] Expected a 'Data' key "
+ "on this line (in brackets) [ %s ], but none was found. " + "on this line (in brackets) [ %s ], but none was found. "
+ "Discarding... Here is the previous line for context [ %s ]. " + "Discarding... Here is the previous line for context [ %s ]. "
+ "What does this mean?", xryLine, xryLines[i - 1])); + "What does this mean?", xryLine, xryLines[i - 1]));
@ -109,7 +109,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
} }
if (i + 1 == xryLines.length) { if (i + 1 == xryLines.length) {
logger.log(Level.SEVERE, String.format("XRY DSP: Found a 'Data' key " logger.log(Level.SEVERE, String.format("[XRY DSP] Found a 'Data' key "
+ "but no corresponding 'Attribute' key. Discarding... Here " + "but no corresponding 'Attribute' key. Discarding... Here "
+ "is the 'Data' line (in brackets) [ %s ]. Here is the previous " + "is the 'Data' line (in brackets) [ %s ]. Here is the previous "
+ "line for context [ %s ]. What does this mean?", xryLine, xryLines[i - 1])); + "line for context [ %s ]. What does this mean?", xryLine, xryLines[i - 1]));
@ -123,7 +123,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
//Expecting to see an "Attribute" key //Expecting to see an "Attribute" key
if (!hasAttributeKey(nextXryLine)) { if (!hasAttributeKey(nextXryLine)) {
logger.log(Level.SEVERE, String.format("XRY DSP: Expected an 'Attribute' " logger.log(Level.SEVERE, String.format("[XRY DSP] Expected an 'Attribute' "
+ "key on this line (in brackets) [ %s ], but none was found. " + "key on this line (in brackets) [ %s ], but none was found. "
+ "Discarding... Here is the previous line for context [ %s ]. " + "Discarding... Here is the previous line for context [ %s ]. "
+ "What does this mean?", nextXryLine, xryLine)); + "What does this mean?", nextXryLine, xryLine));
@ -139,7 +139,7 @@ final class XRYDeviceGenInfoFileParser implements XRYFileParser {
//All of the attribute types in the map expect a string. //All of the attribute types in the map expect a string.
attributes.add(new BlackboardAttribute(KEY_TO_TYPE.get(normalizedAttributeValue), PARSER_NAME, dataValue)); attributes.add(new BlackboardAttribute(KEY_TO_TYPE.get(normalizedAttributeValue), PARSER_NAME, dataValue));
} else { } else {
logger.log(Level.SEVERE, String.format("XRY DSP: Attribute type (in brackets) " logger.log(Level.SEVERE, String.format("[XRY DSP] Attribute type (in brackets) "
+ "[ %s ] was not recognized. Discarding... Here is the " + "[ %s ] was not recognized. Discarding... Here is the "
+ "previous line for context [ %s ]. What does this mean?", nextXryLine, xryLine)); + "previous line for context [ %s ]. What does this mean?", nextXryLine, xryLine));
} }

View File

@ -42,7 +42,7 @@ final class XRYFileParserFactory {
throw new IllegalArgumentException("Report type cannot be null"); throw new IllegalArgumentException("Report type cannot be null");
} }
switch (reportType.toLowerCase()) { switch (reportType.trim().toLowerCase()) {
case "calls": case "calls":
return new XRYCallsFileParser(); return new XRYCallsFileParser();
case "contacts/contacts": case "contacts/contacts":

View File

@ -118,7 +118,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
@Override @Override
public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException { public void parse(XRYFileReader reader, Content parent) throws IOException, TskCoreException {
Path reportPath = reader.getReportPath(); Path reportPath = reader.getReportPath();
logger.log(Level.INFO, String.format("XRY DSP: Processing report at [ %s ]", reportPath.toString())); logger.log(Level.INFO, String.format("[XRY DSP] Processing report at [ %s ]", reportPath.toString()));
//Keep track of the reference numbers that have been parsed. //Keep track of the reference numbers that have been parsed.
Set<Integer> referenceNumbersSeen = new HashSet<>(); Set<Integer> referenceNumbersSeen = new HashSet<>();
@ -129,7 +129,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
//First line of the entity is the title. //First line of the entity is the title.
if (xryLines.length > 0) { if (xryLines.length > 0) {
logger.log(Level.INFO, String.format("XRY DSP: Processing [ %s ]", xryLines[0])); logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ]", xryLines[0]));
} }
List<BlackboardAttribute> attributes = new ArrayList<>(); List<BlackboardAttribute> attributes = new ArrayList<>();
@ -147,7 +147,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Find the XRY key on this line. //Find the XRY key on this line.
int keyDelimiter = xryLine.indexOf(KEY_VALUE_DELIMITER); int keyDelimiter = xryLine.indexOf(KEY_VALUE_DELIMITER);
if (keyDelimiter == -1) { if (keyDelimiter == -1) {
logger.log(Level.SEVERE, String.format("XRY DSP: Expected a key value " logger.log(Level.SEVERE, String.format("[XRY DSP] Expected a key value "
+ "pair on this line (in brackets) [ %s ], but one was not detected." + "pair on this line (in brackets) [ %s ], but one was not detected."
+ " Is this the continuation of a previous line?" + " Is this the continuation of a previous line?"
+ " Here is the previous line (in brackets) [ %s ]. " + " Here is the previous line (in brackets) [ %s ]. "
@ -167,7 +167,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
} }
if (!XRY_KEYS.contains(normalizedKey)) { if (!XRY_KEYS.contains(normalizedKey)) {
logger.log(Level.SEVERE, String.format("XRY DSP: The following key, " logger.log(Level.SEVERE, String.format("[XRY DSP] The following key, "
+ "value pair (in brackets, respectively) [ %s ], [ %s ] " + "value pair (in brackets, respectively) [ %s ], [ %s ] "
+ "was not recognized. Discarding... Here is the previous line " + "was not recognized. Discarding... Here is the previous line "
+ "[ %s ] for context. What does this key mean?", key, value, xryLines[i - 1])); + "[ %s ] for context. What does this key mean?", key, value, xryLines[i - 1]));
@ -175,7 +175,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
} }
if (value.isEmpty()) { if (value.isEmpty()) {
logger.log(Level.SEVERE, String.format("XRY DSP: The following key " logger.log(Level.SEVERE, String.format("[XRY DSP] The following key "
+ "(in brackets) [ %s ] was recognized, but the value " + "(in brackets) [ %s ] was recognized, but the value "
+ "was empty. Discarding... Here is the previous line " + "was empty. Discarding... Here is the previous line "
+ "for context [ %s ]. Is this a continuation of this line? " + "for context [ %s ]. Is this a continuation of this line? "
@ -186,7 +186,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Assume text is the only field that can span multiple lines. //Assume text is the only field that can span multiple lines.
if (normalizedKey.equals(TEXT_KEY)) { if (normalizedKey.equals(TEXT_KEY)) {
//Build up multiple lines. //Build up multiple lines.
for (; i + 1 < xryLines.length for (; (i + 1) < xryLines.length
&& !hasKey(xryLines[i + 1]) && !hasKey(xryLines[i + 1])
&& !hasNamespace(xryLines[i + 1]); i++) { && !hasNamespace(xryLines[i + 1]); i++) {
String continuedValue = xryLines[i + 1].trim(); String continuedValue = xryLines[i + 1].trim();
@ -198,15 +198,15 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Check if there is any segmented text. Min val is used to //Check if there is any segmented text. Min val is used to
//signify that no reference number was found. //signify that no reference number was found.
if (referenceNumber != Integer.MIN_VALUE) { if (referenceNumber != Integer.MIN_VALUE) {
logger.log(Level.INFO, String.format("XRY DSP: Message entity " logger.log(Level.INFO, String.format("[XRY DSP] Message entity "
+ "appears to be segmented with reference number [ %d ]", referenceNumber)); + "appears to be segmented with reference number [ %d ]", referenceNumber));
if (referenceNumbersSeen.contains(referenceNumber)) { if (referenceNumbersSeen.contains(referenceNumber)) {
logger.log(Level.SEVERE, "XRY DSP: This reference has already " logger.log(Level.SEVERE, String.format("[XRY DSP] This reference [ %d ] has already "
+ "been seen. This means that the segments are not " + "been seen. This means that the segments are not "
+ "contiguous. Any segments contiguous with this " + "contiguous. Any segments contiguous with this "
+ "one will be aggregated and another " + "one will be aggregated and another "
+ "(otherwise duplicate) artifact will be created."); + "(otherwise duplicate) artifact will be created.", referenceNumber));
} }
referenceNumbersSeen.add(referenceNumber); referenceNumbersSeen.add(referenceNumber);
@ -269,12 +269,12 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Extract the text key from the entity, which is potentially //Extract the text key from the entity, which is potentially
//multi-lined. //multi-lined.
if (nextEntityLines.length > 0) { if (nextEntityLines.length > 0) {
logger.log(Level.INFO, String.format("XRY DSP: Processing [ %s ] " logger.log(Level.INFO, String.format("[XRY DSP] Processing [ %s ] "
+ "segment with reference number [ %d ]", nextEntityLines[0], referenceNumber)); + "segment with reference number [ %d ]", nextEntityLines[0], referenceNumber));
} }
if (nextSegmentNumber != currentSegmentNumber + 1) { if (nextSegmentNumber != currentSegmentNumber + 1) {
logger.log(Level.SEVERE, String.format("XRY DSP: Contiguous " logger.log(Level.SEVERE, String.format("[XRY DSP] Contiguous "
+ "segments are not ascending incrementally. Encountered " + "segments are not ascending incrementally. Encountered "
+ "segment [ %d ] after segment [ %d ]. This means the reconstructed " + "segment [ %d ] after segment [ %d ]. This means the reconstructed "
+ "text will be out of order.", nextSegmentNumber, currentSegmentNumber)); + "text will be out of order.", nextSegmentNumber, currentSegmentNumber));
@ -365,7 +365,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
try { try {
return Integer.parseInt(value); return Integer.parseInt(value);
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
logger.log(Level.SEVERE, String.format("XRY DSP: Value [ %s ] for " logger.log(Level.SEVERE, String.format("[XRY DSP] Value [ %s ] for "
+ "meta key [ %s ] was not an integer.", value, metaKey), ex); + "meta key [ %s ] was not an integer.", value, metaKey), ex);
} }
} }
@ -395,10 +395,10 @@ final class XRYMessagesFileParser implements XRYFileParser {
try { try {
String dateTime = removeDateTimeLocale(value); String dateTime = removeDateTimeLocale(value);
String normalizedDateTime = dateTime.trim(); String normalizedDateTime = dateTime.trim();
long dateTimeInEpoch = calculateMsSinceEpoch(normalizedDateTime); long dateTimeInEpoch = calculateSecondsSinceEpoch(normalizedDateTime);
return new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, PARSER_NAME, dateTimeInEpoch); return new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, PARSER_NAME, dateTimeInEpoch);
} catch (DateTimeParseException ex) { } catch (DateTimeParseException ex) {
logger.log(Level.SEVERE, String.format("XRY DSP: Assumption " logger.log(Level.SEVERE, String.format("[XRY DSP] Assumption "
+ "about the date time formatting of messages is not " + "about the date time formatting of messages is not "
+ "right. Here is the value [ %s ].", value), ex); + "right. Here is the value [ %s ].", value), ex);
return null; return null;
@ -423,7 +423,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Ignore for now. //Ignore for now.
return null; return null;
default: default:
logger.log(Level.SEVERE, String.format("XRY DSP: Unrecognized " logger.log(Level.SEVERE, String.format("[XRY DSP] Unrecognized "
+ "status value [ %s ].", value)); + "status value [ %s ].", value));
return null; return null;
} }
@ -439,7 +439,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
//Ignore for now. //Ignore for now.
return null; return null;
default: default:
logger.log(Level.SEVERE, String.format("XRY DSP: Unrecognized " logger.log(Level.SEVERE, String.format("[XRY DSP] Unrecognized "
+ "type value [ %s ]", value)); + "type value [ %s ]", value));
return null; return null;
} }
@ -495,9 +495,9 @@ final class XRYMessagesFileParser implements XRYFileParser {
* @param dateTime * @param dateTime
* @return * @return
*/ */
private long calculateMsSinceEpoch(String dateTime) { private long calculateSecondsSinceEpoch(String dateTime) {
LocalDateTime localDateTime = LocalDateTime.parse(dateTime, DATE_TIME_PARSER); LocalDateTime localDateTime = LocalDateTime.parse(dateTime, DATE_TIME_PARSER);
//Assume dates have no offset. //Assume dates have no offset.
return localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(); return localDateTime.toInstant(ZoneOffset.UTC).getEpochSecond();
} }
} }