19 package org.sleuthkit.autopsy.datasourceprocessors.xry;
21 import java.time.format.DateTimeParseException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.logging.Level;
29 import org.
sleuthkit.datamodel.Blackboard.BlackboardException;
33 import org.
sleuthkit.datamodel.InvalidAccountIDException;
36 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper;
37 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper.CallMediaType;
38 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper.CommunicationDirection;
43 final class XRYCallsFileParser
extends AbstractSingleEntityParser {
45 private static final Logger logger = Logger.getLogger(XRYCallsFileParser.class.getName());
52 NAME_MATCHED(
"name (matched)", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME),
60 DELETED(
"deleted", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ISDELETED),
65 NAME(
"name", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
68 private final BlackboardAttribute.ATTRIBUTE_TYPE
type;
70 XryKey(String name, BlackboardAttribute.ATTRIBUTE_TYPE type) {
75 public BlackboardAttribute.ATTRIBUTE_TYPE
getType() {
86 }
catch (IllegalArgumentException ex) {
99 String normalizedKey = key.trim().toLowerCase();
101 if (normalizedKey.equals(keyChoice.name)) {
106 throw new IllegalArgumentException(String.format(
"Key [%s] was not found."
107 +
" All keys should be tested with contains.", key));
129 public static boolean contains(String xryNamespace) {
133 }
catch (IllegalArgumentException ex) {
147 String normalizedNamespace = xryNamespace.trim().toLowerCase();
149 if (normalizedNamespace.equals(keyChoice.name)) {
154 throw new IllegalArgumentException(String.format(
"Key [%s] was not found."
155 +
" All keys should be tested with contains.", xryNamespace));
160 boolean canProcess(XRYKeyValuePair pair) {
161 return XryKey.
contains(pair.getKey());
165 boolean isNamespace(String nameSpace) {
166 return XryNamespace.contains(nameSpace);
170 void makeArtifact(List<XRYKeyValuePair> keyValuePairs, Content parent, SleuthkitCase currentCase)
throws TskCoreException, BlackboardException {
173 String callerId = null;
174 final Collection<String> calleeList =
new ArrayList<>();
175 CommunicationDirection direction = CommunicationDirection.UNKNOWN;
177 final long endTime = 0L;
178 final CallMediaType callType = CallMediaType.UNKNOWN;
179 final Collection<BlackboardAttribute> otherAttributes =
new ArrayList<>();
181 for (XRYKeyValuePair pair : keyValuePairs) {
182 XryKey xryKey = XryKey.fromDisplayName(pair.getKey());
183 XryNamespace xryNamespace = XryNamespace.NONE;
184 if (XryNamespace.contains(pair.getNamespace())) {
185 xryNamespace = XryNamespace.fromDisplayName(pair.getNamespace());
191 if(!XRYUtils.isPhoneValid(pair.getValue())) {
196 if (xryNamespace == XryNamespace.FROM || direction == CommunicationDirection.INCOMING) {
197 callerId = pair.getValue();
198 }
else if (xryNamespace == XryNamespace.TO || direction == CommunicationDirection.OUTGOING) {
199 calleeList.add(pair.getValue());
201 otherAttributes.add(
new BlackboardAttribute(
202 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
203 PARSER_NAME, pair.getValue()));
209 if(!XRYUtils.isPhoneValid(pair.getValue())) {
213 calleeList.add(pair.getValue());
216 if(!XRYUtils.isPhoneValid(pair.getValue())) {
220 callerId = pair.getValue();
225 long dateTimeSinceEpoch = XRYUtils.calculateSecondsSinceEpoch(pair.getValue());
226 startTime = dateTimeSinceEpoch;
227 }
catch (DateTimeParseException ex) {
228 logger.log(Level.WARNING, String.format(
"[XRY DSP] Assumption"
229 +
" about the date time formatting of call logs is "
230 +
"not right. Here is the value [ %s ]", pair.getValue()), ex);
234 String directionString = pair.getValue().toLowerCase();
235 if (directionString.equals(
"incoming")) {
236 direction = CommunicationDirection.INCOMING;
238 direction = CommunicationDirection.OUTGOING;
242 String typeString = pair.getValue();
243 if (typeString.equalsIgnoreCase(
"received")) {
244 direction = CommunicationDirection.INCOMING;
245 }
else if (typeString.equalsIgnoreCase(
"dialed")) {
246 direction = CommunicationDirection.OUTGOING;
252 if (xryKey.getType() != null) {
253 otherAttributes.add(
new BlackboardAttribute(xryKey.getType(),
254 PARSER_NAME, pair.getValue()));
257 logger.log(Level.INFO, String.format(
"[XRY DSP] Key value pair "
258 +
"(in brackets) [ %s ] was recognized but "
259 +
"more data or time is needed to finish implementation. Discarding... ",
268 if (callerId == null && calleeList.isEmpty()
269 || direction == CommunicationDirection.INCOMING && callerId == null
270 || direction == CommunicationDirection.OUTGOING && calleeList.isEmpty()) {
273 if (direction != CommunicationDirection.UNKNOWN) {
274 otherAttributes.add(
new BlackboardAttribute(
275 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION,
276 PARSER_NAME, direction.getDisplayName()));
279 if (startTime > 0L) {
280 otherAttributes.add(
new BlackboardAttribute(
281 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START,
282 PARSER_NAME, startTime));
289 if (callerId != null) {
291 currentCase.getCommunicationsManager().createAccountFileInstance(
292 Account.Type.PHONE, callerId, PARSER_NAME, parent);
293 }
catch (InvalidAccountIDException ex) {
294 logger.log(Level.WARNING, String.format(
"Invalid account identifier %s", callerId), ex);
297 otherAttributes.add(
new BlackboardAttribute(
298 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
299 PARSER_NAME, callerId));
302 for (String phone : calleeList) {
304 currentCase.getCommunicationsManager().createAccountFileInstance(
305 Account.Type.PHONE, phone, PARSER_NAME, parent);
306 }
catch (InvalidAccountIDException ex) {
307 logger.log(Level.WARNING, String.format(
"Invalid account identifier %s", phone), ex);
311 otherAttributes.add(
new BlackboardAttribute(
312 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
313 PARSER_NAME, phone));
316 if (!otherAttributes.isEmpty()) {
317 BlackboardArtifact artifact = parent.newDataArtifact(
new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG), otherAttributes);
319 currentCase.getBlackboard().postArtifact(artifact, PARSER_NAME);
324 CommunicationArtifactsHelper helper =
new CommunicationArtifactsHelper(
325 currentCase, PARSER_NAME, parent, Account.Type.PHONE);
327 helper.addCalllog(direction, callerId, calleeList, startTime,
328 endTime, callType, otherAttributes);
BlackboardAttribute.ATTRIBUTE_TYPE getType()
static boolean contains(String xryNamespace)
final BlackboardAttribute.ATTRIBUTE_TYPE type
static XryKey fromDisplayName(String key)
static XryNamespace fromDisplayName(String xryNamespace)
XryKey(String name, BlackboardAttribute.ATTRIBUTE_TYPE type)
XryNamespace(String name)
static boolean contains(String key)