19 package org.sleuthkit.autopsy.contentviewers;
 
   21 import java.awt.Component;
 
   22 import java.awt.Cursor;
 
   23 import java.text.MessageFormat;
 
   24 import java.util.Arrays;
 
   25 import java.util.Collections;
 
   26 import java.util.List;
 
   27 import java.util.concurrent.ExecutionException;
 
   28 import java.util.logging.Level;
 
   29 import java.util.stream.Stream;
 
   30 import javax.swing.SwingWorker;
 
   31 import org.apache.commons.lang3.StringUtils;
 
   32 import org.openide.nodes.Node;
 
   33 import org.openide.util.NbBundle;
 
   34 import org.openide.util.NbBundle.Messages;
 
   35 import org.openide.util.lookup.ServiceProvider;
 
   59 @ServiceProvider(service = DataContentViewer.class, position = 4)
 
   60 @SuppressWarnings(
"PMD.SingularField") 
 
   72         customizeComponents();
 
   81     @SuppressWarnings(
"unchecked")
 
   83     private 
void initComponents() {
 
   85         jPopupMenu1 = 
new javax.swing.JPopupMenu();
 
   86         jScrollPane2 = 
new javax.swing.JScrollPane();
 
   87         jTextPane1 = 
new javax.swing.JTextPane();
 
   89         setPreferredSize(
new java.awt.Dimension(100, 52));
 
   91         jScrollPane2.setPreferredSize(
new java.awt.Dimension(610, 52));
 
   93         jTextPane1.setEditable(
false);
 
   94         jTextPane1.setPreferredSize(
new java.awt.Dimension(600, 52));
 
   95         jScrollPane2.setViewportView(jTextPane1);
 
   97         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
   98         this.setLayout(layout);
 
   99         layout.setHorizontalGroup(
 
  100             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  101             .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  103         layout.setVerticalGroup(
 
  104             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  105             .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  129         jTextPane1.setText(
"<html><head></head><body>" + str + 
"</body></html>"); 
 
  132     private void addHeader(StringBuilder sb, String header, 
boolean spaced) {
 
  133         sb.append(MessageFormat.format(
"<div class=\"{0}\"><h1 class=\"{1}\">{2}</h1></div>",
 
  140         sb.append(MessageFormat.format(
"<table class=\"{0}\" valign=\"top\" align=\"left\"><tbody>",
 
  145         sb.append(
"</tbody></table>"); 
 
  148     private void addRow(StringBuilder sb, String key, String value) {
 
  149         sb.append(MessageFormat.format(
"<tr><td class=\"{0}\"><span class=\"{1}\">{2}:</span></td><td class=\"{3}\">{4}</td></tr>",
 
  159         sb.append(MessageFormat.format(
"<tr><td class=\"{0}\"><span class=\"{1}\">{2}</span></td></tr>",
 
  167         String[] safeValues = values == null || values.length < 1 ? 
new String[]{
""} : values;
 
  169         addRow(sb, key, safeValues[0]);
 
  170         Stream.of(safeValues)
 
  172                 .filter(line -> line != null)
 
  177         "Metadata.headerTitle=Metadata",
 
  178         "Metadata.tableRowTitle.mimeType=MIME Type",
 
  179         "Metadata.nodeText.truncated=(results truncated)",
 
  180         "Metadata.tableRowTitle.sha1=SHA1",
 
  181         "Metadata.tableRowTitle.sha256=SHA-256",
 
  182         "Metadata.tableRowTitle.imageType=Type",
 
  183         "Metadata.tableRowTitle.sectorSize=Sector Size",
 
  184         "Metadata.tableRowTitle.timezone=Time Zone",
 
  185         "Metadata.tableRowTitle.deviceId=Device ID",
 
  186         "Metadata.tableRowTitle.acquisitionDetails=Acquisition Details",
 
  187         "Metadata.tableRowTitle.downloadSource=Downloaded From",
 
  188         "Metadata.nodeText.unknown=Unknown",
 
  189         "Metadata.nodeText.none=None",
 
  190         "Metadata.nodeText.loading=Metadata loading..."})
 
  194         if (worker != null) {
 
  200             setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  201             setText(Bundle.Metadata_nodeText_loading());
 
  206                         if (!isCancelled()) {
 
  208                             jTextPane1.setCaretPosition(0);
 
  210                     } 
catch (InterruptedException | ExecutionException ex) {
 
  211                         LOGGER.log(Level.SEVERE, 
"Failed to get metaData for node " + node.getName(), ex);
 
  214                     setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
  234         if (associatedArtifact != null
 
  238             if (urlAttr != null) {
 
  239                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.downloadSource"), urlAttr.
getValueString());
 
  251         if (dataSource != null) {
 
  254                 if (StringUtils.isEmpty(details)) {
 
  255                     details = Bundle.Metadata_nodeText_unknown();
 
  257                 String[] lines = (details != null) ? details.split(
"\n") : 
new String[]{
""};
 
  258                 addRowWithMultipleValues(sb,
 
  259                         NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.acquisitionDetails"),
 
  263                 LOGGER.log(Level.SEVERE, 
"Error reading acquisition details from case database", ex); 
 
  270         return getTitle(null);
 
  274         "Metadata_dataArtifactTitle=Source File Metadata" 
  278         if (node != null && !node.getLookup().lookupAll(
DataArtifact.class).isEmpty()) {
 
  279             return Bundle.Metadata_dataArtifactTitle();
 
  281             return NbBundle.getMessage(this.getClass(), 
"Metadata.title");
 
  287         return NbBundle.getMessage(this.getClass(), 
"Metadata.toolTip");
 
  307         Image image = node.getLookup().lookup(
Image.class);
 
  309         return (file != null) || (image != null);
 
  328         @Messages(
"MetadataWorker.doInBackground.noDataMsg=No Data")
 
  332             Image image = node.getLookup().lookup(
Image.class);
 
  334             if (file == null && image == null) {
 
  335                 return NbBundle.getMessage(this.getClass(), 
"Metadata.nodeText.nonFilePassedIn");
 
  338             StringBuilder sb = 
new StringBuilder();
 
  339             addHeader(sb, Bundle.Metadata_headerTitle(), 
false);
 
  344                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.name"), file.
getUniquePath());
 
  346                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.name"), file.
getParentPath() + 
"/" + file.
getName());
 
  349                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.type"), file.
getType().getName());
 
  350                 addRow(sb, Bundle.Metadata_tableRowTitle_mimeType(), file.
getMIMEType());
 
  351                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.size"), Long.toString(file.
getSize()));
 
  352                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.fileNameAlloc"), file.
getDirFlagAsString());
 
  353                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.metadataAlloc"), file.
getMetaFlagsAsString());
 
  361                     md5 = NbBundle.getMessage(this.getClass(), 
"Metadata.tableRowContent.md5notCalc");
 
  363                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.md5"), md5);
 
  365                 if (sha256 == null) {
 
  366                     sha256 = NbBundle.getMessage(this.getClass(), 
"Metadata.tableRowContent.md5notCalc");
 
  368                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.sha256"), sha256);
 
  369                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.hashLookupResults"), file.
getKnown().toString());
 
  370                 addAcquisitionDetails(sb, dataSource);
 
  372                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.internalid"), Long.toString(file.
getId()));
 
  374                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.localPath"), file.
getLocalAbsPath());
 
  379                     if (!associatedObjectArtifacts.isEmpty()) {
 
  382                         if (associatedArtifactAttribute != null) {
 
  383                             long artifactId = associatedArtifactAttribute.
getValueLong();
 
  385                             addDownloadSourceRow(sb, associatedArtifact);
 
  389                     sb.append(NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.exceptionNotice.text")).append(ex.getLocalizedMessage());
 
  399                     FsContent fsFile = (FsContent) file;
 
  401                     addHeader(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.text"), 
true);
 
  403                     List<String> istatStrings = Collections.emptyList();
 
  407                         istatStrings = Arrays.asList(NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.exceptionNotice.text") + ex.getLocalizedMessage());
 
  410                     if (istatStrings.isEmpty() || (istatStrings.size() == 1 && StringUtils.isEmpty(istatStrings.get(0)))) {
 
  411                         sb.append(MessageFormat.format(
"<div class=\"{0}\"><p class=\"{1}\">{2}</p><div>",
 
  414                                 Bundle.MetadataWorker_doInBackground_noDataMsg()));
 
  418                         for (String str : istatStrings) {
 
  419                             addMonospacedRow(sb, str);
 
  425                             if (sb.length() > 50000) {
 
  426                                 addMonospacedRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.truncated"));
 
  437                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.name"), image.
getUniquePath());
 
  439                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.name"), image.
getName());
 
  441                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.imageType"), image.
getType().getName());
 
  442                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.size"), Long.toString(image.
getSize()));
 
  445                     String md5 = image.
getMd5();
 
  446                     if (md5 == null || md5.isEmpty()) {
 
  447                         md5 = NbBundle.getMessage(this.getClass(), 
"Metadata.tableRowContent.md5notCalc");
 
  449                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.md5"), md5);
 
  452                     if (sha1 == null || sha1.isEmpty()) {
 
  453                         sha1 = NbBundle.getMessage(this.getClass(), 
"Metadata.tableRowContent.md5notCalc");
 
  455                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.sha1"), sha1);
 
  458                     if (sha256 == null || sha256.isEmpty()) {
 
  459                         sha256 = NbBundle.getMessage(this.getClass(), 
"Metadata.tableRowContent.md5notCalc");
 
  461                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.sha256"), sha256);
 
  463                     sb.append(NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.exceptionNotice.text")).append(ex.getLocalizedMessage());
 
  465                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.sectorSize"), Long.toString(image.
getSsize()));
 
  466                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.timezone"), image.
getTimeZone());
 
  467                 addAcquisitionDetails(sb, dataSource);
 
  468                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.deviceId"), image.
getDeviceId());
 
  469                 addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.internalid"), Long.toString(image.
getId()));
 
  472                 String[] imagePaths = image.
getPaths();
 
  474                 if (imagePaths.length > 0) {
 
  475                     addRowWithMultipleValues(sb,
 
  476                             NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.localPath"),
 
  479                     addRow(sb, NbBundle.getMessage(
this.getClass(), 
"Metadata.tableRowTitle.localPath"),
 
  480                             NbBundle.getMessage(
this.getClass(), 
"Metadata.nodeText.none"));
 
  490             return sb.toString();
 
static String escapeHtml(String toEscape)
 
void endTable(StringBuilder sb)
 
String getMetaFlagsAsString()
 
static String getSpacedSectionClassName()
 
void addRow(StringBuilder sb, String key, String value)
 
static String getTextClassName()
 
void addAcquisitionDetails(StringBuilder sb, DataSource dataSource)
 
void addRowWithMultipleValues(StringBuilder sb, String key, String[] values)
 
synchronized List< String > getMetaDataText()
 
TskData.TSK_DB_FILES_TYPE_ENUM getType()
 
static String getFormattedTime(long epochTime)
 
String getAcquisitionDetails()
 
String getDirFlagAsString()
 
javax.swing.JTextPane jTextPane1
 
TskData.TSK_IMG_TYPE_ENUM getType()
 
SleuthkitCase getSleuthkitCase()
 
javax.swing.JPopupMenu jPopupMenu1
 
BlackboardArtifact getBlackboardArtifact(long artifactID)
 
static String getKeyColumnClassName()
 
static String getIndentedClassName()
 
void customizeComponents()
 
TskData.FileKnown getKnown()
 
BlackboardAttribute getAttribute(BlackboardAttribute.Type attributeType)
 
String getTitle(Node node)
 
boolean isSupported(Node node)
 
void addHeader(StringBuilder sb, String header, boolean spaced)
 
void addDownloadSourceRow(StringBuilder sb, BlackboardArtifact associatedArtifact)
 
static void setupHtmlJTextPane(JTextPane textPane)
 
DataContentViewer createInstance()
 
int isPreferred(Node node)
 
static String getHeaderClassName()
 
javax.swing.JScrollPane jScrollPane2
 
static String getMonospacedClassName()
 
synchronized static Logger getLogger(String name)
 
void startTable(StringBuilder sb)
 
ArrayList< BlackboardArtifact > getArtifacts(String artifactTypeName)
 
void addMonospacedRow(StringBuilder sb, String key)