diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED index c9c1535975..c529a8aa9d 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED @@ -46,10 +46,24 @@ DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source fil DefaultTableArtifactContentViewer.attrsTableHeader.sources=Source(s) DefaultTableArtifactContentViewer.attrsTableHeader.type=Type DefaultTableArtifactContentViewer.attrsTableHeader.value=Value -GeneralPurposeArtifactViewer.details.attrHeader=Attributes +GeneralPurposeArtifactViewer.dates.created=Created +GeneralPurposeArtifactViewer.dates.end=End +GeneralPurposeArtifactViewer.dates.start=Start +GeneralPurposeArtifactViewer.dates.time=Time +GeneralPurposeArtifactViewer.details.attrHeader=Details +GeneralPurposeArtifactViewer.details.bookmarkHeader=Bookmark Details +GeneralPurposeArtifactViewer.details.cachedHeader=Cached File +GeneralPurposeArtifactViewer.details.cookieHeader=Cookie Details GeneralPurposeArtifactViewer.details.dataSource=Data Source +GeneralPurposeArtifactViewer.details.datesHeader=Dates +GeneralPurposeArtifactViewer.details.downloadHeader=Downloaded File GeneralPurposeArtifactViewer.details.file=File +GeneralPurposeArtifactViewer.details.historyHeader=Visit Details +GeneralPurposeArtifactViewer.details.otherHeader=Other +GeneralPurposeArtifactViewer.details.searchHeader=Web Search GeneralPurposeArtifactViewer.details.sourceHeader=Source +GeneralPurposeArtifactViewer.noFile.text=\ (no longer exists) +GeneralPurposeArtifactViewer.term.label=Term GeneralPurposeArtifactViewer.unknown.text=Unknown GeneralPurposeArtifactViewer_menuitem_copy=Copy MessageAccountPanel.account.justification=Account found in Message artifact diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form index 7fb4b28206..c2451e28cb 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form @@ -1,11 +1,6 @@
- - - - - @@ -16,18 +11,30 @@ + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java index ae3714a1a2..6dbf8f34e5 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java @@ -29,6 +29,7 @@ import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,6 +40,7 @@ import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.SwingUtilities; +import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.coreutils.Logger; @@ -55,7 +57,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ @ServiceProvider(service = ArtifactContentViewer.class) public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { - + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GeneralPurposeArtifactViewer.class.getName()); // Number of columns in the gridbag layout. @@ -76,6 +78,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()}; + private static final List TYPES_WITH_DATE_SECTION = Arrays.asList(new Integer[]{BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()}); private final GridBagLayout gridBagLayout = new GridBagLayout(); private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); private final Map orderingMap = new HashMap<>(); @@ -85,15 +88,53 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i */ @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public GeneralPurposeArtifactViewer() { - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID(), DEFAULT_ORDERING); - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID(), DEFAULT_ORDERING); - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), DEFAULT_ORDERING); - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), DEFAULT_ORDERING); - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), DEFAULT_ORDERING); - orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID(), DEFAULT_ORDERING); + addOrderings(); initComponents(); + detailsPanel.setLayout(gridBagLayout); } + /** + * Private helper method to add the orderings used for each artifact type to + * the map for lookup. + */ + private void addOrderings() { + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID(), new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()}); + } + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @NbBundle.Messages({"GeneralPurposeArtifactViewer.unknown.text=Unknown"}) @Override @@ -114,15 +155,14 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i attributeMap.put(bba.getAttributeType().getTypeID(), attrList); } dataSourceName = artifact.getDataSource().getName(); - sourceFileName = artifact.getParent().getName(); + sourceFileName = artifact.getParent().getUniquePath(); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get attributes for artifact " + artifact.getArtifactID(), ex); } updateView(artifact, attributeMap, dataSourceName, sourceFileName); } - this.setLayout(this.gridBagLayout); - this.revalidate(); - this.repaint(); + revalidate(); + repaint(); } /** @@ -131,7 +171,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void resetComponent() { // clear the panel - this.removeAll(); + detailsPanel.removeAll(); gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; gridBagConstraints.gridy = 0; gridBagConstraints.gridx = LABEL_COLUMN; @@ -140,28 +180,35 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.insets = ROW_INSETS; } - + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public Component getComponent() { - // Slap a vertical scrollbar on the panel. - return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + // Slap a vertical scrollbar on the panel + return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); } - + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override + public boolean isSupported(BlackboardArtifact artifact) { return (artifact != null) && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() - || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()); + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_ACCOUNT_TYPE.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL.getTypeID()); } - - @NbBundle.Messages({"GeneralPurposeArtifactViewer.details.attrHeader=Attributes", + + @NbBundle.Messages({"GeneralPurposeArtifactViewer.details.attrHeader=Details", "GeneralPurposeArtifactViewer.details.sourceHeader=Source", "GeneralPurposeArtifactViewer.details.dataSource=Data Source", - "GeneralPurposeArtifactViewer.details.file=File"}) + "GeneralPurposeArtifactViewer.details.file=File", + "GeneralPurposeArtifactViewer.details.datesHeader=Dates"}) /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -171,18 +218,22 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i // //GEN-BEGIN:initComponents private void initComponents() { - setPreferredSize(new java.awt.Dimension(0, 0)); + detailsPanel = new javax.swing.JPanel(); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) + setLayout(new java.awt.BorderLayout()); + + javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); + detailsPanel.setLayout(detailsPanelLayout); + detailsPanelLayout.setHorizontalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) + detailsPanelLayout.setVerticalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) ); + + add(detailsPanel, java.awt.BorderLayout.PAGE_START); }// //GEN-END:initComponents /** @@ -195,11 +246,18 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i * @param sourceFileName The name of the file that caused the creation of * the artifact. */ + @NbBundle.Messages({"GeneralPurposeArtifactViewer.dates.created=Created", + "GeneralPurposeArtifactViewer.dates.start=Start", + "GeneralPurposeArtifactViewer.dates.end=End", + "GeneralPurposeArtifactViewer.dates.time=Time", + "GeneralPurposeArtifactViewer.term.label=Term", + "GeneralPurposeArtifactViewer.details.otherHeader=Other", + "GeneralPurposeArtifactViewer.noFile.text= (no longer exists)"}) @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private void updateView(BlackboardArtifact artifact, Map> attributeMap, String dataSourceName, String sourceFileName) { + private void updateView(BlackboardArtifact artifact, Map> attributeMap, String dataSourceName, String sourceFilePath) { final Integer artifactTypeId = artifact.getArtifactTypeID(); if (!(artifactTypeId < 1 || artifactTypeId >= Integer.MAX_VALUE)) { - addHeader(Bundle.GeneralPurposeArtifactViewer_details_attrHeader()); + addDetailsHeader(artifactTypeId); Integer[] orderingArray = orderingMap.get(artifactTypeId); if (orderingArray == null) { orderingArray = DEFAULT_ORDERING; @@ -208,6 +266,38 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i List attrList = attributeMap.remove(attrId); if (attrList != null) { for (BlackboardAttribute bba : attrList) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { + if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_dates_time(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); + } else { + addNameValueRow(bba.getAttributeType().getDisplayName(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); + } + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID() && artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_term_label(), bba.getDisplayString()); + } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) { + String displayString = bba.getDisplayString(); + if (!attributeMap.containsKey(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID())) { + displayString += Bundle.GeneralPurposeArtifactViewer_noFile_text(); + } + addNameValueRow(bba.getAttributeType().getDisplayName(), displayString); + } else { + addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + + } + } + } + } + if (TYPES_WITH_DATE_SECTION.contains(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID())) { + boolean headerAdded = false; + headerAdded = addDates(Bundle.GeneralPurposeArtifactViewer_dates_created(), attributeMap.remove(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()), headerAdded); + headerAdded = addDates(Bundle.GeneralPurposeArtifactViewer_dates_start(), attributeMap.remove(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()), headerAdded); + headerAdded = addDates(Bundle.GeneralPurposeArtifactViewer_dates_end(), attributeMap.remove(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()), headerAdded); + addDates(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getDisplayName(), attributeMap.remove(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()), headerAdded); + } + if (!attributeMap.keySet().isEmpty()) { + addHeader(Bundle.GeneralPurposeArtifactViewer_details_otherHeader()); + for (int key : attributeMap.keySet()) { + for (BlackboardAttribute bba : attributeMap.get(key)) { if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { addNameValueRow(bba.getAttributeType().getDisplayName(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); } else { @@ -216,23 +306,73 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i } } } - for (int key : attributeMap.keySet()) { - for (BlackboardAttribute bba : attributeMap.get(key)) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { - addNameValueRow(bba.getAttributeType().getDisplayName(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); - } else { - addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - } - } addHeader(Bundle.GeneralPurposeArtifactViewer_details_sourceHeader()); addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_dataSource(), dataSourceName); - addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_file(), sourceFileName); + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_file(), sourceFilePath); // add veritcal glue at the end addPageEndGlue(); } } + /** + * Private helper method to add all dates in a given attribute list. + * + * @param label Specific String to use in place of attributes display + * name. + * @param attrList List of attributes to add dates for. + * @param headerExists If the "Dates" header has already been displayed. + * + * @return True if the "Dates" header has been displayed, false otherwise. + */ + private boolean addDates(String label, List attrList, boolean headerExists) { + boolean headerAdded = headerExists; + if (attrList != null) { + if (!headerAdded) { + addHeader(Bundle.GeneralPurposeArtifactViewer_details_datesHeader()); + headerAdded = true; + } + String labelToUse = label; + for (BlackboardAttribute bba : attrList) { + if (StringUtils.isBlank(label)) { + labelToUse = bba.getAttributeType().getDisplayName(); + } + addNameValueRow(labelToUse, bba.getDisplayString()); + } + } + return headerAdded; + } + + /** + * Helper method to add an artifact specific details header. + * + * @param artifactTypeId ID of artifact type to add header for. + */ + @NbBundle.Messages({"GeneralPurposeArtifactViewer.details.bookmarkHeader=Bookmark Details", + "GeneralPurposeArtifactViewer.details.historyHeader=Visit Details", + "GeneralPurposeArtifactViewer.details.downloadHeader=Downloaded File", + "GeneralPurposeArtifactViewer.details.searchHeader=Web Search", + "GeneralPurposeArtifactViewer.details.cachedHeader=Cached File", + "GeneralPurposeArtifactViewer.details.cookieHeader=Cookie Details",}) + private void addDetailsHeader(int artifactTypeId) { + String header; + if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_historyHeader(); + } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_bookmarkHeader(); + } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_cachedHeader(); + } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_cookieHeader(); + } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_downloadHeader(); + } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { + header = Bundle.GeneralPurposeArtifactViewer_details_searchHeader(); + } else { + header = Bundle.GeneralPurposeArtifactViewer_details_attrHeader(); + } + addHeader(header); + } + /** * Adds a new heading to the panel. * @@ -248,7 +388,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i // the first section if (gridBagConstraints.gridy != 0) { gridBagConstraints.gridy++; - add(new javax.swing.JLabel(" "), gridBagConstraints); + detailsPanel.add(new javax.swing.JLabel(" "), gridBagConstraints); addLineEndGlue(); } gridBagConstraints.gridy++; @@ -261,7 +401,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i // make it large and bold headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); // add to panel - add(headingLabel, gridBagConstraints); + detailsPanel.add(headingLabel, gridBagConstraints); // reset constraints to normal gridBagConstraints.gridwidth = LABEL_WIDTH; // add line end glue @@ -292,7 +432,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i gridBagConstraints.weightx = GLUE_WEIGHT_X; // take up all the horizontal space gridBagConstraints.fill = GridBagConstraints.BOTH; javax.swing.Box.Filler horizontalFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(32767, 0)); - add(horizontalFiller, gridBagConstraints); + detailsPanel.add(horizontalFiller, gridBagConstraints); // restore fill & weight gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.weightx = TEXT_WEIGHT_X; @@ -306,7 +446,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i gridBagConstraints.weighty = 1.0; // take up all the vertical space gridBagConstraints.fill = GridBagConstraints.VERTICAL; javax.swing.Box.Filler vertFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767)); - add(vertFiller, gridBagConstraints); + detailsPanel.add(vertFiller, gridBagConstraints); } /** @@ -325,7 +465,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i // set text keyLabel.setText(keyString + ": "); // add to panel - add(keyLabel, gridBagConstraints); + detailsPanel.add(keyLabel, gridBagConstraints); return keyLabel; } @@ -348,6 +488,8 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i cloneConstraints.fill = GridBagConstraints.BOTH; // set text valueField.setText(valueString); + // scroll to start of text + valueField.setCaretPosition(0); // attach a right click menu with Copy option valueField.addMouseListener(new java.awt.event.MouseAdapter() { @Override @@ -356,7 +498,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i } }); // add label to panel - add(valueField, cloneConstraints); + detailsPanel.add(valueField, cloneConstraints); // end the line addLineEndGlue(); return valueField; @@ -389,5 +531,6 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel detailsPanel; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java index b36e93728a..b56e60aa8f 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractArtifactDetailsPanel.java @@ -18,7 +18,9 @@ */ package org.sleuthkit.autopsy.discovery.ui; +import java.awt.Component; import javax.swing.JPanel; +import javax.swing.JScrollPane; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -28,6 +30,12 @@ import org.sleuthkit.datamodel.BlackboardArtifact; */ public abstract class AbstractArtifactDetailsPanel extends JPanel { + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public Component getComponent() { + // Slap a vertical scrollbar on the panel. + return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + private static final long serialVersionUID = 1L; /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index d549f1d3f8..6cce1aeeb9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -328,6 +328,8 @@ final class ArtifactsListPanel extends AbstractArtifactListPanel { @NbBundle.Messages({"ArtifactsListPanel.titleColumn.name=Title", "ArtifactsListPanel.fileNameColumn.name=Name", "ArtifactsListPanel.dateColumn.name=Date/Time", + "ArtifactsListPanel.urlColumn.name=URL", + "ArtifactsListPanel.termColumn.name=Term", "ArtifactsListPanel.mimeTypeColumn.name=MIME Type"}) @Override public String getColumnName(int column) { @@ -335,11 +337,19 @@ final class ArtifactsListPanel extends AbstractArtifactListPanel { case 0: return Bundle.ArtifactsListPanel_dateColumn_name(); case 1: - if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) { - return Bundle.ArtifactsListPanel_fileNameColumn_name(); - } else { - return Bundle.ArtifactsListPanel_titleColumn_name(); + if (artifactType != null) { + switch (artifactType) { + case TSK_WEB_CACHE: + case TSK_WEB_DOWNLOAD: + return Bundle.ArtifactsListPanel_fileNameColumn_name(); + case TSK_WEB_COOKIE: + return Bundle.ArtifactsListPanel_urlColumn_name(); + case TSK_WEB_SEARCH_QUERY: + return Bundle.ArtifactsListPanel_termColumn_name(); + default: + } } + return Bundle.ArtifactsListPanel_titleColumn_name(); case 2: return Bundle.ArtifactsListPanel_mimeTypeColumn_name(); default: diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index 4f5a801573..3fcce54c93 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -3,7 +3,9 @@ ArtifactMenuMouseAdapter_label=Extract Files ArtifactsListPanel.dateColumn.name=Date/Time ArtifactsListPanel.fileNameColumn.name=Name ArtifactsListPanel.mimeTypeColumn.name=MIME Type +ArtifactsListPanel.termColumn.name=Term ArtifactsListPanel.titleColumn.name=Title +ArtifactsListPanel.urlColumn.name=URL ArtifactsListPanel.value.noValue=No value available. ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected. CTL_OpenDiscoveryAction=Discovery diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 1bc31e1d9b..3bc5ae14a7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -91,7 +91,7 @@ final class DomainArtifactsTabPanel extends JPanel { break; } if (rightPanel != null) { - jSplitPane1.setRightComponent(new JScrollPane(rightPanel)); + jSplitPane1.setRightComponent(rightPanel.getComponent()); } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/MiniTimelinePanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/MiniTimelinePanel.java index ad7dc0bcb5..f577622a36 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/MiniTimelinePanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/MiniTimelinePanel.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.discovery.ui; import com.google.common.eventbus.Subscribe; import java.util.logging.Level; -import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -64,7 +63,7 @@ class MiniTimelinePanel extends javax.swing.JPanel { rightPanel = new GeneralPurposeArtifactViewer(); } rightPanel.setArtifact(artifact); - mainSplitPane.setRightComponent(new JScrollPane(rightPanel)); + mainSplitPane.setRightComponent(rightPanel.getComponent()); validate(); repaint(); } @@ -88,7 +87,7 @@ class MiniTimelinePanel extends javax.swing.JPanel { artifactListPanel.addSelectionListener(artifactListener); leftSplitPane.setLeftComponent(dateListPanel); leftSplitPane.setRightComponent(artifactListPanel); - mainSplitPane.setRightComponent(rightPanel); + mainSplitPane.setRightComponent(rightPanel.getComponent()); } /**