Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ReportGenerator.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013 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.autopsy.report;
20 
21 import java.awt.Dimension;
22 import java.awt.Toolkit;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.awt.event.WindowAdapter;
26 import java.awt.event.WindowEvent;
27 import java.io.File;
28 import java.io.IOException;
29 import java.sql.ResultSet;
30 import java.sql.SQLException;
31 import java.text.DateFormat;
32 import java.text.SimpleDateFormat;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Comparator;
38 import java.util.Date;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Map.Entry;
45 import java.util.Objects;
46 import java.util.Set;
47 import java.util.TreeSet;
48 import java.util.concurrent.ExecutionException;
49 import java.util.logging.Level;
50 import javax.swing.JDialog;
51 import javax.swing.JFrame;
52 import javax.swing.SwingWorker;
53 import org.openide.filesystems.FileUtil;
54 import org.openide.util.NbBundle;
63 import org.sleuthkit.datamodel.AbstractFile;
64 import org.sleuthkit.datamodel.BlackboardArtifact;
65 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
66 import org.sleuthkit.datamodel.BlackboardArtifactTag;
67 import org.sleuthkit.datamodel.BlackboardAttribute;
68 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
69 import org.sleuthkit.datamodel.Content;
70 import org.sleuthkit.datamodel.ContentTag;
71 import org.sleuthkit.datamodel.SleuthkitCase;
72 import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
73 import org.sleuthkit.datamodel.TskCoreException;
74 import org.sleuthkit.datamodel.TskData;
75 import org.sleuthkit.datamodel.BlackboardAttribute.Type;
76 
83 class ReportGenerator {
84 
85  private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName());
86 
87  private Case currentCase = Case.getCurrentCase();
88  private SleuthkitCase skCase = currentCase.getSleuthkitCase();
89 
90  private Map<TableReportModule, ReportProgressPanel> tableProgress;
91  private Map<GeneralReportModule, ReportProgressPanel> generalProgress;
92  private Map<FileReportModule, ReportProgressPanel> fileProgress;
93  private Map<Integer, List<Column>> columnHeaderMap;
94 
95  private String reportPath;
96  private ReportGenerationPanel panel = new ReportGenerationPanel();
97 
98  static final String REPORTS_DIR = "Reports"; //NON-NLS
99 
100  private List<String> errorList;
101 
108  private void displayReportErrors() {
109  if (!errorList.isEmpty()) {
110  String errorString = "";
111  for (String error : errorList) {
112  errorString += error + "\n";
113  }
114  MessageNotifyUtil.Notify.error(
115  NbBundle.getMessage(this.getClass(), "ReportGenerator.notifyErr.errsDuringRptGen"), errorString);
116  return;
117  }
118  }
119 
120  ReportGenerator(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates, Map<FileReportModule, Boolean> fileListModuleStates) {
121  // Create the root reports directory path of the form: <CASE DIRECTORY>/Reports/<Case fileName> <Timestamp>/
122  DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
123  Date date = new Date();
124  String dateNoTime = dateFormat.format(date);
125  this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getName() + " " + dateNoTime + File.separator;
126 
127  this.errorList = new ArrayList<String>();
128 
129  // Create the root reports directory.
130  try {
131  FileUtil.createFolder(new File(this.reportPath));
132  } catch (IOException ex) {
133  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder"));
134  logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS
135  return;
136  }
137 
138  // Initialize the progress panels
139  generalProgress = new HashMap<>();
140  tableProgress = new HashMap<>();
141  fileProgress = new HashMap<>();
142  setupProgressPanels(tableModuleStates, generalModuleStates, fileListModuleStates);
143  this.columnHeaderMap = new HashMap<>();
144  }
145 
157  private void setupProgressPanels(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates, Map<FileReportModule, Boolean> fileListModuleStates) {
158  if (null != tableModuleStates) {
159  for (Entry<TableReportModule, Boolean> entry : tableModuleStates.entrySet()) {
160  if (entry.getValue()) {
161  TableReportModule module = entry.getKey();
162  String reportFilePath = module.getRelativeFilePath();
163  if (!reportFilePath.isEmpty()) {
164  tableProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
165  } else {
166  tableProgress.put(module, panel.addReport(module.getName(), null));
167  }
168  }
169  }
170  }
171 
172  if (null != generalModuleStates) {
173  for (Entry<GeneralReportModule, Boolean> entry : generalModuleStates.entrySet()) {
174  if (entry.getValue()) {
175  GeneralReportModule module = entry.getKey();
176  String reportFilePath = module.getRelativeFilePath();
177  if (!reportFilePath.isEmpty()) {
178  generalProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
179  } else {
180  generalProgress.put(module, panel.addReport(module.getName(), null));
181  }
182  }
183  }
184  }
185 
186  if (null != fileListModuleStates) {
187  for (Entry<FileReportModule, Boolean> entry : fileListModuleStates.entrySet()) {
188  if (entry.getValue()) {
189  FileReportModule module = entry.getKey();
190  String reportFilePath = module.getRelativeFilePath();
191  if (!reportFilePath.isEmpty()) {
192  fileProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
193  } else {
194  fileProgress.put(module, panel.addReport(module.getName(), null));
195  }
196  }
197  }
198  }
199  }
200 
205  public void displayProgressPanels() {
206  final JDialog dialog = new JDialog(new JFrame(), true);
207  dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
208  dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text"));
209  dialog.add(this.panel);
210  dialog.pack();
211 
212  panel.addCloseAction(new ActionListener() {
213  @Override
214  public void actionPerformed(ActionEvent e) {
215  dialog.dispose();
216  }
217  });
218 
219  dialog.addWindowListener(new WindowAdapter() {
220  @Override
221  public void windowClosing(WindowEvent e) {
222  panel.close();
223  }
224  });
225 
226  Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
227  int w = dialog.getSize().width;
228  int h = dialog.getSize().height;
229 
230  // set the location of the popUp Window on the center of the screen
231  dialog.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
232  dialog.setVisible(true);
233  }
234 
238  public void generateGeneralReports() {
239  GeneralReportsWorker worker = new GeneralReportsWorker();
240  worker.execute();
241  }
242 
251  public void generateTableReports(Map<BlackboardArtifact.Type, Boolean> artifactTypeSelections, Map<String, Boolean> tagNameSelections) {
252  if (!tableProgress.isEmpty() && null != artifactTypeSelections) {
253  TableReportsWorker worker = new TableReportsWorker(artifactTypeSelections, tagNameSelections);
254  worker.execute();
255  }
256  }
257 
264  public void generateFileListReports(Map<FileReportDataTypes, Boolean> enabledInfo) {
265  if (!fileProgress.isEmpty() && null != enabledInfo) {
266  List<FileReportDataTypes> enabled = new ArrayList<>();
267  for (Entry<FileReportDataTypes, Boolean> e : enabledInfo.entrySet()) {
268  if (e.getValue()) {
269  enabled.add(e.getKey());
270  }
271  }
272  FileReportsWorker worker = new FileReportsWorker(enabled);
273  worker.execute();
274  }
275  }
276 
280  private class GeneralReportsWorker extends SwingWorker<Integer, Integer> {
281 
282  @Override
283  protected Integer doInBackground() throws Exception {
284  for (Entry<GeneralReportModule, ReportProgressPanel> entry : generalProgress.entrySet()) {
285  GeneralReportModule module = entry.getKey();
286  if (generalProgress.get(module).getStatus() != ReportStatus.CANCELED) {
287  module.generateReport(reportPath, generalProgress.get(module));
288  }
289  }
290  return 0;
291  }
292 
293  @Override
294  protected void done() {
295  try {
296  get();
297  } catch (InterruptedException | ExecutionException ex) {
299  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
300  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
302  logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS
303  } // catch and ignore if we were cancelled
304  catch (java.util.concurrent.CancellationException ex) {
305  } finally {
306  displayReportErrors();
307  errorList.clear();
308  }
309  }
310 
311  }
312 
316  private class FileReportsWorker extends SwingWorker<Integer, Integer> {
317 
318  private List<FileReportDataTypes> enabledInfo = Arrays.asList(FileReportDataTypes.values());
319  private List<FileReportModule> fileModules = new ArrayList<>();
320 
321  FileReportsWorker(List<FileReportDataTypes> enabled) {
322  enabledInfo = enabled;
323  for (Entry<FileReportModule, ReportProgressPanel> entry : fileProgress.entrySet()) {
324  fileModules.add(entry.getKey());
325  }
326  }
327 
328  @Override
329  protected Integer doInBackground() throws Exception {
330  for (FileReportModule module : fileModules) {
331  ReportProgressPanel progress = fileProgress.get(module);
332  if (progress.getStatus() != ReportStatus.CANCELED) {
333  progress.start();
334  progress.updateStatusLabel(
335  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text"));
336  }
337  }
338 
339  List<AbstractFile> files = getFiles();
340  int numFiles = files.size();
341  for (FileReportModule module : fileModules) {
342  module.startReport(reportPath);
343  module.startTable(enabledInfo);
344  fileProgress.get(module).setIndeterminate(false);
345  fileProgress.get(module).setMaximumProgress(numFiles);
346  }
347 
348  int i = 0;
349  // Add files to report.
350  for (AbstractFile file : files) {
351  // Check to see if any reports have been cancelled.
352  if (fileModules.isEmpty()) {
353  break;
354  }
355  // Remove cancelled reports, add files to report otherwise.
356  Iterator<FileReportModule> iter = fileModules.iterator();
357  while (iter.hasNext()) {
358  FileReportModule module = iter.next();
359  ReportProgressPanel progress = fileProgress.get(module);
360  if (progress.getStatus() == ReportStatus.CANCELED) {
361  iter.remove();
362  } else {
363  module.addRow(file, enabledInfo);
364  progress.increment();
365  }
366 
367  if ((i % 100) == 0) {
368  progress.updateStatusLabel(
369  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text",
370  file.getName()));
371  }
372  }
373  i++;
374  }
375 
376  for (FileReportModule module : fileModules) {
377  module.endTable();
378  module.endReport();
379  fileProgress.get(module).complete(ReportStatus.COMPLETE);
380  }
381 
382  return 0;
383  }
384 
390  private List<AbstractFile> getFiles() {
391  List<AbstractFile> absFiles;
392  try {
393  SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
394  absFiles = skCase.findAllFilesWhere("meta_type != " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
395  return absFiles;
396  } catch (TskCoreException ex) {
398  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
399  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
401  logger.log(Level.SEVERE, "failed to generate reports. Unable to get all files in the image.", ex); //NON-NLS
402  return Collections.<AbstractFile>emptyList();
403  }
404  }
405 
406  @Override
407  protected void done() {
408  try {
409  get();
410  } catch (InterruptedException | ExecutionException ex) {
412  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
413  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
415  logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS
416  } // catch and ignore if we were cancelled
417  catch (java.util.concurrent.CancellationException ex) {
418  } finally {
419  displayReportErrors();
420  errorList.clear();
421  }
422  }
423  }
424 
429  private class TableReportsWorker extends SwingWorker<Integer, Integer> {
430 
431  private List<TableReportModule> tableModules = new ArrayList<>();
432  private List<BlackboardArtifact.Type> artifactTypes = new ArrayList<>();
433  private HashSet<String> tagNamesFilter = new HashSet<>();
434 
435  private List<Content> images = new ArrayList<>();
436 
437  TableReportsWorker(Map<BlackboardArtifact.Type, Boolean> artifactTypeSelections, Map<String, Boolean> tagNameSelections) {
438  // Get the report modules selected by the user.
439  for (Entry<TableReportModule, ReportProgressPanel> entry : tableProgress.entrySet()) {
440  tableModules.add(entry.getKey());
441  }
442 
443  // Get the artifact types selected by the user.
444  for (Entry<BlackboardArtifact.Type, Boolean> entry : artifactTypeSelections.entrySet()) {
445  if (entry.getValue()) {
446  artifactTypes.add(entry.getKey());
447  }
448  }
449 
450  // Get the tag names selected by the user and make a tag names filter.
451  if (null != tagNameSelections) {
452  for (Entry<String, Boolean> entry : tagNameSelections.entrySet()) {
453  if (entry.getValue() == true) {
454  tagNamesFilter.add(entry.getKey());
455  }
456  }
457  }
458  }
459 
460  @Override
461  protected Integer doInBackground() throws Exception {
462  // Start the progress indicators for each active TableReportModule.
463  for (TableReportModule module : tableModules) {
464  ReportProgressPanel progress = tableProgress.get(module);
465  if (progress.getStatus() != ReportStatus.CANCELED) {
466  module.startReport(reportPath);
467  progress.start();
468  progress.setIndeterminate(false);
469  progress.setMaximumProgress(this.artifactTypes.size() + 2); // +2 for content and blackboard artifact tags
470  }
471  }
472 
473  // report on the blackboard results
475 
476  // report on the tagged files and artifacts
479 
480  // report on the tagged images
482 
483  // finish progress, wrap up
484  for (TableReportModule module : tableModules) {
485  tableProgress.get(module).complete(ReportStatus.COMPLETE);
486  module.endReport();
487  }
488 
489  return 0;
490  }
491 
496  // Make a comment string describing the tag names filter in effect.
497  StringBuilder comment = new StringBuilder();
498  if (!tagNamesFilter.isEmpty()) {
499  comment.append(NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text"));
500  comment.append(makeCommaSeparatedList(tagNamesFilter));
501  }
502 
503  // Add a table to the report for every enabled blackboard artifact type.
504  for (BlackboardArtifact.Type type : artifactTypes) {
505  // Check for cancellaton.
506  removeCancelledTableReportModules();
507  if (tableModules.isEmpty()) {
508  return;
509  }
510 
511  for (TableReportModule module : tableModules) {
512  tableProgress.get(module).updateStatusLabel(
513  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
514  type.getDisplayName()));
515  }
516 
517  // Keyword hits and hashset hit artifacts get special handling.
518  if (type.getTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
519  writeKeywordHits(tableModules, comment.toString(), tagNamesFilter);
520  continue;
521  } else if (type.getTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
522  writeHashsetHits(tableModules, comment.toString(), tagNamesFilter);
523  continue;
524  }
525 
526  List<ArtifactData> artifactList = getFilteredArtifacts(type, tagNamesFilter);
527 
528  if (artifactList.isEmpty()) {
529  continue;
530  }
531 
532  /*
533  Gets all of the attribute types of this artifact type by adding
534  all of the types to a set
535  */
536  Set<BlackboardAttribute.Type> attrTypeSet = new TreeSet<>((Type o1, Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName()));
537  for (ArtifactData data : artifactList) {
538  List<BlackboardAttribute> attributes = data.getAttributes();
539  for (BlackboardAttribute attribute : attributes) {
540  attrTypeSet.add(attribute.getAttributeType());
541  }
542  }
543  // Get the columns appropriate for the artifact type. This is
544  // used to get the data that will be in the cells below based on
545  // type, and display the column headers.
546  List<Column> columns = getArtifactTableColumns(type.getTypeID(), attrTypeSet);
547  if (columns.isEmpty()) {
548  continue;
549  }
550  ReportGenerator.this.columnHeaderMap.put(type.getTypeID(), columns);
551 
552  // The artifact list is sorted now, as getting the row data is
553  // dependent on having the columns, which is necessary for
554  // sorting.
555  Collections.sort(artifactList);
556  List<String> columnHeaderNames = new ArrayList<>();
557  for (Column currColumn : columns) {
558  columnHeaderNames.add(currColumn.getColumnHeader());
559  }
560 
561  for (TableReportModule module : tableModules) {
562  module.startDataType(type.getDisplayName(), comment.toString());
563  module.startTable(columnHeaderNames);
564  }
565  for (ArtifactData artifactData : artifactList) {
566  // Add the row data to all of the reports.
567  for (TableReportModule module : tableModules) {
568 
569  // Get the row data for this artifact, and has the
570  // module add it.
571  List<String> rowData = artifactData.getRow();
572  if (rowData.isEmpty()) {
573  continue;
574  }
575 
576  module.addRow(rowData);
577  }
578  }
579  // Finish up this data type
580  for (TableReportModule module : tableModules) {
581  tableProgress.get(module).increment();
582  module.endTable();
583  module.endDataType();
584  }
585  }
586  }
587 
591  @SuppressWarnings("deprecation")
592  private void makeContentTagsTables() {
593  // Check for cancellaton.
594  removeCancelledTableReportModules();
595  if (tableModules.isEmpty()) {
596  return;
597  }
598 
599  // Get the content tags.
600  List<ContentTag> tags;
601  try {
603  } catch (TskCoreException ex) {
604  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetContentTags"));
605  logger.log(Level.SEVERE, "failed to get content tags", ex); //NON-NLS
606  return;
607  }
608 
609  // Tell the modules reporting on content tags is beginning.
610  for (TableReportModule module : tableModules) {
611  // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
612  // @@@ Alos Using the obsolete ARTIFACT_TYPE.TSK_TAG_FILE is also an expedient hack.
613  tableProgress.get(module).updateStatusLabel(
614  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
615  ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName()));
616  ArrayList<String> columnHeaders = new ArrayList<>(Arrays.asList(
617  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.tag"),
618  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.file"),
619  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.comment"),
620  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeModified"),
621  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeChanged"),
622  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeAccessed"),
623  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeCreated"),
624  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.size"),
625  NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.hash")));
626 
627  StringBuilder comment = new StringBuilder();
628  if (!tagNamesFilter.isEmpty()) {
629  comment.append(
630  NbBundle.getMessage(this.getClass(), "ReportGenerator.makeContTagTab.taggedFiles.msg"));
631  comment.append(makeCommaSeparatedList(tagNamesFilter));
632  }
633  if (module instanceof ReportHTML) {
634  ReportHTML htmlReportModule = (ReportHTML) module;
635  htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
636  htmlReportModule.startContentTagsTable(columnHeaders);
637  } else {
638  module.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
639  module.startTable(columnHeaders);
640  }
641  }
642 
643  // Give the modules the rows for the content tags.
644  for (ContentTag tag : tags) {
645  // skip tags that we are not reporting on
646  if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) {
647  continue;
648  }
649 
650  String fileName;
651  try {
652  fileName = tag.getContent().getUniquePath();
653  } catch (TskCoreException ex) {
654  fileName = tag.getContent().getName();
655  }
656 
657  ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment()));
658  Content content = tag.getContent();
659  if (content instanceof AbstractFile) {
660  AbstractFile file = (AbstractFile) content;
661 
662  // Add metadata about the file to HTML output
663  rowData.add(file.getMtimeAsDate());
664  rowData.add(file.getCtimeAsDate());
665  rowData.add(file.getAtimeAsDate());
666  rowData.add(file.getCrtimeAsDate());
667  rowData.add(Long.toString(file.getSize()));
668  rowData.add(file.getMd5Hash());
669  }
670  for (TableReportModule module : tableModules) {
671  // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
672  if (module instanceof ReportHTML) {
673  ReportHTML htmlReportModule = (ReportHTML) module;
674  htmlReportModule.addRowWithTaggedContentHyperlink(rowData, tag);
675  } else {
676  module.addRow(rowData);
677  }
678  }
679 
680  // see if it is for an image so that we later report on it
681  checkIfTagHasImage(tag);
682  }
683 
684  // The the modules content tags reporting is ended.
685  for (TableReportModule module : tableModules) {
686  tableProgress.get(module).increment();
687  module.endTable();
688  module.endDataType();
689  }
690  }
691 
692  @Override
693  protected void done() {
694  try {
695  get();
696  } catch (InterruptedException | ExecutionException ex) {
698  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
699  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
701  logger.log(Level.SEVERE, "failed to generate reports", ex.getCause()); //NON-NLS
702  logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS
703  } // catch and ignore if we were cancelled
704  catch (java.util.concurrent.CancellationException ex) {
705  } finally {
706  displayReportErrors();
707  errorList.clear();
708  }
709  }
710 
714  @SuppressWarnings("deprecation")
716  // Check for cancellaton.
717  removeCancelledTableReportModules();
718  if (tableModules.isEmpty()) {
719  return;
720  }
721 
722  List<BlackboardArtifactTag> tags;
723  try {
725  } catch (TskCoreException ex) {
726  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBArtifactTags"));
727  logger.log(Level.SEVERE, "failed to get blackboard artifact tags", ex); //NON-NLS
728  return;
729  }
730 
731  // Tell the modules reporting on blackboard artifact tags data type is beginning.
732  // @@@ Using the obsolete ARTIFACT_TYPE.TSK_TAG_ARTIFACT is an expedient hack.
733  for (TableReportModule module : tableModules) {
734  tableProgress.get(module).updateStatusLabel(
735  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
736  ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName()));
737  StringBuilder comment = new StringBuilder();
738  if (!tagNamesFilter.isEmpty()) {
739  comment.append(
740  NbBundle.getMessage(this.getClass(), "ReportGenerator.makeBbArtTagTab.taggedRes.msg"));
741  comment.append(makeCommaSeparatedList(tagNamesFilter));
742  }
743  module.startDataType(ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName(), comment.toString());
744  module.startTable(new ArrayList<>(Arrays.asList(
745  NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.resultType"),
746  NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.tag"),
747  NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.comment"),
748  NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.srcFile"))));
749  }
750 
751  // Give the modules the rows for the content tags.
752  for (BlackboardArtifactTag tag : tags) {
753  if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) {
754  continue;
755  }
756 
757  List<String> row;
758  for (TableReportModule module : tableModules) {
759  row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName()));
760  module.addRow(row);
761  }
762 
763  // check if the tag is an image that we should later make a thumbnail for
764  checkIfTagHasImage(tag);
765  }
766 
767  // The the modules blackboard artifact tags reporting is ended.
768  for (TableReportModule module : tableModules) {
769  tableProgress.get(module).increment();
770  module.endTable();
771  module.endDataType();
772  }
773  }
774 
782  private boolean passesTagNamesFilter(String tagName) {
783  return tagNamesFilter.isEmpty() || tagNamesFilter.contains(tagName);
784  }
785 
786  void removeCancelledTableReportModules() {
787  Iterator<TableReportModule> iter = tableModules.iterator();
788  while (iter.hasNext()) {
789  TableReportModule module = iter.next();
790  if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
791  iter.remove();
792  }
793  }
794  }
795 
799  private void makeThumbnailTable() {
800  for (TableReportModule module : tableModules) {
801  tableProgress.get(module).updateStatusLabel(
802  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.createdThumb.text"));
803 
804  if (module instanceof ReportHTML) {
805  ReportHTML htmlModule = (ReportHTML) module;
806  htmlModule.startDataType(
807  NbBundle.getMessage(this.getClass(), "ReportGenerator.thumbnailTable.name"),
808  NbBundle.getMessage(this.getClass(), "ReportGenerator.thumbnailTable.desc"));
809  List<String> emptyHeaders = new ArrayList<>();
810  for (int i = 0; i < ReportHTML.THUMBNAIL_COLUMNS; i++) {
811  emptyHeaders.add("");
812  }
813  htmlModule.startTable(emptyHeaders);
814 
815  htmlModule.addThumbnailRows(images);
816 
817  htmlModule.endTable();
818  htmlModule.endDataType();
819  }
820  }
821  }
822 
829  private void checkIfTagHasImage(BlackboardArtifactTag artifactTag) {
830  AbstractFile file;
831  try {
832  file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(artifactTag.getArtifact().getObjectID());
833  } catch (TskCoreException ex) {
834  errorList.add(
835  NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.errGetContentFromBBArtifact"));
836  logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex); //NON-NLS
837  return;
838  }
839 
840  if (file != null) {
841  checkIfFileIsImage(file);
842  }
843  }
844 
852  private void checkIfTagHasImage(ContentTag contentTag) {
853  Content c = contentTag.getContent();
854  if (c instanceof AbstractFile == false) {
855  return;
856  }
857  checkIfFileIsImage((AbstractFile) c);
858  }
859 
865  private void checkIfFileIsImage(AbstractFile file) {
866 
867  if (file.isDir()
868  || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS
869  || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) {
870  return;
871  }
872 
873  if (ImageUtils.thumbnailSupported(file)) {
874  images.add(file);
875  }
876  }
877  }
878 
880  private Boolean failsTagFilter(HashSet<String> tagNames, HashSet<String> tagsNamesFilter) {
881  if (null == tagsNamesFilter || tagsNamesFilter.isEmpty()) {
882  return false;
883  }
884 
885  HashSet<String> filteredTagNames = new HashSet<>(tagNames);
886  filteredTagNames.retainAll(tagsNamesFilter);
887  return filteredTagNames.isEmpty();
888  }
889 
899  private List<ArtifactData> getFilteredArtifacts(BlackboardArtifact.Type type, HashSet<String> tagNamesFilter) {
900  List<ArtifactData> artifacts = new ArrayList<>();
901  try {
902  for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type.getTypeID())) {
903  List<BlackboardArtifactTag> tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact);
904  HashSet<String> uniqueTagNames = new HashSet<>();
905  for (BlackboardArtifactTag tag : tags) {
906  uniqueTagNames.add(tag.getName().getDisplayName());
907  }
908  if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
909  continue;
910  }
911  try {
912  artifacts.add(new ArtifactData(artifact, skCase.getBlackboardAttributes(artifact), uniqueTagNames));
913  } catch (TskCoreException ex) {
914  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBAttribs"));
915  logger.log(Level.SEVERE, "Failed to get Blackboard Attributes when generating report.", ex); //NON-NLS
916  }
917  }
918  } catch (TskCoreException ex) {
919  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBArtifacts"));
920  logger.log(Level.SEVERE, "Failed to get Blackboard Artifacts when generating report.", ex); //NON-NLS
921  }
922  return artifacts;
923  }
924 
930  @SuppressWarnings("deprecation")
931  private void writeKeywordHits(List<TableReportModule> tableModules, String comment, HashSet<String> tagNamesFilter) {
932 
933  // Query for keyword lists-only so that we can tell modules what lists
934  // will exist for their index.
935  // @@@ There is a bug in here. We should use the tags in the below code
936  // so that we only report the lists that we will later provide with real
937  // hits. If no keyord hits are tagged, then we make the page for nothing.
938  String orderByClause;
939  if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
940  orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
941  } else {
942  orderByClause = "ORDER BY list ASC"; //NON-NLS
943  }
944  String keywordListQuery
945  = "SELECT att.value_text AS list " + //NON-NLS
946  "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS
947  "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS
948  "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + " " + //NON-NLS
949  "AND att.artifact_id = art.artifact_id " + //NON-NLS
950  "GROUP BY list " + orderByClause; //NON-NLS
951 
952  try (CaseDbQuery dbQuery = skCase.executeQuery(keywordListQuery)) {
953  ResultSet listsRs = dbQuery.getResultSet();
954  List<String> lists = new ArrayList<>();
955  while (listsRs.next()) {
956  String list = listsRs.getString("list"); //NON-NLS
957  if (list.isEmpty()) {
958  list = NbBundle.getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs");
959  }
960  lists.add(list);
961  }
962 
963  // Make keyword data type and give them set index
964  for (TableReportModule module : tableModules) {
965  module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
966  module.addSetIndex(lists);
967  tableProgress.get(module).updateStatusLabel(
968  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
969  ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName()));
970  }
971  } catch (TskCoreException | SQLException ex) {
972  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWLists"));
973  logger.log(Level.SEVERE, "Failed to query keyword lists: ", ex); //NON-NLS
974  return;
975  }
976 
977  if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
978  orderByClause = "ORDER BY convert_to(att3.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
979  + "convert_to(att1.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
980  + "convert_to(f.parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
981  + "convert_to(f.name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
982  + "convert_to(att2.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
983  } else {
984  orderByClause = "ORDER BY list ASC, keyword ASC, parent_path ASC, name ASC, preview ASC"; //NON-NLS
985  }
986  // Query for keywords, grouped by list
987  String keywordsQuery
988  = "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path " + //NON-NLS
989  "FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, blackboard_attributes AS att3, tsk_files AS f " + //NON-NLS
990  "WHERE (att1.artifact_id = art.artifact_id) " + //NON-NLS
991  "AND (att2.artifact_id = art.artifact_id) " + //NON-NLS
992  "AND (att3.artifact_id = art.artifact_id) " + //NON-NLS
993  "AND (f.obj_id = art.obj_id) " + //NON-NLS
994  "AND (att1.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID() + ") " + //NON-NLS
995  "AND (att2.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID() + ") " + //NON-NLS
996  "AND (att3.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ") " + //NON-NLS
997  "AND (art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") " + //NON-NLS
998  orderByClause; //NON-NLS
999 
1000  try (CaseDbQuery dbQuery = skCase.executeQuery(keywordsQuery)) {
1001  ResultSet resultSet = dbQuery.getResultSet();
1002 
1003  String currentKeyword = "";
1004  String currentList = "";
1005  while (resultSet.next()) {
1006  // Check to see if all the TableReportModules have been canceled
1007  if (tableModules.isEmpty()) {
1008  break;
1009  }
1010  Iterator<TableReportModule> iter = tableModules.iterator();
1011  while (iter.hasNext()) {
1012  TableReportModule module = iter.next();
1013  if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
1014  iter.remove();
1015  }
1016  }
1017 
1018  // Get any tags that associated with this artifact and apply the tag filter.
1019  HashSet<String> uniqueTagNames = getUniqueTagNames(resultSet.getLong("artifact_id")); //NON-NLS
1020  if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
1021  continue;
1022  }
1023  String tagsList = makeCommaSeparatedList(uniqueTagNames);
1024 
1025  Long objId = resultSet.getLong("obj_id"); //NON-NLS
1026  String keyword = resultSet.getString("keyword"); //NON-NLS
1027  String preview = resultSet.getString("preview"); //NON-NLS
1028  String list = resultSet.getString("list"); //NON-NLS
1029  String uniquePath = "";
1030 
1031  try {
1032  AbstractFile f = skCase.getAbstractFileById(objId);
1033  if (f != null) {
1034  uniquePath = skCase.getAbstractFileById(objId).getUniquePath();
1035  }
1036  } catch (TskCoreException ex) {
1037  errorList.add(
1038  NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileByID"));
1039  logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex); //NON-NLS
1040  }
1041 
1042  // If the lists aren't the same, we've started a new list
1043  if ((!list.equals(currentList) && !list.isEmpty()) || (list.isEmpty() && !currentList.equals(
1044  NbBundle.getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs")))) {
1045  if (!currentList.isEmpty()) {
1046  for (TableReportModule module : tableModules) {
1047  module.endTable();
1048  module.endSet();
1049  }
1050  }
1051  currentList = list.isEmpty() ? NbBundle
1052  .getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs") : list;
1053  currentKeyword = ""; // reset the current keyword because it's a new list
1054  for (TableReportModule module : tableModules) {
1055  module.startSet(currentList);
1056  tableProgress.get(module).updateStatusLabel(
1057  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingList",
1058  ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), currentList));
1059  }
1060  }
1061  if (!keyword.equals(currentKeyword)) {
1062  if (!currentKeyword.equals("")) {
1063  for (TableReportModule module : tableModules) {
1064  module.endTable();
1065  }
1066  }
1067  currentKeyword = keyword;
1068  for (TableReportModule module : tableModules) {
1069  module.addSetElement(currentKeyword);
1070  List<String> columnHeaderNames = new ArrayList<>();
1071  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview"));
1072  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile"));
1073  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"));
1074  module.startTable(columnHeaderNames);
1075  }
1076  }
1077 
1078  String previewreplace = EscapeUtil.escapeHtml(preview);
1079  for (TableReportModule module : tableModules) {
1080  module.addRow(Arrays.asList(new String[]{previewreplace.replaceAll("<!", ""), uniquePath, tagsList}));
1081  }
1082  }
1083 
1084  // Finish the current data type
1085  for (TableReportModule module : tableModules) {
1086  tableProgress.get(module).increment();
1087  module.endDataType();
1088  }
1089  } catch (TskCoreException | SQLException ex) {
1090  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWs"));
1091  logger.log(Level.SEVERE, "Failed to query keywords: ", ex); //NON-NLS
1092  }
1093  }
1094 
1100  @SuppressWarnings("deprecation")
1101  private void writeHashsetHits(List<TableReportModule> tableModules, String comment, HashSet<String> tagNamesFilter) {
1102  String orderByClause;
1103  if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
1104  orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
1105  } else {
1106  orderByClause = "ORDER BY att.value_text ASC"; //NON-NLS
1107  }
1108  String hashsetsQuery
1109  = "SELECT att.value_text AS list " + //NON-NLS
1110  "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS
1111  "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS
1112  "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + " " + //NON-NLS
1113  "AND att.artifact_id = art.artifact_id " + //NON-NLS
1114  "GROUP BY list " + orderByClause; //NON-NLS
1115 
1116  try (CaseDbQuery dbQuery = skCase.executeQuery(hashsetsQuery)) {
1117  // Query for hashsets
1118  ResultSet listsRs = dbQuery.getResultSet();
1119  List<String> lists = new ArrayList<>();
1120  while (listsRs.next()) {
1121  lists.add(listsRs.getString("list")); //NON-NLS
1122  }
1123 
1124  for (TableReportModule module : tableModules) {
1125  module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
1126  module.addSetIndex(lists);
1127  tableProgress.get(module).updateStatusLabel(
1128  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
1129  ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName()));
1130  }
1131  } catch (TskCoreException | SQLException ex) {
1132  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryHashsetLists"));
1133  logger.log(Level.SEVERE, "Failed to query hashset lists: ", ex); //NON-NLS
1134  return;
1135  }
1136 
1137  if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
1138  orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
1139  + "convert_to(f.parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
1140  + "convert_to(f.name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
1141  + "size ASC NULLS FIRST"; //NON-NLS
1142  } else {
1143  orderByClause = "ORDER BY att.value_text ASC, f.parent_path ASC, f.name ASC, size ASC"; //NON-NLS
1144  }
1145  String hashsetHitsQuery
1146  = "SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size, f.parent_path AS parent_path " + //NON-NLS
1147  "FROM blackboard_artifacts AS art, blackboard_attributes AS att, tsk_files AS f " + //NON-NLS
1148  "WHERE (att.artifact_id = art.artifact_id) " + //NON-NLS
1149  "AND (f.obj_id = art.obj_id) " + //NON-NLS
1150  "AND (att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ") " + //NON-NLS
1151  "AND (art.artifact_type_id = " + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + ") " + //NON-NLS
1152  orderByClause; //NON-NLS
1153 
1154  try (CaseDbQuery dbQuery = skCase.executeQuery(hashsetHitsQuery)) {
1155  // Query for hashset hits
1156  ResultSet resultSet = dbQuery.getResultSet();
1157  String currentSet = "";
1158  while (resultSet.next()) {
1159  // Check to see if all the TableReportModules have been canceled
1160  if (tableModules.isEmpty()) {
1161  break;
1162  }
1163  Iterator<TableReportModule> iter = tableModules.iterator();
1164  while (iter.hasNext()) {
1165  TableReportModule module = iter.next();
1166  if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
1167  iter.remove();
1168  }
1169  }
1170 
1171  // Get any tags that associated with this artifact and apply the tag filter.
1172  HashSet<String> uniqueTagNames = getUniqueTagNames(resultSet.getLong("artifact_id")); //NON-NLS
1173  if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
1174  continue;
1175  }
1176  String tagsList = makeCommaSeparatedList(uniqueTagNames);
1177 
1178  Long objId = resultSet.getLong("obj_id"); //NON-NLS
1179  String set = resultSet.getString("setname"); //NON-NLS
1180  String size = resultSet.getString("size"); //NON-NLS
1181  String uniquePath = "";
1182 
1183  try {
1184  AbstractFile f = skCase.getAbstractFileById(objId);
1185  if (f != null) {
1186  uniquePath = skCase.getAbstractFileById(objId).getUniquePath();
1187  }
1188  } catch (TskCoreException ex) {
1189  errorList.add(
1190  NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileFromID"));
1191  logger.log(Level.WARNING, "Failed to get Abstract File from ID.", ex); //NON-NLS
1192  return;
1193  }
1194 
1195  // If the sets aren't the same, we've started a new set
1196  if (!set.equals(currentSet)) {
1197  if (!currentSet.isEmpty()) {
1198  for (TableReportModule module : tableModules) {
1199  module.endTable();
1200  module.endSet();
1201  }
1202  }
1203  currentSet = set;
1204  for (TableReportModule module : tableModules) {
1205  module.startSet(currentSet);
1206  List<String> columnHeaderNames = new ArrayList<>();
1207  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"));
1208  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size"));
1209  columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"));
1210  module.startTable(columnHeaderNames);
1211  tableProgress.get(module).updateStatusLabel(
1212  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingList",
1213  ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), currentSet));
1214  }
1215  }
1216 
1217  // Add a row for this hit to every module
1218  for (TableReportModule module : tableModules) {
1219  module.addRow(Arrays.asList(new String[]{uniquePath, size, tagsList}));
1220  }
1221  }
1222 
1223  // Finish the current data type
1224  for (TableReportModule module : tableModules) {
1225  tableProgress.get(module).increment();
1226  module.endDataType();
1227  }
1228  } catch (TskCoreException | SQLException ex) {
1229  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryHashsetHits"));
1230  logger.log(Level.SEVERE, "Failed to query hashsets hits: ", ex); //NON-NLS
1231  }
1232  }
1233 
1244  private List<Column> getArtifactTableColumns(int artifactTypeId, Set<BlackboardAttribute.Type> attributeTypeSet) {
1245  ArrayList<Column> columns = new ArrayList<>();
1246 
1247  // Long switch statement to retain ordering of attribute types that are
1248  // attached to pre-defined artifact types.
1249  if (ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() == artifactTypeId) {
1250  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
1251  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
1252 
1253  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"),
1254  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE)));
1255 
1256  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateCreated"),
1257  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED)));
1258 
1259  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1260  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1261 
1262  } else if (ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() == artifactTypeId) {
1263  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
1264  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
1265 
1266  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1267  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1268 
1269  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1270  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1271 
1272  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.value"),
1273  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_VALUE)));
1274 
1275  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1276  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1277 
1278  } else if (ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() == artifactTypeId) {
1279  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
1280  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
1281 
1282  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
1283  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
1284 
1285  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.referrer"),
1286  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REFERRER)));
1287 
1288  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"),
1289  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE)));
1290 
1291  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1292  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1293 
1294  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.urlDomainDecoded"),
1295  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL_DECODED)));
1296 
1297  } else if (ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeId) {
1298  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dest"),
1299  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
1300 
1301  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.sourceUrl"),
1302  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
1303 
1304  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
1305  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
1306 
1307  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1308  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1309 
1310  } else if (ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifactTypeId) {
1311  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path"),
1312  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
1313 
1314  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1315  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1316 
1317  } else if (ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID() == artifactTypeId) {
1318  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"),
1319  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1320 
1321  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.instDateTime"),
1322  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1323 
1324  } else if (ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() == artifactTypeId) {
1325  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview")));
1326 
1327  } else if (ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == artifactTypeId) {
1328  columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file")));
1329 
1330  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size")));
1331 
1332  } else if (ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeId) {
1333  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devMake"),
1334  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)));
1335 
1336  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"),
1337  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)));
1338 
1339  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceId"),
1340  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID)));
1341 
1342  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1343  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1344 
1345  } else if (ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() == artifactTypeId) {
1346  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"),
1347  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT)));
1348 
1349  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.domain"),
1350  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN)));
1351 
1352  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
1353  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
1354 
1355  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"),
1356  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1357 
1358  } else if (ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID() == artifactTypeId) {
1359  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTaken"),
1360  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED)));
1361 
1362  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devManufacturer"),
1363  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)));
1364 
1365  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"),
1366  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)));
1367 
1368  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
1369  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
1370 
1371  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
1372  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
1373 
1374  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
1375  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
1376 
1377  } else if (ARTIFACT_TYPE.TSK_CONTACT.getTypeID() == artifactTypeId) {
1378  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
1379  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1380 
1381  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"),
1382  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)));
1383 
1384  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumHome"),
1385  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME)));
1386 
1387  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumOffice"),
1388  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE)));
1389 
1390  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumMobile"),
1391  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE)));
1392 
1393  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.email"),
1394  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL)));
1395 
1396  } else if (ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifactTypeId) {
1397  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.msgType"),
1398  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)));
1399 
1400  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"),
1401  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION)));
1402 
1403  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.readStatus"),
1404  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_READ_STATUS)));
1405 
1406  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1407  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1408 
1409  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"),
1410  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)));
1411 
1412  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromEmail"),
1413  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)));
1414 
1415  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"),
1416  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)));
1417 
1418  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toEmail"),
1419  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO)));
1420 
1421  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.subject"),
1422  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)));
1423 
1424  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"),
1425  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT)));
1426 
1427  } else if (ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() == artifactTypeId) {
1428  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
1429  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1430 
1431  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"),
1432  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)));
1433 
1434  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"),
1435  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)));
1436 
1437  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1438  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START)));
1439 
1440  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"),
1441  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION)));
1442 
1443  } else if (ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID() == artifactTypeId) {
1444  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.calendarEntryType"),
1445  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CALENDAR_ENTRY_TYPE)));
1446 
1447  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
1448  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
1449 
1450  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.startDateTime"),
1451  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START)));
1452 
1453  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.endDateTime"),
1454  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END)));
1455 
1456  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"),
1457  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
1458 
1459  } else if (ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID() == artifactTypeId) {
1460  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.shortCut"),
1461  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SHORTCUT)));
1462 
1463  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
1464  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME_PERSON)));
1465 
1466  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"),
1467  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)));
1468 
1469  } else if (ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() == artifactTypeId) {
1470  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceName"),
1471  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_NAME)));
1472 
1473  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceAddress"),
1474  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID)));
1475 
1476  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1477  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1478 
1479  } else if (ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID() == artifactTypeId) {
1480  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
1481  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
1482 
1483  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
1484  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
1485 
1486  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1487  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1488 
1489  } else if (ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID() == artifactTypeId) {
1490  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
1491  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
1492 
1493  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
1494  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
1495 
1496  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
1497  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
1498 
1499  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1500  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1501 
1502  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
1503  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
1504 
1505  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1506  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1507 
1508  } else if (ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID() == artifactTypeId) {
1509  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
1510  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
1511 
1512  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
1513  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
1514 
1515  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
1516  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
1517 
1518  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1519  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1520 
1521  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
1522  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
1523 
1524  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1525  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1526 
1527  } else if (ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID() == artifactTypeId) {
1528  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
1529  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
1530 
1531  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
1532  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
1533 
1534  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
1535  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
1536 
1537  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1538  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1539 
1540  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
1541  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
1542 
1543  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1544  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1545 
1546  } else if (ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID() == artifactTypeId) {
1547  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.category"),
1548  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
1549 
1550  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"),
1551  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)));
1552 
1553  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.password"),
1554  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PASSWORD)));
1555 
1556  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
1557  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1558 
1559  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appName"),
1560  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1561 
1562  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
1563  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
1564 
1565  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appPath"),
1566  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
1567 
1568  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
1569  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
1570 
1571  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.replytoAddress"),
1572  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_REPLYTO)));
1573 
1574  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mailServer"),
1575  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SERVER_NAME)));
1576 
1577  } else if (ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() == artifactTypeId) {
1578  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1579  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1580 
1581  } else if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == artifactTypeId) {
1582  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file")));
1583 
1584  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.extension.text")));
1585 
1586  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mimeType.text")));
1587 
1588  columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path")));
1589 
1590  } else if (ARTIFACT_TYPE.TSK_OS_INFO.getTypeID() == artifactTypeId) {
1591  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.processorArchitecture.text"),
1592  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE)));
1593 
1594  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osName.text"),
1595  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1596 
1597  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osInstallDate.text"),
1598  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1599 
1600  } else if (ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifactTypeId) {
1601  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailTo"),
1602  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO)));
1603 
1604  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailFrom"),
1605  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)));
1606 
1607  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSubject"),
1608  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)));
1609 
1610  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeSent"),
1611  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT)));
1612 
1613  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeRcvd"),
1614  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD)));
1615 
1616  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
1617  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
1618 
1619  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailCc"),
1620  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CC)));
1621 
1622  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailBcc"),
1623  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_BCC)));
1624 
1625  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskMsgId"),
1626  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MSG_ID)));
1627 
1628  } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == artifactTypeId) {
1629  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"),
1630  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME)));
1631 
1632  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskInterestingFilesCategory"),
1633  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
1634 
1635  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
1636  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
1637 
1638  } else if (ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID() == artifactTypeId) {
1639  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskGpsRouteCategory"),
1640  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
1641 
1642  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1643  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1644 
1645  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeEnd"),
1646  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END)));
1647 
1648  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeEnd"),
1649  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END)));
1650 
1651  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeStart"),
1652  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START)));
1653 
1654  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeStart"),
1655  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START)));
1656 
1657  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
1658  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
1659 
1660  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"),
1661  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
1662 
1663  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1664  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1665 
1666  } else if (ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifactTypeId) {
1667  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"),
1668  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME)));
1669 
1670  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"),
1671  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)));
1672 
1673  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1674  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1675 
1676  } else if (ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == artifactTypeId) {
1677  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
1678  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
1679 
1680  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"),
1681  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)));
1682 
1683  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
1684  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
1685 
1686  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.count"),
1687  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT)));
1688 
1689  } else if (ARTIFACT_TYPE.TSK_OS_ACCOUNT.getTypeID() == artifactTypeId) {
1690  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userName"),
1691  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)));
1692 
1693  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"),
1694  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)));
1695 
1696  } else if (ARTIFACT_TYPE.TSK_REMOTE_DRIVE.getTypeID() == artifactTypeId) {
1697  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.localPath"),
1698  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCAL_PATH)));
1699 
1700  columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"),
1701  new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REMOTE_PATH)));
1702  } else {
1703  // This is the case that it is a custom type. The reason an else is
1704  // necessary is to make sure that the source file column is added
1705  for (BlackboardAttribute.Type type : attributeTypeSet) {
1706  columns.add(new AttributeColumn(type.getDisplayName(), type));
1707  }
1708  columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")));
1709  columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")));
1710 
1711  // Short circuits to guarantee that the attribute types aren't added
1712  // twice.
1713  return columns;
1714  }
1715  // If it is an attribute column, it removes the attribute type of that
1716  // column from the set, so types are not reported more than once.
1717  for (Column column : columns) {
1718  attributeTypeSet = column.removeTypeFromSet(attributeTypeSet);
1719  }
1720  // Now uses the remaining types in the set to construct columns
1721  for (BlackboardAttribute.Type type : attributeTypeSet) {
1722  columns.add(new AttributeColumn(type.getDisplayName(), type));
1723  }
1724  // Source file column is added here for ordering purposes.
1725  if (artifactTypeId == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()
1726  || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()
1727  || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
1728  || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
1729  || artifactTypeId == ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()
1730  || artifactTypeId == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()
1731  || artifactTypeId == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()
1732  || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()
1733  || artifactTypeId == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()
1734  || artifactTypeId == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
1735  || artifactTypeId == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
1736  || artifactTypeId == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
1737  || artifactTypeId == ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID()
1738  || artifactTypeId == ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID()
1739  || artifactTypeId == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID()
1740  || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID()
1741  || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID()
1742  || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID()
1743  || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID()
1744  || artifactTypeId == ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID()
1745  || artifactTypeId == ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()
1746  || artifactTypeId == ARTIFACT_TYPE.TSK_OS_INFO.getTypeID()) {
1747  columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")));
1748  }
1749  columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")));
1750 
1751  return columns;
1752  }
1753 
1762  private String makeCommaSeparatedList(Collection<String> items) {
1763  String list = "";
1764  for (Iterator<String> iterator = items.iterator(); iterator.hasNext();) {
1765  list += iterator.next() + (iterator.hasNext() ? ", " : "");
1766  }
1767  return list;
1768  }
1769 
1777  private String getFileUniquePath(Content content) {
1778  try {
1779  if (content != null) {
1780  return content.getUniquePath();
1781  } else {
1782  return "";
1783  }
1784  } catch (TskCoreException ex) {
1785  errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileByID"));
1786  logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex); //NON-NLS
1787  }
1788  return "";
1789 
1790  }
1791 
1796  private class ArtifactData implements Comparable<ArtifactData> {
1797 
1798  private BlackboardArtifact artifact;
1799  private List<BlackboardAttribute> attributes;
1800  private HashSet<String> tags;
1801  private List<String> rowData = null;
1802  private Content content;
1803 
1804  ArtifactData(BlackboardArtifact artifact, List<BlackboardAttribute> attrs, HashSet<String> tags) {
1805  this.artifact = artifact;
1806  this.attributes = attrs;
1807  this.tags = tags;
1808  try {
1809  this.content = Case.getCurrentCase().getSleuthkitCase().getContentById(artifact.getObjectID());
1810  } catch (TskCoreException ex) {
1811  logger.log(Level.SEVERE, "Could not get content from database");
1812  }
1813  }
1814 
1815  public BlackboardArtifact getArtifact() {
1816  return artifact;
1817  }
1818 
1819  public List<BlackboardAttribute> getAttributes() {
1820  return attributes;
1821  }
1822 
1823  public HashSet<String> getTags() {
1824  return tags;
1825  }
1826 
1827  public long getArtifactID() {
1828  return artifact.getArtifactID();
1829  }
1830 
1831  public long getObjectID() {
1832  return artifact.getObjectID();
1833  }
1834 
1838  public Content getContent() {
1839  return content;
1840  }
1841 
1851  @Override
1852  public int compareTo(ArtifactData otherArtifactData) {
1853  List<String> thisRow = getRow();
1854  List<String> otherRow = otherArtifactData.getRow();
1855  for (int i = 0; i < thisRow.size(); i++) {
1856  int compare = thisRow.get(i).compareTo(otherRow.get(i));
1857  if (compare != 0) {
1858  return compare;
1859  }
1860  }
1861  return ((Long) this.getArtifactID()).compareTo((Long) otherArtifactData.getArtifactID());
1862  }
1863 
1871  public List<String> getRow() {
1872  if (rowData == null) {
1873  try {
1874  rowData = getOrderedRowDataAsStrings();
1875  // If else is done so that row data is not set before
1876  // columns are added to the hash map.
1877  if (rowData.size() > 0) {
1878  // replace null values if attribute was not defined
1879  for (int i = 0; i < rowData.size(); i++) {
1880  if (rowData.get(i) == null) {
1881  rowData.set(i, "");
1882  }
1883  }
1884  } else {
1885  rowData = null;
1886  return new ArrayList<>();
1887  }
1888  } catch (TskCoreException ex) {
1889  errorList.add(
1890  NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.coreExceptionWhileGenRptRow"));
1891  logger.log(Level.WARNING, "Core exception while generating row data for artifact report.", ex); //NON-NLS
1892  rowData = Collections.<String>emptyList();
1893  }
1894  }
1895  return rowData;
1896  }
1897 
1907  private List<String> getOrderedRowDataAsStrings() throws TskCoreException {
1908 
1909  List<String> orderedRowData = new ArrayList<>();
1910  if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) {
1911  if (content != null && content instanceof AbstractFile) {
1912  AbstractFile file = (AbstractFile) content;
1913  orderedRowData.add(file.getName());
1914  orderedRowData.add(file.getNameExtension());
1915  String mimeType = file.getMIMEType();
1916  if (mimeType == null) {
1917  orderedRowData.add("");
1918  } else {
1919  orderedRowData.add(mimeType);
1920  }
1921  orderedRowData.add(file.getUniquePath());
1922  } else {
1923  // Make empty rows to make sure the formatting is correct
1924  orderedRowData.add(null);
1925  orderedRowData.add(null);
1926  orderedRowData.add(null);
1927  orderedRowData.add(null);
1928  }
1929  orderedRowData.add(makeCommaSeparatedList(getTags()));
1930 
1931  } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) {
1932  String[] attributeDataArray = new String[3];
1933  // Array is used so that the order of the attributes is
1934  // maintained.
1935  for (BlackboardAttribute attr : attributes) {
1936  if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME))) {
1937  attributeDataArray[0] = attr.getDisplayString();
1938  } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))) {
1939  attributeDataArray[1] = attr.getDisplayString();
1940  } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) {
1941  String pathToShow = attr.getDisplayString();
1942  if (pathToShow.isEmpty()) {
1943  pathToShow = getFileUniquePath(content);
1944  }
1945  attributeDataArray[2] = pathToShow;
1946  }
1947  }
1948  orderedRowData.addAll(Arrays.asList(attributeDataArray));
1949  orderedRowData.add(makeCommaSeparatedList(getTags()));
1950 
1951  } else {
1952  if (ReportGenerator.this.columnHeaderMap.containsKey(this.artifact.getArtifactTypeID())) {
1953 
1954  for (Column currColumn : ReportGenerator.this.columnHeaderMap.get(this.artifact.getArtifactTypeID())) {
1955  String cellData = currColumn.getCellData(this);
1956  orderedRowData.add(cellData);
1957  }
1958  }
1959  }
1960 
1961  return orderedRowData;
1962  }
1963 
1964  }
1965 
1975  @SuppressWarnings("deprecation")
1976  private HashSet<String> getUniqueTagNames(long artifactId) throws TskCoreException {
1977  HashSet<String> uniqueTagNames = new HashSet<>();
1978 
1979  String query = "SELECT display_name, artifact_id FROM tag_names AS tn, blackboard_artifact_tags AS bat " + //NON-NLS
1980  "WHERE tn.tag_name_id = bat.tag_name_id AND bat.artifact_id = " + artifactId; //NON-NLS
1981 
1982  try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
1983  ResultSet tagNameRows = dbQuery.getResultSet();
1984  while (tagNameRows.next()) {
1985  uniqueTagNames.add(tagNameRows.getString("display_name")); //NON-NLS
1986  }
1987  } catch (TskCoreException | SQLException ex) {
1988  throw new TskCoreException("Error getting tag names for artifact: ", ex);
1989  }
1990 
1991  return uniqueTagNames;
1992 
1993  }
1994 
1995  private interface Column {
1996 
1997  String getColumnHeader();
1998 
1999  String getCellData(ArtifactData artData);
2000 
2001  Set<BlackboardAttribute.Type> removeTypeFromSet(Set<BlackboardAttribute.Type> types);
2002  }
2003 
2004  private class AttributeColumn implements Column {
2005 
2006  private String columnHeader;
2007  private BlackboardAttribute.Type attributeType;
2008 
2015  AttributeColumn(String columnHeader, BlackboardAttribute.Type attributeType) {
2016  this.columnHeader = Objects.requireNonNull(columnHeader);
2018  }
2019 
2020  @Override
2021  public String getColumnHeader() {
2022  return this.columnHeader;
2023  }
2024 
2025  @Override
2026  public String getCellData(ArtifactData artData) {
2027  List<BlackboardAttribute> attributes = artData.getAttributes();
2028  for (BlackboardAttribute attribute : attributes) {
2029  if (attribute.getAttributeType().equals(this.attributeType)) {
2030  if (attribute.getAttributeType().getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
2031  return attribute.getDisplayString();
2032  } else {
2033  return ContentUtils.getStringTime(attribute.getValueLong(), artData.getContent());
2034  }
2035  }
2036  }
2037  return "";
2038  }
2039 
2040  @Override
2041  public Set<BlackboardAttribute.Type> removeTypeFromSet(Set<Type> types) {
2042  types.remove(this.attributeType);
2043  return types;
2044  }
2045  }
2046 
2047  private class SourceFileColumn implements Column {
2048 
2049  private String columnHeader;
2050 
2051  SourceFileColumn(String columnHeader) {
2052  this.columnHeader = columnHeader;
2053  }
2054 
2055  @Override
2056  public String getColumnHeader() {
2057  return this.columnHeader;
2058  }
2059 
2060  @Override
2061  public String getCellData(ArtifactData artData) {
2062  return getFileUniquePath(artData.getContent());
2063  /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) {
2064  return makeCommaSeparatedList(artData.getTags());
2065  }
2066  return "";*/
2067  }
2068 
2069  @Override
2070  public Set<BlackboardAttribute.Type> removeTypeFromSet(Set<Type> types) {
2071  // This column doesn't have a type, so nothing to remove
2072  return types;
2073  }
2074  }
2075 
2076  private class TaggedResultsColumn implements Column {
2077 
2078  private String columnHeader;
2079 
2080  TaggedResultsColumn(String columnHeader) {
2081  this.columnHeader = columnHeader;
2082  }
2083 
2084  @Override
2085  public String getColumnHeader() {
2086  return this.columnHeader;
2087  }
2088 
2089  @Override
2090  public String getCellData(ArtifactData artData) {
2091  return makeCommaSeparatedList(artData.getTags());
2092  }
2093 
2094  @Override
2095  public Set<BlackboardAttribute.Type> removeTypeFromSet(Set<Type> types) {
2096  // This column doesn't have a type, so nothing to remove
2097  return types;
2098  }
2099  }
2100 
2101  private class HeaderOnlyColumn implements Column {
2102 
2103  private String columnHeader;
2104 
2105  HeaderOnlyColumn(String columnHeader) {
2106  this.columnHeader = columnHeader;
2107  }
2108 
2109  @Override
2110  public String getColumnHeader() {
2111  return columnHeader;
2112  }
2113 
2114  @Override
2115  public String getCellData(ArtifactData artData) {
2116  throw new UnsupportedOperationException("Cannot get cell data of unspecified column");
2117  }
2118 
2119  @Override
2120  public Set<BlackboardAttribute.Type> removeTypeFromSet(Set<Type> types) {
2121  // This column doesn't have a type, so nothing to remove
2122  return types;
2123  }
2124  }
2125 }
static String getStringTime(long epochSeconds, TimeZone tzone)
static boolean thumbnailSupported(Content content)
void generateReport(String baseReportDir, ReportProgressPanel progressPanel)
Set< BlackboardAttribute.Type > removeTypeFromSet(Set< BlackboardAttribute.Type > types)
Set< BlackboardAttribute.Type > removeTypeFromSet(Set< Type > types)
synchronized List< BlackboardArtifactTag > getAllBlackboardArtifactTags()
Set< BlackboardAttribute.Type > removeTypeFromSet(Set< Type > types)
Set< BlackboardAttribute.Type > removeTypeFromSet(Set< Type > types)
static void show(String title, String message, MessageType type, ActionListener actionListener)
synchronized List< ContentTag > getAllContentTags()
Set< BlackboardAttribute.Type > removeTypeFromSet(Set< Type > types)

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.