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;
28 import org.
sleuthkit.datamodel.Blackboard.BlackboardException;
34 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper;
35 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper.CallMediaType;
36 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper.CommunicationDirection;
41 final class XRYCallsFileParser
extends AbstractSingleEntityParser {
43 private static final Logger logger = Logger.getLogger(XRYCallsFileParser.class.getName());
50 NAME_MATCHED(
"name (matched)", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME),
58 DELETED(
"deleted", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ISDELETED),
63 NAME(
"name", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
66 private final BlackboardAttribute.ATTRIBUTE_TYPE
type;
68 XryKey(String name, BlackboardAttribute.ATTRIBUTE_TYPE type) {
73 public BlackboardAttribute.ATTRIBUTE_TYPE
getType() {
84 }
catch (IllegalArgumentException ex) {
97 String normalizedKey = key.trim().toLowerCase();
99 if (normalizedKey.equals(keyChoice.name)) {
104 throw new IllegalArgumentException(String.format(
"Key [%s] was not found."
105 +
" All keys should be tested with contains.", key));
127 public static boolean contains(String xryNamespace) {
131 }
catch (IllegalArgumentException ex) {
145 String normalizedNamespace = xryNamespace.trim().toLowerCase();
147 if (normalizedNamespace.equals(keyChoice.name)) {
152 throw new IllegalArgumentException(String.format(
"Key [%s] was not found."
153 +
" All keys should be tested with contains.", xryNamespace));
158 boolean canProcess(XRYKeyValuePair pair) {
159 return XryKey.
contains(pair.getKey());
163 boolean isNamespace(String nameSpace) {
164 return XryNamespace.contains(nameSpace);
168 void makeArtifact(List<XRYKeyValuePair> keyValuePairs, Content parent, SleuthkitCase currentCase)
throws TskCoreException, BlackboardException {
171 String callerId = null;
172 final Collection<String> calleeList =
new ArrayList<>();
173 CommunicationDirection direction = CommunicationDirection.UNKNOWN;
175 final long endTime = 0L;
176 final CallMediaType callType = CallMediaType.UNKNOWN;
177 final Collection<BlackboardAttribute> otherAttributes =
new ArrayList<>();
179 for (XRYKeyValuePair pair : keyValuePairs) {
180 XryKey xryKey = XryKey.fromDisplayName(pair.getKey());
181 XryNamespace xryNamespace = XryNamespace.NONE;
182 if (XryNamespace.contains(pair.getNamespace())) {
183 xryNamespace = XryNamespace.fromDisplayName(pair.getNamespace());
189 if(!XRYUtils.isPhoneValid(pair.getValue())) {
194 if (xryNamespace == XryNamespace.FROM || direction == CommunicationDirection.INCOMING) {
195 callerId = pair.getValue();
196 }
else if (xryNamespace == XryNamespace.TO || direction == CommunicationDirection.OUTGOING) {
197 calleeList.add(pair.getValue());
199 otherAttributes.add(
new BlackboardAttribute(
200 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
201 PARSER_NAME, pair.getValue()));
207 if(!XRYUtils.isPhoneValid(pair.getValue())) {
211 calleeList.add(pair.getValue());
214 if(!XRYUtils.isPhoneValid(pair.getValue())) {
218 callerId = pair.getValue();
223 long dateTimeSinceEpoch = XRYUtils.calculateSecondsSinceEpoch(pair.getValue());
224 startTime = dateTimeSinceEpoch;
225 }
catch (DateTimeParseException ex) {
226 logger.log(Level.WARNING, String.format(
"[XRY DSP] Assumption"
227 +
" about the date time formatting of call logs is "
228 +
"not right. Here is the value [ %s ]", pair.getValue()), ex);
232 String directionString = pair.getValue().toLowerCase();
233 if (directionString.equals(
"incoming")) {
234 direction = CommunicationDirection.INCOMING;
236 direction = CommunicationDirection.OUTGOING;
240 String typeString = pair.getValue();
241 if (typeString.equalsIgnoreCase(
"received")) {
242 direction = CommunicationDirection.INCOMING;
243 }
else if (typeString.equalsIgnoreCase(
"dialed")) {
244 direction = CommunicationDirection.OUTGOING;
250 if (xryKey.getType() != null) {
251 otherAttributes.add(
new BlackboardAttribute(xryKey.getType(),
252 PARSER_NAME, pair.getValue()));
255 logger.log(Level.INFO, String.format(
"[XRY DSP] Key value pair "
256 +
"(in brackets) [ %s ] was recognized but "
257 +
"more data or time is needed to finish implementation. Discarding... ",
266 if (callerId == null && calleeList.isEmpty()
267 || direction == CommunicationDirection.INCOMING && callerId == null
268 || direction == CommunicationDirection.OUTGOING && calleeList.isEmpty()) {
271 if (direction != CommunicationDirection.UNKNOWN) {
272 otherAttributes.add(
new BlackboardAttribute(
273 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION,
274 PARSER_NAME, direction.getDisplayName()));
277 if (startTime > 0L) {
278 otherAttributes.add(
new BlackboardAttribute(
279 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START,
280 PARSER_NAME, startTime));
287 if (callerId != null) {
288 currentCase.getCommunicationsManager().createAccountFileInstance(
289 Account.Type.PHONE, callerId, PARSER_NAME, parent);
291 otherAttributes.add(
new BlackboardAttribute(
292 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
293 PARSER_NAME, callerId));
296 for (String phone : calleeList) {
297 currentCase.getCommunicationsManager().createAccountFileInstance(
298 Account.Type.PHONE, phone, PARSER_NAME, parent);
300 otherAttributes.add(
new BlackboardAttribute(
301 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
302 PARSER_NAME, phone));
305 if (!otherAttributes.isEmpty()) {
306 BlackboardArtifact artifact = parent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG);
307 artifact.addAttributes(otherAttributes);
309 currentCase.getBlackboard().postArtifact(artifact, PARSER_NAME);
314 CommunicationArtifactsHelper helper =
new CommunicationArtifactsHelper(
315 currentCase, PARSER_NAME, parent, Account.Type.PHONE);
317 helper.addCalllog(direction, callerId, calleeList, startTime,
318 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)