1 /*
2  * Sleuth Kit CASE JSON LD Support
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	 http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.caseuco;
20 
21 import com.google.gson.Gson;
22 import com.google.gson.JsonElement;
23 
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Properties;
28 
29 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
30 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED;
31 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
32 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EXTRACTED_TEXT;
33 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO;
34 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT;
35 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG;
36 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
37 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
38 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF;
39 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT;
40 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO;
41 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT;
42 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT;
43 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
44 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE;
45 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
46 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY;
47 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY;
48 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT;
49 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER;
50 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING;
51 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CALENDAR_ENTRY;
52 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG;
53 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE;
54 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_INFO;
55 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED;
56 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED;
57 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK;
58 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION;
59 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE;
60 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH;
61 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT;
62 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED;
63 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN;
64 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_REMOTE_DRIVE;
65 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_SIM_ATTACHED;
66 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY;
67 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED;
68 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK;
69 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER;
70 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CLIPBOARD_CONTENT;
71 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK;
72 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA;
73 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_TL_EVENT;
74 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED;
75 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE;
76 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS;
77 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
78 
79 import org.sleuthkit.datamodel.ContentTag;
80 import org.sleuthkit.datamodel.DataSource;
81 import org.sleuthkit.datamodel.FileSystem;
82 import org.sleuthkit.datamodel.Image;
83 import org.sleuthkit.datamodel.Pool;
84 import org.sleuthkit.datamodel.Volume;
85 import org.sleuthkit.datamodel.VolumeSystem;
86 import org.sleuthkit.datamodel.AbstractFile;
87 import org.sleuthkit.datamodel.BlackboardArtifact;
88 import org.sleuthkit.datamodel.BlackboardAttribute;
89 import org.sleuthkit.datamodel.TimelineEventType;
90 import org.sleuthkit.datamodel.TskCoreException;
91 import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
92 import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints;
93 import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments;
94 import org.sleuthkit.datamodel.SleuthkitCase;
95 import org.sleuthkit.datamodel.TskData.DbType;
96 
97 /**
98  * Exports Sleuth Kit DataModel objects to CASE. The CASE JSON output is
99  * configured to be serialized with Gson. Each export method will produce a list
100  * of CASE JSON objects. Clients should loop through this list and write these
101  * objects to any OutputStream via Gson. See the Gson documentation for more
102  * information on object serialization.
103  *
104  * NOTE: The exporter behavior can be configured by passing configuration
105  * parameters in a custom Properties instance. A list of available configuration
106  * properties can be found in the README.md file.
107  */
108 public class CaseUcoExporter {
109 
110     private static final String INCLUDE_PARENT_CHILD_RELATIONSHIPS_PROP = "exporter.relationships.includeParentChild";
111     private static final String DEFAULT_PARENT_CHILD_RELATIONSHIPS_VALUE = "true";
112 
113     private final Gson gson;
114 
115     private final SleuthkitCase sleuthkitCase;
116     private CaseUcoUUIDService uuidService;
117 
118     private Properties props;
119 
120     /**
121      * Creates a default CaseUcoExporter.
122      *
123      * @param sleuthkitCase The sleuthkit case instance containing the data to
124      * be exported.
125      */
CaseUcoExporter(SleuthkitCase sleuthkitCase)126     public CaseUcoExporter(SleuthkitCase sleuthkitCase) {
127         this(sleuthkitCase, new Properties());
128     }
129 
130     /**
131      * Creates a CaseUcoExporter configured to the properties present in the
132      * Properties instance.
133      *
134      * A list of available configuration properties can be found in the
135      * README.md file.
136      *
137      * @param sleuthkitCase The sleuthkit case instance containing the data to
138      * be exported.
139      * @param props Properties instance containing supported configuration
140      * parameters.
141      */
CaseUcoExporter(SleuthkitCase sleuthkitCase, Properties props)142     public CaseUcoExporter(SleuthkitCase sleuthkitCase, Properties props) {
143         this.sleuthkitCase = sleuthkitCase;
144         this.props = props;
145         this.setUUIDService(new CaseUcoUUIDServiceImpl(sleuthkitCase));
146         this.gson = new Gson();
147     }
148 
149     /**
150      * Overrides the default UUID implementation, which is used to generate the
151      * unique @id properties in the CASE output. Some use cases may require a
152      * different value for @id, such as a web service (where this value should
153      * contain a URL).
154      *
155      * @param uuidService A custom UUID implementation, which will be used to
156      * generate @id values in all export methods.
157      *
158      * @return reference to this, for chaining configuration method calls.
159      */
setUUIDService(CaseUcoUUIDService uuidService)160     public final CaseUcoExporter setUUIDService(CaseUcoUUIDService uuidService) {
161         this.uuidService = uuidService;
162         return this;
163     }
164 
165     /**
166      * Exports the SleuthkitCase instance passed during initialization to CASE.
167      *
168      * @return A collection of CASE JSON elements
169      *
170      * @throws TskCoreException If an error occurred during database access.
171      */
exportSleuthkitCase()172     public List<JsonElement> exportSleuthkitCase() throws TskCoreException {
173         List<JsonElement> output = new ArrayList<>();
174 
175         String caseDirPath = sleuthkitCase
176                 .getDbDirPath()
177                 .replaceAll("\\\\", "/");
178 
179         Trace export = new Trace(this.uuidService.createUUID(sleuthkitCase));
180 
181         if (sleuthkitCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
182             export.addBundle(new File()
183                     .setFilePath(caseDirPath)
184                     .setIsDirectory(true));
185         } else {
186             export.addBundle(new File()
187                     .setFilePath(caseDirPath + "/" + sleuthkitCase.getDatabaseName())
188                     .setIsDirectory(false));
189         }
190 
191         addToOutput(export, output);
192         return output;
193     }
194 
195     /**
196      * Exports an AbstractFile instance to CASE.
197      *
198      * @param file AbstractFile instance to export
199      * @return A collection of CASE JSON elements
200      *
201      * @throws TskCoreException If an error occurred during database access.
202      */
exportAbstractFile(AbstractFile file)203     public List<JsonElement> exportAbstractFile(AbstractFile file) throws TskCoreException {
204         return exportAbstractFile(file, null);
205     }
206 
207     /**
208      * Exports an AbstractFile instance to CASE.
209      *
210      * @param file AbstractFile instance to export
211      * @param localPath The location of the file on secondary storage, somewhere
212      * other than the case. Example: local disk. This value will be ignored if
213      * null
214      * @return A collection of CASE JSON elements
215      *
216      * @throws TskCoreException If an error occurred during database access.
217      */
exportAbstractFile(AbstractFile file, String localPath)218     public List<JsonElement> exportAbstractFile(AbstractFile file, String localPath) throws TskCoreException {
219         List<JsonElement> output = new ArrayList<>();
220 
221         ContentData contentData = new ContentData()
222                 .setMimeType(file.getMIMEType())
223                 .setSizeInBytes(file.getSize())
224                 .setMd5Hash(file.getMd5Hash());
225 
226         if (localPath != null) {
227             Trace localPathTrace = new BlankTraceNode()
228                     .addBundle(new URL()
229                             .setFullValue(localPath));
230             contentData.setDataPayloadReferenceUrl(localPathTrace);
231 
232             addToOutput(localPathTrace, output);
233         }
234 
235         File fileExport = new File()
236                 .setAccessedTime(file.getAtime())
237                 .setExtension(file.getNameExtension())
238                 .setFileName(file.getName())
239                 .setFilePath(file.getUniquePath())
240                 .setIsDirectory(file.isDir())
241                 .setSizeInBytes(file.getSize());
242         fileExport.setModifiedTime(file.getMtime());
243         fileExport.setCreatedTime(file.getCrtime());
244 
245         Trace export = new Trace(this.uuidService.createUUID(file))
246                 .addBundle(contentData)
247                 .addBundle(fileExport);
248 
249         addToOutput(export, output);
250         addParentChildRelationship(output, export.getId(),
251                 this.uuidService.createUUID(file.getDataSource()));
252 
253         return output;
254     }
255 
256     /**
257      * Exports a ContentTag instance to CASE.
258      *
259      * @param contentTag ContentTag instance to export
260      * @return A collection of CASE JSON elements
261      * @throws TskCoreException If an error occurred during database access.
262      */
exportContentTag(ContentTag contentTag)263     public List<JsonElement> exportContentTag(ContentTag contentTag) throws TskCoreException {
264         List<JsonElement> output = new ArrayList<>();
265 
266         Annotation annotation = new Annotation(this.uuidService.createUUID(contentTag))
267                 .addObject(this.uuidService.createUUID(contentTag.getContent()));
268         annotation.setDescription(contentTag.getComment());
269         annotation.addTag(contentTag.getName().getDisplayName());
270 
271         addToOutput(annotation, output);
272         return output;
273     }
274 
275     /**
276      * Exports a DataSource instance to CASE.
277      *
278      * @param dataSource DataSource instance to export
279      * @return A collection of CASE JSON elements
280      * @throws TskCoreException If an error occurred during database access.
281      */
exportDataSource(DataSource dataSource)282     public List<JsonElement> exportDataSource(DataSource dataSource) throws TskCoreException {
283         List<JsonElement> output = new ArrayList<>();
284 
285         Trace export = new Trace(this.uuidService.createUUID(dataSource))
286                 .addBundle(new File()
287                         .setFilePath(getDataSourcePath(dataSource)))
288                 .addBundle(new ContentData()
289                         .setSizeInBytes(dataSource.getSize()));
290 
291         addToOutput(export, output);
292         addParentChildRelationship(output, export.getId(),
293                 this.uuidService.createUUID(this.sleuthkitCase));
294 
295         return output;
296     }
297 
getDataSourcePath(DataSource dataSource)298     String getDataSourcePath(DataSource dataSource) {
299         String dataSourcePath = "";
300         if (dataSource instanceof Image) {
301             String[] paths = ((Image) dataSource).getPaths();
302             if (paths.length > 0) {
303                 dataSourcePath = paths[0];
304             }
305         } else {
306             dataSourcePath = dataSource.getName();
307         }
308         dataSourcePath = dataSourcePath.replaceAll("\\\\", "/");
309         return dataSourcePath;
310     }
311 
312     /**
313      * Exports a FileSystem instance to CASE.
314      *
315      * @param fileSystem FileSystem instance to export
316      * @return A collection of CASE JSON elements
317      * @throws TskCoreException If an error occurred during database access.
318      */
exportFileSystem(FileSystem fileSystem)319     public List<JsonElement> exportFileSystem(FileSystem fileSystem) throws TskCoreException {
320         List<JsonElement> output = new ArrayList<>();
321 
322         Trace export = new Trace(this.uuidService.createUUID(fileSystem))
323                 .addBundle(new org.sleuthkit.caseuco.FileSystem()
324                         .setFileSystemType(fileSystem.getFsType())
325                         .setCluserSize(fileSystem.getBlock_size()));
326 
327         addToOutput(export, output);
328         addParentChildRelationship(output, export.getId(),
329                 this.uuidService.createUUID(fileSystem.getParent()));
330 
331         return output;
332     }
333 
334     /**
335      * Exports a Pool instance to CASE.
336      *
337      * @param pool Pool instance to export
338      * @return A collection of CASE JSON elements
339      *
340      * @throws TskCoreException If an error occurred during database access.
341      */
exportPool(Pool pool)342     public List<JsonElement> exportPool(Pool pool) throws TskCoreException {
343         List<JsonElement> output = new ArrayList<>();
344 
345         Trace export = new Trace(this.uuidService.createUUID(pool))
346                 .addBundle(new ContentData()
347                         .setSizeInBytes(pool.getSize()));
348 
349         addToOutput(export, output);
350         addParentChildRelationship(output, export.getId(),
351                 this.uuidService.createUUID(pool.getParent()));
352 
353         return output;
354     }
355 
356     /**
357      * Exports a Volume instance to CASE.
358      *
359      * @param volume Volume instance to export
360      * @return A collection of CASE JSON elements
361      * @throws TskCoreException If an error occurred during database access.
362      */
exportVolume(Volume volume)363     public List<JsonElement> exportVolume(Volume volume) throws TskCoreException {
364         List<JsonElement> output = new ArrayList<>();
365 
366         Trace export = new Trace(this.uuidService.createUUID(volume));
367         org.sleuthkit.caseuco.Volume volumeFacet = new org.sleuthkit.caseuco.Volume();
368         if (volume.getLength() > 0) {
369             volumeFacet.setSectorSize(volume.getSize() / volume.getLength());
370         }
371         export.addBundle(volumeFacet)
372                 .addBundle(new ContentData()
373                         .setSizeInBytes(volume.getSize()));
374 
375         addToOutput(export, output);
376         addParentChildRelationship(output, export.getId(),
377                 this.uuidService.createUUID(volume.getParent()));
378 
379         return output;
380 
381     }
382 
383     /**
384      * Exports a VolumeSystem instance to CASE.
385      *
386      * @param volumeSystem VolumeSystem instance to export
387      * @return A collection of CASE JSON elements
388      *
389      * @throws TskCoreException If an error occurred during database access.
390      */
exportVolumeSystem(VolumeSystem volumeSystem)391     public List<JsonElement> exportVolumeSystem(VolumeSystem volumeSystem) throws TskCoreException {
392         List<JsonElement> output = new ArrayList<>();
393 
394         Trace export = new Trace(this.uuidService.createUUID(volumeSystem))
395                 .addBundle(new ContentData()
396                         .setSizeInBytes(volumeSystem.getSize()));
397 
398         addToOutput(export, output);
399         addParentChildRelationship(output, export.getId(),
400                 this.uuidService.createUUID(volumeSystem.getParent()));
401 
402         return output;
403     }
404 
405     /**
406      * Exports a BlackboardArtifact instance to CASE.
407      *
408      * @param artifact BlackboardArtifact instance to export
409      * @return A collection of CASE JSON elements
410      *
411      * @throws TskCoreException If an error occurred during database access.
412      * @throws ContentNotExportableException if the content could not be
413      * exported, even in part, to CASE.
414      * @throws BlackboardJsonAttrUtil.InvalidJsonException If a JSON valued
415      * attribute could not be correctly deserialized.
416      */
exportBlackboardArtifact(BlackboardArtifact artifact)417     public List<JsonElement> exportBlackboardArtifact(BlackboardArtifact artifact) throws TskCoreException,
418             ContentNotExportableException, BlackboardJsonAttrUtil.InvalidJsonException {
419         List<JsonElement> output = new ArrayList<>();
420 
421         String uuid = this.uuidService.createUUID(artifact);
422         int artifactTypeId = artifact.getArtifactTypeID();
423 
424         if (TSK_GEN_INFO.getTypeID() == artifactTypeId) {
425             assembleGenInfo(uuid, artifact, output);
426         } else if (TSK_WEB_BOOKMARK.getTypeID() == artifactTypeId) {
427             assembleWebBookmark(uuid, artifact, output);
428         } else if (TSK_WEB_COOKIE.getTypeID() == artifactTypeId) {
429             assembleWebCookie(uuid, artifact, output);
430         } else if (TSK_WEB_HISTORY.getTypeID() == artifactTypeId) {
431             assembleWebHistory(uuid, artifact, output);
432         } else if (TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeId) {
433             assembleWebDownload(uuid, artifact, output);
434         } else if (TSK_RECENT_OBJECT.getTypeID() == artifactTypeId) {
435             assembleRecentObject(uuid, artifact, output);
436         } else if (TSK_INSTALLED_PROG.getTypeID() == artifactTypeId) {
437             assembleInstalledProg(uuid, artifact, output);
438         } else if (TSK_HASHSET_HIT.getTypeID() == artifactTypeId) {
439             assembleHashsetHit(uuid, artifact, output);
440         } else if (TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeId) {
441             assembleDeviceAttached(uuid, artifact, output);
442         } else if (TSK_INTERESTING_FILE_HIT.getTypeID() == artifactTypeId) {
443             assembleInterestingFileHit(uuid, artifact, output);
444         } else if (TSK_EMAIL_MSG.getTypeID() == artifactTypeId) {
445             assembleEmailMessage(uuid, artifact, output);
446         } else if (TSK_EXTRACTED_TEXT.getTypeID() == artifactTypeId) {
447             assembleExtractedText(uuid, artifact, output);
448         } else if (TSK_WEB_SEARCH_QUERY.getTypeID() == artifactTypeId) {
449             assembleWebSearchQuery(uuid, artifact, output);
450         } else if (TSK_METADATA_EXIF.getTypeID() == artifactTypeId) {
451             assembleMetadataExif(uuid, artifact, output);
452         } else if (TSK_OS_INFO.getTypeID() == artifactTypeId) {
453             assembleOsInfo(uuid, artifact, output);
454         } else if (TSK_OS_ACCOUNT.getTypeID() == artifactTypeId) {
455             assembleOsAccount(uuid, artifact, output);
456         } else if (TSK_SERVICE_ACCOUNT.getTypeID() == artifactTypeId) {
457             assembleServiceAccount(uuid, artifact, output);
458         } else if (TSK_CONTACT.getTypeID() == artifactTypeId) {
459             assembleContact(uuid, artifact, output);
460         } else if (TSK_MESSAGE.getTypeID() == artifactTypeId) {
461             assembleMessage(uuid, artifact, output);
462         } else if (TSK_CALLLOG.getTypeID() == artifactTypeId) {
463             assembleCallog(uuid, artifact, output);
464         } else if (TSK_CALENDAR_ENTRY.getTypeID() == artifactTypeId) {
465             assembleCalendarEntry(uuid, artifact, output);
466         } else if (TSK_SPEED_DIAL_ENTRY.getTypeID() == artifactTypeId) {
467             assembleSpeedDialEntry(uuid, artifact, output);
468         } else if (TSK_BLUETOOTH_PAIRING.getTypeID() == artifactTypeId) {
469             assembleBluetoothPairing(uuid, artifact, output);
470         } else if (TSK_GPS_BOOKMARK.getTypeID() == artifactTypeId) {
471             assembleGpsBookmark(uuid, artifact, output);
472         } else if (TSK_GPS_LAST_KNOWN_LOCATION.getTypeID() == artifactTypeId) {
473             assembleGpsLastKnownLocation(uuid, artifact, output);
474         } else if (TSK_GPS_SEARCH.getTypeID() == artifactTypeId) {
475             assembleGpsSearch(uuid, artifact, output);
476         } else if (TSK_PROG_RUN.getTypeID() == artifactTypeId) {
477             assembleProgRun(uuid, artifact, output);
478         } else if (TSK_ENCRYPTION_DETECTED.getTypeID() == artifactTypeId) {
479             assembleEncryptionDetected(uuid, artifact, output);
480         } else if (TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifactTypeId) {
481             assembleInterestingArtifact(uuid, artifact, output);
482         } else if (TSK_GPS_ROUTE.getTypeID() == artifactTypeId) {
483             assembleGPSRoute(uuid, artifact, output);
484         } else if (TSK_REMOTE_DRIVE.getTypeID() == artifactTypeId) {
485             assembleRemoteDrive(uuid, artifact, output);
486         } else if (TSK_ACCOUNT.getTypeID() == artifactTypeId) {
487             assembleAccount(uuid, artifact, output);
488         } else if (TSK_ENCRYPTION_SUSPECTED.getTypeID() == artifactTypeId) {
489             assembleEncryptionSuspected(uuid, artifact, output);
490         } else if (TSK_OBJECT_DETECTED.getTypeID() == artifactTypeId) {
491             assembleObjectDetected(uuid, artifact, output);
492         } else if (TSK_WIFI_NETWORK.getTypeID() == artifactTypeId) {
493             assembleWifiNetwork(uuid, artifact, output);
494         } else if (TSK_DEVICE_INFO.getTypeID() == artifactTypeId) {
495             assembleDeviceInfo(uuid, artifact, output);
496         } else if (TSK_SIM_ATTACHED.getTypeID() == artifactTypeId) {
497             assembleSimAttached(uuid, artifact, output);
498         } else if (TSK_BLUETOOTH_ADAPTER.getTypeID() == artifactTypeId) {
499             assembleBluetoothAdapter(uuid, artifact, output);
500         } else if (TSK_WIFI_NETWORK_ADAPTER.getTypeID() == artifactTypeId) {
501             assembleWifiNetworkAdapter(uuid, artifact, output);
502         } else if (TSK_VERIFICATION_FAILED.getTypeID() == artifactTypeId) {
503             assembleVerificationFailed(uuid, artifact, output);
504         } else if (TSK_DATA_SOURCE_USAGE.getTypeID() == artifactTypeId) {
505             assembleDataSourceUsage(uuid, artifact, output);
506         } else if (TSK_WEB_FORM_ADDRESS.getTypeID() == artifactTypeId) {
507             assembleWebFormAddress(uuid, artifact, output);
508         } else if (TSK_WEB_CACHE.getTypeID() == artifactTypeId) {
509             assembleWebCache(uuid, artifact, output);
510         } else if (TSK_TL_EVENT.getTypeID() == artifactTypeId) {
511             assembleTimelineEvent(uuid, artifact, output);
512         } else if (TSK_CLIPBOARD_CONTENT.getTypeID() == artifactTypeId) {
513             assembleClipboardContent(uuid, artifact, output);
514         } else if (TSK_ASSOCIATED_OBJECT.getTypeID() == artifactTypeId) {
515             assembleAssociatedObject(uuid, artifact, output);
516         } else if (TSK_USER_CONTENT_SUSPECTED.getTypeID() == artifactTypeId) {
517             assembleUserContentSuspected(uuid, artifact, output);
518         } else if (TSK_METADATA.getTypeID() == artifactTypeId) {
519             assembleMetadata(uuid, artifact, output);
520         } else if (TSK_GPS_TRACK.getTypeID() == artifactTypeId) {
521             assembleGpsTrack(uuid, artifact, output);
522         }
523 
524         if (output.isEmpty()) {
525             throw new ContentNotExportableException(String.format(
526                     "Artifact [id:%d, type:%d] is either not supported "
527                     + "or did not have any exported attributes.", artifact.getId(), artifactTypeId));
528         }
529 
530         addParentChildRelationship(output, uuid,
531                 this.uuidService.createUUID(artifact.getParent()));
532 
533         return output;
534     }
535 
assembleWebCookie(String uuid, BlackboardArtifact artifact, List<JsonElement> output)536     private void assembleWebCookie(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
537         Trace export = new Trace(uuid)
538                 .addBundle(new URL()
539                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
540                 .addBundle(new ContentData()
541                         .setDataPayload(getValueIfPresent(artifact, StandardAttributeTypes.TSK_VALUE)));
542 
543         Trace cookieDomainNode = new BlankTraceNode()
544                 .addBundle(new DomainName()
545                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)));
546 
547         Trace applicationNode = new BlankTraceNode()
548                 .addBundle(new Application()
549                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
550 
551         BrowserCookie cookie = new BrowserCookie()
552                 .setCookieName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME))
553                 .setCookieDomain(cookieDomainNode)
554                 .setApplication(applicationNode)
555                 .setAccessedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_START))
556                 .setExpirationTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_END));
557         cookie.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
558 
559         export.addBundle(cookie);
560 
561         addToOutput(export, output);
562         addToOutput(cookieDomainNode, output);
563         addToOutput(applicationNode, output);
564     }
565 
assembleWebBookmark(String uuid, BlackboardArtifact artifact, List<JsonElement> output)566     private void assembleWebBookmark(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
567         Trace applicationNode = new BlankTraceNode()
568                 .addBundle(new Application()
569                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
570 
571         BrowserBookmark bookmark = new BrowserBookmark()
572                 .setUrlTargeted(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL))
573                 .setApplication(applicationNode);
574         bookmark.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
575         bookmark.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
576 
577         Trace export = new Trace(uuid)
578                 .addBundle(bookmark)
579                 .addBundle(new DomainName()
580                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)));
581 
582         addToOutput(export, output);
583         addToOutput(applicationNode, output);
584     }
585 
assembleGenInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output)586     private void assembleGenInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
587         Hash hash = new Hash(uuid, getValueIfPresent(artifact, StandardAttributeTypes.TSK_HASH_PHOTODNA));
588         addToOutput(hash, output);
589     }
590 
assembleWebHistory(String uuid, BlackboardArtifact artifact, List<JsonElement> output)591     private void assembleWebHistory(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
592         Trace userNameNode = new BlankTraceNode();
593 
594         IdentityFacet identityFacet = new IdentityFacet();
595         identityFacet.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_USER_NAME));
596         userNameNode.addBundle(identityFacet);
597 
598         Trace export = new Trace(uuid)
599                 .addBundle(new URL()
600                         .setUserName(userNameNode)
601                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
602                 .addBundle(new DomainName()
603                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)))
604                 .addBundle(new Application()
605                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
606 
607         addToOutput(export, output);
608         addToOutput(userNameNode, output);
609     }
610 
assembleWebDownload(String uuid, BlackboardArtifact artifact, List<JsonElement> output)611     private void assembleWebDownload(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
612         Trace export = new Trace(uuid)
613                 .addBundle(new URL()
614                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
615                 .addBundle(new DomainName()
616                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)))
617                 .addBundle(new File()
618                         .setFilePath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH)))
619                 .addBundle(new Application()
620                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
621         addToOutput(export, output);
622     }
623 
assembleDeviceAttached(String uuid, BlackboardArtifact artifact, List<JsonElement> output)624     private void assembleDeviceAttached(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
625         Trace export = new Trace(uuid)
626                 .addBundle(new Device()
627                         .setManufacturer(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_MAKE))
628                         .setModel(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_MODEL))
629                         .setId(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_ID)))
630                 .addBundle(new MACAddress()
631                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MAC_ADDRESS)));
632 
633         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
634         addToOutput(export, output);
635     }
636 
assembleHashsetHit(String uuid, BlackboardArtifact artifact, List<JsonElement> output)637     private void assembleHashsetHit(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
638         Assertion export = new Assertion(uuid);
639         export.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SET_NAME));
640         export.setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
641 
642         addToOutput(export, output);
643     }
644 
assembleInstalledProg(String uuid, BlackboardArtifact artifact, List<JsonElement> output)645     private void assembleInstalledProg(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
646         Trace export = new Trace(uuid)
647                 .addBundle(new File()
648                         .setFilePath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH_SOURCE)));
649         Software software = new Software();
650         software.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME));
651         export.addBundle(software);
652 
653         File file = new File()
654                 .setFilePath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH));
655         file.setModifiedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
656 
657         file.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
658         export.addBundle(file);
659 
660         addToOutput(export, output);
661     }
662 
assembleRecentObject(String uuid, BlackboardArtifact artifact, List<JsonElement> output)663     private void assembleRecentObject(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
664         Trace export = new Trace(uuid)
665                 .addBundle(new Application()
666                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
667 
668         WindowsRegistryValue registryValue = new WindowsRegistryValue()
669                 .setData(getValueIfPresent(artifact, StandardAttributeTypes.TSK_VALUE));
670         registryValue.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
671 
672         export.addBundle(registryValue);
673 
674         File file = new File()
675                 .setAccessedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_ACCESSED));
676         file.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
677 
678         export.addBundle(file);
679 
680         addToOutput(export, output);
681 
682         Assertion assertion = new BlankAssertionNode()
683                 .setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
684         addToOutput(assertion, output);
685         addToOutput(new BlankRelationshipNode()
686                 .setSource(assertion.getId())
687                 .setTarget(uuid), output);
688     }
689 
assembleInterestingFileHit(String uuid, BlackboardArtifact artifact, List<JsonElement> output)690     private void assembleInterestingFileHit(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
691         Assertion export = new Assertion(uuid);
692         export.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SET_NAME));
693         export.setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
694         addToOutput(export, output);
695     }
696 
assembleExtractedText(String uuid, BlackboardArtifact artifact, List<JsonElement> output)697     private void assembleExtractedText(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
698         Trace export = new Trace(uuid)
699                 .addBundle(new ExtractedString()
700                         .setStringValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_TEXT)));
701         addToOutput(export, output);
702     }
703 
assembleEmailMessage(String uuid, BlackboardArtifact artifact, List<JsonElement> output)704     private void assembleEmailMessage(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
705         Trace bccNode = new BlankTraceNode()
706                 .addBundle(new EmailAddress()
707                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_BCC)));
708 
709         Trace ccNode = new BlankTraceNode()
710                 .addBundle(new EmailAddress()
711                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_CC)));
712 
713         Trace fromNode = new BlankTraceNode()
714                 .addBundle(new EmailAddress()
715                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_FROM)));
716 
717         Trace headerRawNode = new BlankTraceNode()
718                 .addBundle(new ExtractedString()
719                         .setStringValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_HEADERS)));
720 
721         EmailMessage emailMessage = new EmailMessage();
722         String html = getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_CONTENT_HTML);
723         String plain = getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_CONTENT_PLAIN);
724         String rtf = getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_CONTENT_RTF);
725 
726         if (html != null) {
727             emailMessage.setBody(html);
728             emailMessage.setContentType("text/html");
729         } else if (rtf != null) {
730             emailMessage.setBody(rtf);
731             emailMessage.setContentType("text/rtf");
732         } else if (plain != null) {
733             emailMessage.setBody(plain);
734             emailMessage.setContentType("text/plain");
735         }
736 
737         Trace export = new Trace(uuid)
738                 .addBundle(emailMessage
739                         .setReceivedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_RCVD))
740                         .setSentTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_SENT))
741                         .setBcc(bccNode)
742                         .setCc(ccNode)
743                         .setFrom(fromNode)
744                         .setHeaderRaw(headerRawNode)
745                         .setMessageID(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MSG_ID))
746                         .setSubject(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SUBJECT)))
747                 .addBundle(new File()
748                         .setFilePath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH)));
749 
750         addToOutput(export, output);
751         addToOutput(bccNode, output);
752         addToOutput(ccNode, output);
753         addToOutput(fromNode, output);
754         addToOutput(headerRawNode, output);
755     }
756 
assembleWebSearchQuery(String uuid, BlackboardArtifact artifact, List<JsonElement> output)757     private void assembleWebSearchQuery(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
758         Trace applicationNode = new BlankTraceNode()
759                 .addBundle(new Application()
760                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
761 
762         Trace export = new Trace(uuid)
763                 .addBundle(new Note()
764                         .setText(getValueIfPresent(artifact, StandardAttributeTypes.TSK_TEXT)))
765                 .addBundle(new Domain()
766                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)))
767                 .addBundle(new ApplicationAccount()
768                         .setApplication(applicationNode));
769         addToOutput(export, output);
770         addToOutput(applicationNode, output);
771     }
772 
assembleOsInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output)773     private void assembleOsInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
774         Identity registeredOwnerNode = new BlankIdentityNode();
775         registeredOwnerNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_OWNER));
776         Identity registeredOrganizationNode = new BlankIdentityNode();
777         registeredOrganizationNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ORGANIZATION));
778 
779         OperatingSystem operatingSystem = new OperatingSystem()
780                 .setInstallDate(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME))
781                 .setVersion(getValueIfPresent(artifact, StandardAttributeTypes.TSK_VERSION));
782         operatingSystem.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME));
783 
784         EnvironmentVariable envVar = new EnvironmentVariable()
785                 .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_TEMP_DIR));
786         envVar.setName("TEMP");
787         Trace tempDirectoryNode = new BlankTraceNode()
788                 .addBundle(envVar);
789 
790         Trace export = new Trace(uuid)
791                 .addBundle(operatingSystem)
792                 .addBundle(new DomainName()
793                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)))
794                 .addBundle(new Device()
795                         .setSerialNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PRODUCT_ID)))
796                 .addBundle(new ComputerSpecification()
797                         .setHostName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME))
798                         .setProcessorArchitecture(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROCESSOR_ARCHITECTURE)))
799                 .addBundle(new WindowsComputerSpecification()
800                         .setRegisteredOrganization(registeredOrganizationNode)
801                         .setRegisteredOwner(registeredOwnerNode)
802                         .setWindowsTempDirectory(tempDirectoryNode));
803 
804         addToOutput(export, output);
805         addToOutput(registeredOwnerNode, output);
806         addToOutput(registeredOrganizationNode, output);
807         addToOutput(tempDirectoryNode, output);
808     }
809 
assembleOsAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output)810     private void assembleOsAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
811         Trace export = new Trace(uuid)
812                 .addBundle(new EmailAddress()
813                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL)))
814                 .addBundle(new PathRelation()
815                         .setPath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH)))
816                 .addBundle(new WindowsAccount()
817                         .setGroups(getValueIfPresent(artifact, StandardAttributeTypes.TSK_GROUPS)));
818 
819         export.setTag(getValueIfPresent(artifact, StandardAttributeTypes.TSK_FLAG));
820 
821         DigitalAccount digitalAccount = new DigitalAccount()
822                 .setDisplayName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DISPLAY_NAME))
823                 .setLastLoginTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_ACCESSED));
824         digitalAccount.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
825 
826         export.addBundle(digitalAccount);
827 
828         Identity ownerNode = new BlankIdentityNode();
829         ownerNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
830 
831         Account account = new Account()
832                 .setAccountType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ACCOUNT_TYPE))
833                 .setOwner(ownerNode)
834                 .setAccountIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_USER_ID));
835         account.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
836 
837         export.addBundle(account);
838 
839         addToOutput(export, output);
840         addToOutput(ownerNode, output);
841     }
842 
assembleServiceAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output)843     private void assembleServiceAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
844         Trace inReplyToNode = new BlankTraceNode()
845                 .addBundle(new EmailAddress()
846                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_REPLYTO)));
847 
848         Trace export = new Trace(uuid)
849                 .addBundle(new Account()
850                         .setAccountType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_CATEGORY)))
851                 .addBundle(new DomainName()
852                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DOMAIN)))
853                 .addBundle(new EmailMessage()
854                         .setInReplyTo(inReplyToNode))
855                 .addBundle(new DigitalAccount()
856                         .setDisplayName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME)))
857                 .addBundle(new AccountAuthentication()
858                         .setPassword(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PASSWORD)))
859                 .addBundle(new PathRelation()
860                         .setPath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH)))
861                 .addBundle(new URL()
862                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
863                 .addBundle(new DigitalAccount()
864                         .setDisplayName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_USER_NAME)));
865 
866         export.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
867 
868         Trace applicationNode = new BlankTraceNode()
869                 .addBundle(new Application()
870                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
871 
872         ApplicationAccount account = new ApplicationAccount()
873                 .setApplication(applicationNode);
874         account.setId(getValueIfPresent(artifact, StandardAttributeTypes.TSK_USER_ID));
875         account.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
876         export.addBundle(account);
877 
878         addToOutput(export, output);
879         addToOutput(applicationNode, output);
880         addToOutput(inReplyToNode, output);
881     }
882 
assembleContact(String uuid, BlackboardArtifact artifact, List<JsonElement> output)883     private void assembleContact(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
884         EmailAddress homeAddress = new EmailAddress()
885                 .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_HOME));
886         homeAddress.setTag("Home");
887 
888         EmailAddress workAddress = new EmailAddress()
889                 .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_OFFICE));
890         workAddress.setTag("Work");
891 
892         PhoneAccount homePhone = new PhoneAccount()
893                 .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_HOME));
894         homePhone.setTag("Home");
895 
896         PhoneAccount workPhone = new PhoneAccount()
897                 .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_OFFICE));
898         workPhone.setTag("Work");
899 
900         PhoneAccount mobilePhone = new PhoneAccount()
901                 .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_MOBILE));
902         mobilePhone.setTag("Mobile");
903 
904         Trace export = new Trace(uuid)
905                 .addBundle(new URL()
906                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
907                 .addBundle(new EmailAddress()
908                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL)))
909                 .addBundle(homeAddress)
910                 .addBundle(workAddress)
911                 .addBundle(new Contact()
912                         .setContactName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME)))
913                 .addBundle(new PhoneAccount()
914                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER)))
915                 .addBundle(homePhone)
916                 .addBundle(workPhone)
917                 .addBundle(mobilePhone);
918         addToOutput(export, output);
919     }
920 
assembleMessage(String uuid, BlackboardArtifact artifact, List<JsonElement> output)921     private void assembleMessage(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException, BlackboardJsonAttrUtil.InvalidJsonException {
922         Trace applicationNode = new BlankTraceNode()
923                 .addBundle(new Application()
924                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MESSAGE_TYPE)));
925 
926         Trace senderNode = new BlankTraceNode()
927                 .addBundle(new EmailAddress()
928                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL_FROM)));
929 
930         Trace fromNode = new BlankTraceNode()
931                 .addBundle(new PhoneAccount()
932                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_FROM)));
933 
934         Trace toNode = new BlankTraceNode()
935                 .addBundle(new PhoneAccount()
936                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_TO)));
937 
938         Trace export = new Trace(uuid)
939                 .addBundle(new Message()
940                         .setMessageText(getValueIfPresent(artifact, StandardAttributeTypes.TSK_TEXT))
941                         .setApplication(applicationNode)
942                         .setSentTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME))
943                         .setMessageType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DIRECTION))
944                         .setId(getValueIfPresent(artifact, StandardAttributeTypes.TSK_THREAD_ID)))
945                 .addBundle(new EmailMessage()
946                         .setSender(senderNode))
947                 .addBundle(new PhoneAccount()
948                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER)))
949                 .addBundle(new PhoneCall()
950                         .setFrom(fromNode)
951                         .setTo(toNode))
952                 .addBundle(new SMSMessage()
953                         .setIsRead(getIntegerIfPresent(artifact, StandardAttributeTypes.TSK_READ_STATUS)));
954 
955         BlackboardAttribute attachments = artifact.getAttribute(StandardAttributeTypes.TSK_ATTACHMENTS);
956         if (attachments != null) {
957             MessageAttachments attachmentsContainer = BlackboardJsonAttrUtil.fromAttribute(attachments, MessageAttachments.class);
958             List<MessageAttachments.Attachment> tskAttachments = new ArrayList<>();
959             tskAttachments.addAll(attachmentsContainer.getUrlAttachments());
960             tskAttachments.addAll(attachmentsContainer.getFileAttachments());
961 
962             tskAttachments.forEach((tskAttachment) -> {
963                 export.addBundle(new Attachment()
964                         .setUrl(tskAttachment.getLocation())
965                 );
966             });
967         }
968 
969         addToOutput(export, output);
970         addToOutput(applicationNode, output);
971         addToOutput(senderNode, output);
972         addToOutput(fromNode, output);
973         addToOutput(toNode, output);
974     }
975 
assembleMetadataExif(String uuid, BlackboardArtifact artifact, List<JsonElement> output)976     private void assembleMetadataExif(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
977         Trace export = new Trace(uuid)
978                 .addBundle(new Device()
979                         .setManufacturer(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_MAKE))
980                         .setModel(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_MODEL)))
981                 .addBundle(new LatLongCoordinates()
982                         .setAltitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_ALTITUDE))
983                         .setLatitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LATITUDE))
984                         .setLongitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LONGITUDE)));
985 
986         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
987         addToOutput(export, output);
988     }
989 
assembleCallog(String uuid, BlackboardArtifact artifact, List<JsonElement> output)990     private void assembleCallog(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
991         Trace fromNode = new BlankTraceNode()
992                 .addBundle(new PhoneAccount()
993                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_FROM)));
994 
995         Trace toNode = new BlankTraceNode()
996                 .addBundle(new PhoneAccount()
997                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER_TO)));
998 
999         Trace export = new Trace(uuid)
1000                 .addBundle(new PhoneAccount()
1001                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER)))
1002                 .addBundle(new PhoneCall()
1003                         .setFrom(fromNode)
1004                         .setTo(toNode)
1005                         .setEndTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_END))
1006                         .setStartTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_START))
1007                         .setCallType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DIRECTION)))
1008                 .addBundle(new Contact()
1009                         .setContactName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME)));
1010 
1011         addToOutput(export, output);
1012         addToOutput(toNode, output);
1013         addToOutput(fromNode, output);
1014     }
1015 
assembleCalendarEntry(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1016     private void assembleCalendarEntry(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1017         Trace export = new Trace(uuid);
1018 
1019         CalendarEntry calendarEntry = new CalendarEntry()
1020                 .setStartTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_START))
1021                 .setEndTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_END))
1022                 .setEventType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_CALENDAR_ENTRY_TYPE));
1023 
1024         calendarEntry.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
1025 
1026         BlankLocationNode locationNode = new BlankLocationNode();
1027         locationNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1028 
1029         calendarEntry.setLocation(locationNode);
1030         export.addBundle(calendarEntry);
1031 
1032         addToOutput(export, output);
1033         addToOutput(locationNode, output);
1034     }
1035 
assembleSpeedDialEntry(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1036     private void assembleSpeedDialEntry(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1037         Trace export = new Trace(uuid)
1038                 .addBundle(new Contact()
1039                         .setContactName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME_PERSON)))
1040                 .addBundle(new PhoneAccount()
1041                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER)));
1042 
1043         addToOutput(export, output);
1044     }
1045 
assembleBluetoothPairing(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1046     private void assembleBluetoothPairing(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1047         Trace export = new Trace(uuid)
1048                 .addBundle(new MobileDevice()
1049                         .setBluetoothDeviceName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_NAME)))
1050                 .addBundle(new MACAddress()
1051                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MAC_ADDRESS)));
1052 
1053         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1054         addToOutput(export, output);
1055     }
1056 
assembleGpsBookmark(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1057     private void assembleGpsBookmark(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1058         Trace export = new Trace(uuid)
1059                 .addBundle(new LatLongCoordinates()
1060                         .setAltitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_ALTITUDE))
1061                         .setLatitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LATITUDE))
1062                         .setLongitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LONGITUDE)))
1063                 .addBundle(new Application()
1064                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
1065 
1066         SimpleAddress simpleAddress = new SimpleAddress();
1067         simpleAddress.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1068         export.addBundle(simpleAddress);
1069 
1070         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1071         export.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
1072         addToOutput(export, output);
1073     }
1074 
assembleGpsLastKnownLocation(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1075     private void assembleGpsLastKnownLocation(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1076         Trace export = new Trace(uuid)
1077                 .addBundle(new LatLongCoordinates()
1078                         .setAltitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_ALTITUDE))
1079                         .setLatitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LATITUDE))
1080                         .setLongitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LONGITUDE)));
1081         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1082 
1083         BlankLocationNode locationNode = new BlankLocationNode();
1084         locationNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
1085 
1086         SimpleAddress simpleAddress = new SimpleAddress();
1087         simpleAddress.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1088         export.addBundle(simpleAddress);
1089 
1090         addToOutput(export, output);
1091         addToOutput(locationNode, output);
1092         addToOutput(new BlankRelationshipNode()
1093                 .setSource(locationNode.getId())
1094                 .setTarget(export.getId()), output);
1095     }
1096 
assembleGpsSearch(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1097     private void assembleGpsSearch(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1098         Trace export = new Trace(uuid)
1099                 .addBundle(new LatLongCoordinates()
1100                         .setAltitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_ALTITUDE))
1101                         .setLatitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LATITUDE))
1102                         .setLongitude(getDoubleIfPresent(artifact, StandardAttributeTypes.TSK_GEO_LONGITUDE)));
1103         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1104 
1105         BlankLocationNode locationNode = new BlankLocationNode();
1106         locationNode.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
1107 
1108         SimpleAddress simpleAddress = new SimpleAddress();
1109         simpleAddress.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1110         export.addBundle(simpleAddress);
1111 
1112         addToOutput(export, output);
1113         addToOutput(locationNode, output);
1114         addToOutput(new BlankRelationshipNode()
1115                 .setSource(locationNode.getId())
1116                 .setTarget(export.getId()), output);
1117     }
1118 
assembleProgRun(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1119     private void assembleProgRun(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1120         Trace export = new Trace(uuid)
1121                 .addBundle(new Application()
1122                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME))
1123                         .setNumberOfLaunches(getIntegerIfPresent(artifact, StandardAttributeTypes.TSK_COUNT)));
1124 
1125         addToOutput(export, output);
1126     }
1127 
assembleEncryptionDetected(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1128     private void assembleEncryptionDetected(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1129         Assertion export = new Assertion(uuid)
1130                 .setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1131 
1132         addToOutput(export, output);
1133     }
1134 
assembleInterestingArtifact(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1135     private void assembleInterestingArtifact(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1136         Assertion export = new Assertion(uuid);
1137         export.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SET_NAME));
1138         export.setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1139 
1140         Long associatedArtifactId = getLongIfPresent(artifact, StandardAttributeTypes.TSK_ASSOCIATED_ARTIFACT);
1141         if (associatedArtifactId != null) {
1142             BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getBlackboardArtifact(associatedArtifactId);
1143 
1144             addToOutput(new BlankRelationshipNode()
1145                     .setSource(export.getId())
1146                     .setTarget(this.uuidService.createUUID(associatedArtifact)), output);
1147         }
1148 
1149         addToOutput(export, output);
1150     }
1151 
assembleGPSRoute(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1152     private void assembleGPSRoute(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1153         Trace export = new Trace(uuid)
1154                 .addBundle(new Application()
1155                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
1156         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1157 
1158         SimpleAddress simpleAddress = new SimpleAddress();
1159         simpleAddress.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1160         export.addBundle(simpleAddress);
1161 
1162         Location location = new BlankLocationNode();
1163         location.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
1164 
1165         addToOutput(export, output);
1166         addToOutput(location, output);
1167         addToOutput(new BlankRelationshipNode()
1168                 .setSource(location.getId())
1169                 .setTarget(export.getId()), output);
1170     }
1171 
assembleRemoteDrive(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1172     private void assembleRemoteDrive(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1173         Trace export = new Trace(uuid)
1174                 .addBundle(new PathRelation()
1175                         .setPath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_REMOTE_PATH)))
1176                 .addBundle(new PathRelation()
1177                         .setPath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCAL_PATH)));
1178 
1179         addToOutput(export, output);
1180     }
1181 
assembleAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1182     private void assembleAccount(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1183         Account account = new Account()
1184                 .setAccountType(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ACCOUNT_TYPE))
1185                 .setAccountIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ID));
1186 
1187         Account creditCardAccount = new Account()
1188                 .setAccountIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_CARD_NUMBER));
1189 
1190         creditCardAccount.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SET_NAME));
1191         Trace export = new Trace(uuid)
1192                 .addBundle(account)
1193                 .addBundle(creditCardAccount);
1194 
1195         addToOutput(export, output);
1196     }
1197 
assembleEncryptionSuspected(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1198     private void assembleEncryptionSuspected(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1199         Assertion export = new Assertion(uuid)
1200                 .setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1201 
1202         addToOutput(export, output);
1203     }
1204 
assembleObjectDetected(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1205     private void assembleObjectDetected(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1206         Assertion export = new Assertion(uuid)
1207                 .setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1208         export.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
1209 
1210         addToOutput(export, output);
1211     }
1212 
assembleWifiNetwork(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1213     private void assembleWifiNetwork(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1214         WirelessNetworkConnection wirelessNetwork = new WirelessNetworkConnection()
1215                 .setSSID(getValueIfPresent(artifact, StandardAttributeTypes.TSK_SSID));
1216 
1217         wirelessNetwork.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1218 
1219         String networkId = getValueIfPresent(artifact, StandardAttributeTypes.TSK_DEVICE_ID);
1220         if (networkId != null) {
1221             wirelessNetwork.setId("_:" + networkId);
1222         }
1223 
1224         Trace export = new Trace(uuid)
1225                 .addBundle(wirelessNetwork);
1226 
1227         addToOutput(export, output);
1228     }
1229 
assembleDeviceInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1230     private void assembleDeviceInfo(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1231         Trace export = new Trace(uuid)
1232                 .addBundle(new MobileDevice()
1233                         .setIMEI(getValueIfPresent(artifact, StandardAttributeTypes.TSK_IMEI)))
1234                 .addBundle(new SIMCard()
1235                         .setICCID(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ICCID))
1236                         .setIMSI(getValueIfPresent(artifact, StandardAttributeTypes.TSK_IMSI)));
1237 
1238         addToOutput(export, output);
1239     }
1240 
assembleSimAttached(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1241     private void assembleSimAttached(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1242         Trace export = new Trace(uuid)
1243                 .addBundle(new SIMCard()
1244                         .setICCID(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ICCID))
1245                         .setIMSI(getValueIfPresent(artifact, StandardAttributeTypes.TSK_IMSI)));
1246 
1247         addToOutput(export, output);
1248     }
1249 
assembleBluetoothAdapter(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1250     private void assembleBluetoothAdapter(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1251         Trace export = new Trace(uuid)
1252                 .addBundle(new MACAddress()
1253                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MAC_ADDRESS)));
1254 
1255         addToOutput(export, output);
1256     }
1257 
assembleWifiNetworkAdapter(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1258     private void assembleWifiNetworkAdapter(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1259         Trace export = new Trace(uuid)
1260                 .addBundle(new MACAddress()
1261                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_MAC_ADDRESS)));
1262 
1263         addToOutput(export, output);
1264     }
1265 
assembleVerificationFailed(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1266     private void assembleVerificationFailed(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1267         Assertion export = new Assertion(uuid);
1268         export.setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1269 
1270         addToOutput(export, output);
1271     }
1272 
assembleDataSourceUsage(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1273     private void assembleDataSourceUsage(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1274         Trace export = new Trace(uuid);
1275         export.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
1276 
1277         addToOutput(export, output);
1278     }
1279 
assembleWebFormAddress(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1280     private void assembleWebFormAddress(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1281         SimpleAddress simpleAddress = new SimpleAddress();
1282         simpleAddress.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_LOCATION));
1283 
1284         Trace export = new Trace(uuid)
1285                 .addBundle(simpleAddress)
1286                 .addBundle(new EmailAddress()
1287                         .setValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_EMAIL)))
1288                 .addBundle(new PhoneAccount()
1289                         .setPhoneNumber(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PHONE_NUMBER)));
1290 
1291         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_ACCESSED));
1292         export.setModifiedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_MODIFIED));
1293 
1294         Person person = new BlankPersonNode();
1295         person.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME_PERSON));
1296 
1297         addToOutput(export, output);
1298         addToOutput(person, output);
1299         addToOutput(new BlankRelationshipNode()
1300                 .setSource(person.getId())
1301                 .setTarget(export.getId()), output);
1302 
1303     }
1304 
assembleWebCache(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1305     private void assembleWebCache(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1306         Trace export = new Trace(uuid)
1307                 .addBundle(new PathRelation()
1308                         .setPath(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PATH)))
1309                 .addBundle(new URL()
1310                         .setFullValue(getValueIfPresent(artifact, StandardAttributeTypes.TSK_URL)))
1311                 .addBundle(new HTTPConnection()
1312                         .setHttpRequestHeader(getValueIfPresent(artifact, StandardAttributeTypes.TSK_HEADERS)));
1313 
1314         export.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
1315 
1316         addToOutput(export, output);
1317     }
1318 
assembleTimelineEvent(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1319     private void assembleTimelineEvent(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1320         Action export = new Action(uuid)
1321                 .setStartTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME));
1322 
1323         export.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
1324 
1325         Long eventType = getLongIfPresent(artifact, StandardAttributeTypes.TSK_TL_EVENT_TYPE);
1326         if (eventType != null) {
1327             Optional<TimelineEventType> timelineEventType = artifact.getSleuthkitCase()
1328                     .getTimelineManager()
1329                     .getEventType(eventType);
1330             if (timelineEventType.isPresent()) {
1331                 Trace actionArg = new BlankTraceNode()
1332                         .addBundle(new ActionArgument()
1333                                 .setArgumentName(timelineEventType.get().getDisplayName()));
1334 
1335                 addToOutput(actionArg, output);
1336                 addToOutput(new BlankRelationshipNode()
1337                         .setSource(actionArg.getId())
1338                         .setTarget(export.getId()), output);
1339             }
1340         }
1341 
1342         addToOutput(export, output);
1343     }
1344 
assembleClipboardContent(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1345     private void assembleClipboardContent(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1346         Trace export = new Trace(uuid)
1347                 .addBundle(new Note()
1348                         .setText(getValueIfPresent(artifact, StandardAttributeTypes.TSK_TEXT)));
1349 
1350         addToOutput(export, output);
1351     }
1352 
assembleAssociatedObject(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1353     private void assembleAssociatedObject(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1354         Trace export = new Trace(uuid);
1355         addToOutput(export, output);
1356 
1357         BlackboardAttribute associatedArtifactID = artifact.getAttribute(StandardAttributeTypes.TSK_ASSOCIATED_ARTIFACT);
1358         if (associatedArtifactID != null) {
1359             long artifactID = associatedArtifactID.getValueLong();
1360             BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getArtifactByArtifactId(artifactID);
1361             if (associatedArtifact != null) {
1362                 addToOutput(new BlankRelationshipNode()
1363                         .setSource(uuid)
1364                         .setTarget(this.uuidService.createUUID(associatedArtifact)), output);
1365             }
1366         }
1367     }
1368 
assembleUserContentSuspected(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1369     private void assembleUserContentSuspected(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1370         Assertion export = new Assertion(uuid);
1371         export.setStatement(getValueIfPresent(artifact, StandardAttributeTypes.TSK_COMMENT));
1372 
1373         addToOutput(export, output);
1374     }
1375 
assembleMetadata(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1376     private void assembleMetadata(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException {
1377         Trace export = new Trace(uuid)
1378                 .addBundle(new Application()
1379                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME))
1380                         .setVersion(getValueIfPresent(artifact, StandardAttributeTypes.TSK_VERSION)));
1381 
1382         ContentData contentData = new ContentData();
1383         contentData.setCreatedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_CREATED));
1384         contentData.setModifiedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_DATETIME_MODIFIED));
1385         contentData.setDescription(getValueIfPresent(artifact, StandardAttributeTypes.TSK_DESCRIPTION));
1386 
1387         Identity owner = new BlankIdentityNode();
1388         owner.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_OWNER));
1389         contentData.setOwner(owner);
1390         export.addBundle(contentData);
1391 
1392         ContentData contentDataTwo = new ContentData();
1393         contentDataTwo.setTag("Last Printed");
1394         contentDataTwo.setModifiedTime(getLongIfPresent(artifact, StandardAttributeTypes.TSK_LAST_PRINTED_DATETIME));
1395         export.addBundle(contentDataTwo);
1396 
1397         Organization organization = new BlankOrganizationNode();
1398         organization.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_ORGANIZATION));
1399 
1400         Identity lastAuthor = new BlankIdentityNode();
1401         lastAuthor.setTag("Last Author");
1402         lastAuthor.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_USER_ID));
1403 
1404         addToOutput(export, output);
1405         addToOutput(owner, output);
1406         addToOutput(organization, output);
1407         addToOutput(new BlankRelationshipNode()
1408                 .setSource(organization.getId())
1409                 .setTarget(export.getId()), output);
1410         addToOutput(lastAuthor, output);
1411         addToOutput(new BlankRelationshipNode()
1412                 .setSource(lastAuthor.getId())
1413                 .setTarget(export.getId()), output);
1414     }
1415 
assembleGpsTrack(String uuid, BlackboardArtifact artifact, List<JsonElement> output)1416     private void assembleGpsTrack(String uuid, BlackboardArtifact artifact, List<JsonElement> output) throws TskCoreException, BlackboardJsonAttrUtil.InvalidJsonException {
1417         Trace export = new Trace(uuid)
1418                 .addBundle(new Application()
1419                         .setApplicationIdentifier(getValueIfPresent(artifact, StandardAttributeTypes.TSK_PROG_NAME)));
1420         export.setName(getValueIfPresent(artifact, StandardAttributeTypes.TSK_NAME));
1421 
1422         BlackboardAttribute trackpoints = artifact.getAttribute(StandardAttributeTypes.TSK_GEO_TRACKPOINTS);
1423         if (trackpoints != null) {
1424             GeoTrackPoints points = BlackboardJsonAttrUtil.fromAttribute(trackpoints, GeoTrackPoints.class);
1425             for (GeoTrackPoints.TrackPoint point : points) {
1426                 export.addBundle(new LatLongCoordinates()
1427                         .setAltitude(point.getAltitude())
1428                         .setLatitude(point.getLatitude())
1429                         .setLongitude(point.getLongitude()));
1430             }
1431         }
1432 
1433         addToOutput(export, output);
1434     }
1435 
1436     /**
1437      * Pulls the attribute type from the artifact and returns its value if
1438      * present. Should only be called on BlackboardAttribute types that hold
1439      * integer values.
1440      */
getIntegerIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type)1441     private Integer getIntegerIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type) throws TskCoreException {
1442         if (artifact.getAttribute(type) != null) {
1443             return artifact.getAttribute(type).getValueInt();
1444         } else {
1445             return null;
1446         }
1447     }
1448 
1449     /**
1450      * Pulls the attribute type from the artifact and returns its value if
1451      * present. Should only be called on BlackboardAttribute types that hold
1452      * double values.
1453      */
getDoubleIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type)1454     private Double getDoubleIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type) throws TskCoreException {
1455         if (artifact.getAttribute(type) != null) {
1456             return artifact.getAttribute(type).getValueDouble();
1457         } else {
1458             return null;
1459         }
1460     }
1461 
1462     /**
1463      * Pulls the attribute type from the artifact and returns its value if
1464      * present. Should only be called on BlackboardAttribute types that hold
1465      * long values.
1466      */
getLongIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type)1467     private Long getLongIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type) throws TskCoreException {
1468         if (artifact.getAttribute(type) != null) {
1469             return artifact.getAttribute(type).getValueLong();
1470         } else {
1471             return null;
1472         }
1473     }
1474 
1475     /**
1476      * Pulls the attribute type from the artifact and returns its value as a
1477      * string if present. This operation is valid for all attribute types.
1478      */
getValueIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type)1479     private String getValueIfPresent(BlackboardArtifact artifact, BlackboardAttribute.Type type) throws TskCoreException {
1480         if (artifact.getAttribute(type) != null) {
1481             return artifact.getAttribute(type).getDisplayString();
1482         } else {
1483             return null;
1484         }
1485     }
1486 
1487     /**
1488      * Add the parent-child relationship, if configured to do so.
1489      */
addParentChildRelationship(List<JsonElement> output, String sourceId, String parentId)1490     private void addParentChildRelationship(List<JsonElement> output, String sourceId, String parentId) {
1491         String parentChildProperty = this.props.getProperty(INCLUDE_PARENT_CHILD_RELATIONSHIPS_PROP,
1492                 DEFAULT_PARENT_CHILD_RELATIONSHIPS_VALUE);
1493 
1494         if (Boolean.valueOf(parentChildProperty)) {
1495             addToOutput(new BlankRelationshipNode()
1496                     .setSource(sourceId)
1497                     .setTarget(parentId)
1498                     .setKindOfRelationship("contained-within")
1499                     .isDirectional(true), output);
1500         }
1501     }
1502 
1503     /**
1504      * Adds a given CASE export object to the JSON output that will be consumed
1505      * by the client.
1506      */
addToOutput(UcoObject ucoObject, List<JsonElement> output)1507     private void addToOutput(UcoObject ucoObject, List<JsonElement> output) {
1508         output.add(gson.toJsonTree(ucoObject));
1509     }
1510 }
1511