mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 1205-download-source
This commit is contained in:
commit
90177a7fb6
@ -6,3 +6,4 @@ DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
||||
DataContentViewerOtherCases.earliestCaseDate.text=Earliest Case Date
|
||||
DataContentViewerOtherCases.earliestCaseLabel.toolTipText=
|
||||
DataContentViewerOtherCases.earliestCaseLabel.text=Central Repository Starting Date:
|
||||
DataContentViewerOtherCases.foundInLabel.text=
|
||||
|
@ -73,7 +73,7 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="otherCasesPanel" pref="58" max="32767" attributes="0"/>
|
||||
<Component id="otherCasesPanel" pref="53" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -96,10 +96,10 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="483" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="61" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tableContainerPanel" pref="58" max="32767" attributes="0"/>
|
||||
<Component id="tableContainerPanel" pref="53" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -117,31 +117,28 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="tableStatusPanel" pref="1282" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="218" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tableScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tableScrollPane" alignment="0" pref="1508" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="earliestCaseLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="earliestCaseDate" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="66" max="-2" attributes="0"/>
|
||||
<Component id="foundInLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="1157" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="tableScrollPane" pref="27" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<Component id="tableScrollPane" pref="71" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="foundInLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="tableStatusPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -198,26 +195,13 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="tableStatusPanel">
|
||||
<Component class="javax.swing.JLabel" name="foundInLabel">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[1500, 16]"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.foundInLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="16" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2018 Basis Technology Corp.
|
||||
* Copyright 2015-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -33,10 +33,12 @@ import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.JFileChooser;
|
||||
@ -46,9 +48,13 @@ import static javax.swing.JOptionPane.DEFAULT_OPTION;
|
||||
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.openide.nodes.Node;
|
||||
@ -139,6 +145,19 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
||||
otherCasesTable.setDefaultRenderer(Object.class, renderer);
|
||||
|
||||
// Configure column sorting.
|
||||
TableRowSorter<TableModel> sorter = new TableRowSorter<>(otherCasesTable.getModel());
|
||||
otherCasesTable.setRowSorter(sorter);
|
||||
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
|
||||
|
||||
int caseNameColumnIndex = DataContentViewerOtherCasesTableModel.TableColumns.CASE_NAME.ordinal();
|
||||
sortKeys.add(new RowSorter.SortKey(caseNameColumnIndex, SortOrder.ASCENDING));
|
||||
|
||||
int dataSourceColumnIndex = DataContentViewerOtherCasesTableModel.TableColumns.DATA_SOURCE.ordinal();
|
||||
sortKeys.add(new RowSorter.SortKey(dataSourceColumnIndex, SortOrder.ASCENDING));
|
||||
|
||||
sorter.setSortKeys(sortKeys);
|
||||
sorter.sort();
|
||||
}
|
||||
|
||||
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
||||
@ -306,6 +325,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
tableModel.clearTable();
|
||||
correlationAttributes.clear();
|
||||
earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
|
||||
foundInLabel.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -338,6 +358,40 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of unique cases and data sources.
|
||||
*/
|
||||
@Messages({
|
||||
"DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources."
|
||||
})
|
||||
private void setOccurrenceCounts() {
|
||||
DataContentViewerOtherCasesTableModel model = (DataContentViewerOtherCasesTableModel) otherCasesTable.getModel();
|
||||
|
||||
int caseColumnIndex = DataContentViewerOtherCasesTableModel.TableColumns.CASE_NAME.ordinal();
|
||||
int deviceColumnIndex = DataContentViewerOtherCasesTableModel.TableColumns.DEVICE.ordinal();
|
||||
|
||||
/*
|
||||
* We need a unique set of data sources. We rely on device ID for this.
|
||||
* To mitigate edge cases where a device ID could be duplicated in the
|
||||
* same case (e.g. "report.xml"), we put the device ID and case name in
|
||||
* a key-value pair.
|
||||
*
|
||||
* Note: Relying on the case name isn't a fool-proof way of determining
|
||||
* a case to be unique. We should improve this in the future.
|
||||
*/
|
||||
Set<String> cases = new HashSet<>();
|
||||
Map<String, String> devices = new HashMap();
|
||||
|
||||
for (int i=0; i < model.getRowCount(); i++) {
|
||||
String caseName = (String) model.getValueAt(i, caseColumnIndex);
|
||||
String deviceId = (String) model.getValueAt(i, deviceColumnIndex);
|
||||
cases.add(caseName);
|
||||
devices.put(deviceId, caseName);
|
||||
}
|
||||
|
||||
foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), model.getRowCount(), cases.size(), devices.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated BlackboardArtifact from a node, if it exists.
|
||||
*
|
||||
@ -720,7 +774,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
} else {
|
||||
setColumnWidths();
|
||||
}
|
||||
|
||||
setEarliestCaseDate();
|
||||
setOccurrenceCounts();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -772,7 +828,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
otherCasesTable = new javax.swing.JTable();
|
||||
earliestCaseLabel = new javax.swing.JLabel();
|
||||
earliestCaseDate = new javax.swing.JLabel();
|
||||
tableStatusPanel = new javax.swing.JPanel();
|
||||
foundInLabel = new javax.swing.JLabel();
|
||||
|
||||
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
||||
@ -818,44 +874,31 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseDate.text")); // NOI18N
|
||||
|
||||
tableStatusPanel.setPreferredSize(new java.awt.Dimension(1500, 16));
|
||||
|
||||
javax.swing.GroupLayout tableStatusPanelLayout = new javax.swing.GroupLayout(tableStatusPanel);
|
||||
tableStatusPanel.setLayout(tableStatusPanelLayout);
|
||||
tableStatusPanelLayout.setHorizontalGroup(
|
||||
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
tableStatusPanelLayout.setVerticalGroup(
|
||||
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 16, Short.MAX_VALUE)
|
||||
);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.foundInLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||
tableContainerPanelLayout.setHorizontalGroup(
|
||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||
.addComponent(tableStatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1282, Short.MAX_VALUE)
|
||||
.addGap(218, 218, 218))
|
||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1508, Short.MAX_VALUE)
|
||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||
.addComponent(earliestCaseLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(earliestCaseDate)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(66, 66, 66)
|
||||
.addComponent(foundInLabel)
|
||||
.addGap(0, 1157, Short.MAX_VALUE))
|
||||
);
|
||||
tableContainerPanelLayout.setVerticalGroup(
|
||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
|
||||
.addGap(2, 2, 2)
|
||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 71, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(earliestCaseLabel)
|
||||
.addComponent(earliestCaseDate))
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0))
|
||||
.addComponent(earliestCaseDate)
|
||||
.addComponent(foundInLabel))
|
||||
.addGap(6, 6, 6))
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
|
||||
@ -868,10 +911,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
);
|
||||
otherCasesPanelLayout.setVerticalGroup(
|
||||
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 483, Short.MAX_VALUE)
|
||||
.addGap(0, 61, Short.MAX_VALUE)
|
||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE)
|
||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0)))
|
||||
);
|
||||
|
||||
@ -883,7 +926,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE)
|
||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -907,6 +950,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
private javax.swing.JLabel earliestCaseDate;
|
||||
private javax.swing.JLabel earliestCaseLabel;
|
||||
private javax.swing.JMenuItem exportToCSVMenuItem;
|
||||
private javax.swing.JLabel foundInLabel;
|
||||
private javax.swing.JPanel otherCasesPanel;
|
||||
private javax.swing.JTable otherCasesTable;
|
||||
private javax.swing.JPopupMenu rightClickPopupMenu;
|
||||
@ -915,7 +959,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||
private javax.swing.JPanel tableContainerPanel;
|
||||
private javax.swing.JScrollPane tableScrollPane;
|
||||
private javax.swing.JPanel tableStatusPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
|
@ -83,3 +83,4 @@ MediaViewImagePanel.zoomResetButton.text=Reset
|
||||
MediaViewImagePanel.zoomTextField.text=
|
||||
MediaViewImagePanel.rotationTextField.text=
|
||||
MediaViewImagePanel.rotateLeftButton.toolTipText=
|
||||
HtmlPanel.showImagesToggleButton.text=Show Images
|
||||
|
@ -11,6 +11,7 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
<LayoutCode>
|
||||
<CodeStatement>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Copyright 2018-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -49,7 +49,8 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
|
||||
private final FileTypeViewer[] KNOWN_VIEWERS = new FileTypeViewer[]{
|
||||
new SQLiteViewer(),
|
||||
new PListViewer(),
|
||||
new MediaFileViewer()
|
||||
new MediaFileViewer(),
|
||||
new HtmlViewer()
|
||||
};
|
||||
|
||||
private FileTypeViewer lastViewer;
|
||||
|
65
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.form
Executable file
65
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.form
Executable file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlScrollPane" pref="300" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="htmlScrollPane" pref="71" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="htmlScrollPane">
|
||||
<Properties>
|
||||
<Property name="verticalScrollBarPolicy" type="int" value="22"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextPane" name="htmlbodyTextPane">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JToggleButton" name="showImagesToggleButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="HtmlPanel.showImagesToggleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showImagesToggleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
165
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java
Executable file
165
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java
Executable file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
* A file content viewer for HTML files.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class HtmlPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String htmlText;
|
||||
|
||||
/**
|
||||
* Creates new form HtmlViewerPanel
|
||||
*/
|
||||
HtmlPanel() {
|
||||
initComponents();
|
||||
|
||||
Utilities.configureTextPaneAsHtml(htmlbodyTextPane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text pane's HTML text and refresh the view to display it.
|
||||
*
|
||||
* @param htmlText The HTML text to be applied to the text pane.
|
||||
*/
|
||||
void setHtmlText(String htmlText) {
|
||||
this.htmlText = htmlText;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the HTML in the text pane and disable the show/hide button.
|
||||
*/
|
||||
void reset() {
|
||||
htmlbodyTextPane.setText("");
|
||||
showImagesToggleButton.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guarantee the HTML text has 'html' and 'body' tags.
|
||||
*
|
||||
* @param htmlText The HTML text
|
||||
*
|
||||
* @return The HTML text with the 'html' and 'body' tags applied.
|
||||
*/
|
||||
private String wrapInHtmlBody(String htmlText) {
|
||||
return "<html><body>" + htmlText + "</body></html>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out input HTML string
|
||||
*
|
||||
* @param htmlInString The HTML string to cleanse
|
||||
*
|
||||
* @return The cleansed HTML String
|
||||
*/
|
||||
private String cleanseHTML(String htmlInString) {
|
||||
|
||||
Document doc = Jsoup.parse(htmlInString);
|
||||
|
||||
// Update all 'img' tags.
|
||||
doc.select("img[src]").forEach(img -> img.attr("src", ""));
|
||||
|
||||
return doc.html();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the panel to reflect the current show/hide images setting.
|
||||
*/
|
||||
@Messages({
|
||||
"HtmlPanel_showImagesToggleButton_show=Show Images",
|
||||
"HtmlPanel_showImagesToggleButton_hide=Hide Images"
|
||||
})
|
||||
private void refresh() {
|
||||
if (false == htmlText.isEmpty()) {
|
||||
if (showImagesToggleButton.isSelected()) {
|
||||
showImagesToggleButton.setText(Bundle.HtmlPanel_showImagesToggleButton_hide());
|
||||
this.htmlbodyTextPane.setText(wrapInHtmlBody(htmlText));
|
||||
} else {
|
||||
showImagesToggleButton.setText(Bundle.HtmlPanel_showImagesToggleButton_show());
|
||||
this.htmlbodyTextPane.setText(wrapInHtmlBody(cleanseHTML(htmlText)));
|
||||
}
|
||||
|
||||
htmlbodyTextPane.setCaretPosition(0);
|
||||
showImagesToggleButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
htmlScrollPane = new javax.swing.JScrollPane();
|
||||
htmlbodyTextPane = new javax.swing.JTextPane();
|
||||
showImagesToggleButton = new javax.swing.JToggleButton();
|
||||
|
||||
htmlScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
|
||||
htmlbodyTextPane.setEditable(false);
|
||||
htmlScrollPane.setViewportView(htmlbodyTextPane);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showImagesToggleButton, org.openide.util.NbBundle.getMessage(HtmlPanel.class, "HtmlPanel.showImagesToggleButton.text")); // NOI18N
|
||||
showImagesToggleButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showImagesToggleButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(htmlScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 71, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showImagesToggleButtonActionPerformed
|
||||
refresh();
|
||||
}//GEN-LAST:event_showImagesToggleButtonActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollPane htmlScrollPane;
|
||||
private javax.swing.JTextPane htmlbodyTextPane;
|
||||
private javax.swing.JToggleButton showImagesToggleButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
40
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlViewer.form
Executable file
40
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlViewer.form
Executable file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
128
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlViewer.java
Executable file
128
Core/src/org/sleuthkit/autopsy/contentviewers/HtmlViewer.java
Executable file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* A file content viewer for HTML files.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class HtmlViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(HtmlViewer.class.getName());
|
||||
|
||||
private static final String[] SUPPORTED_MIMETYPES = new String[]{
|
||||
"text/html",
|
||||
"application/xhtml+xml"
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new form HtmlViewerPanel
|
||||
*/
|
||||
HtmlViewer() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the HTML text content from the supplied file.
|
||||
*
|
||||
* @param abstractFile The file to read.
|
||||
*
|
||||
* @return The text content of the file.
|
||||
*/
|
||||
private String getHtmlText(AbstractFile abstractFile) {
|
||||
try {
|
||||
int fileSize = (int) abstractFile.getSize();
|
||||
byte[] buffer = new byte[fileSize];
|
||||
abstractFile.read(buffer, 0, fileSize);
|
||||
return new String(buffer);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Unable to read from file '%s' (id=%d).",
|
||||
abstractFile.getName(), abstractFile.getId()), ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedMIMETypes() {
|
||||
return Arrays.asList(SUPPORTED_MIMETYPES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFile(AbstractFile file) {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
htmlPanel.setHtmlText(getHtmlText(file));
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetComponent() {
|
||||
htmlPanel.reset();
|
||||
}
|
||||
}
|
@ -126,7 +126,6 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N
|
||||
fxPanel.setScene(scene);
|
||||
|
||||
//bind size of image to that of scene, while keeping proportions
|
||||
fxImageView.setSmooth(true);
|
||||
fxImageView.setCache(true);
|
||||
|
||||
@ -142,11 +141,13 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
}
|
||||
|
||||
/**
|
||||
* clear the displayed image
|
||||
* Clear the displayed image
|
||||
*/
|
||||
public void reset() {
|
||||
Platform.runLater(() -> {
|
||||
fxImageView.setViewport(new Rectangle2D(0, 0, 0, 0));
|
||||
fxImageView.setImage(null);
|
||||
|
||||
scrollPane.setContent(null);
|
||||
scrollPane.setContent(fxImageView);
|
||||
});
|
||||
|
@ -274,50 +274,17 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="533" max="32767" attributes="0"/>
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="htmlPanel" alignment="0" pref="647" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlScrollPane" pref="333" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="htmlPanel" alignment="0" pref="362" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="htmlScrollPane">
|
||||
<Properties>
|
||||
<Property name="verticalScrollBarPolicy" type="int" value="22"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextPane" name="htmlbodyTextPane">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JToggleButton" name="showImagesToggleButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Show Images"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showImagesToggleButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-2018 Basis Technology Corp.
|
||||
* Copyright 2017-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -106,9 +106,12 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
attachmentsScrollPane.setViewportView(drp);
|
||||
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, true);
|
||||
|
||||
textAreas = Arrays.asList(headersTextArea, textbodyTextArea, htmlbodyTextPane, rtfbodyTextPane);
|
||||
/*
|
||||
* HTML tab uses the HtmlPanel instead of an internal text pane, so we
|
||||
* use 'null' for that index.
|
||||
*/
|
||||
textAreas = Arrays.asList(headersTextArea, textbodyTextArea, null, rtfbodyTextPane);
|
||||
|
||||
Utilities.configureTextPaneAsHtml(htmlbodyTextPane);
|
||||
Utilities.configureTextPaneAsRtf(rtfbodyTextPane);
|
||||
resetComponent();
|
||||
|
||||
@ -150,9 +153,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
textbodyScrollPane = new javax.swing.JScrollPane();
|
||||
textbodyTextArea = new javax.swing.JTextArea();
|
||||
htmlPane = new javax.swing.JPanel();
|
||||
htmlScrollPane = new javax.swing.JScrollPane();
|
||||
htmlbodyTextPane = new javax.swing.JTextPane();
|
||||
showImagesToggleButton = new javax.swing.JToggleButton();
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
rtfbodyScrollPane = new javax.swing.JScrollPane();
|
||||
rtfbodyTextPane = new javax.swing.JTextPane();
|
||||
attachmentsPanel = new javax.swing.JPanel();
|
||||
@ -265,35 +266,15 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.textbodyScrollPane.TabConstraints.tabTitle"), textbodyScrollPane); // NOI18N
|
||||
|
||||
htmlScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
|
||||
htmlbodyTextPane.setEditable(false);
|
||||
htmlScrollPane.setViewportView(htmlbodyTextPane);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showImagesToggleButton, "Show Images");
|
||||
showImagesToggleButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showImagesToggleButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
|
||||
htmlPane.setLayout(htmlPaneLayout);
|
||||
htmlPaneLayout.setHorizontalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlScrollPane)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, htmlPaneLayout.createSequentialGroup()
|
||||
.addContainerGap(533, Short.MAX_VALUE)
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addGap(3, 3, 3))
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
|
||||
);
|
||||
htmlPaneLayout.setVerticalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(htmlPaneLayout.createSequentialGroup()
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(htmlScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0))
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
|
||||
@ -358,26 +339,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@NbBundle.Messages({
|
||||
"MessageContentViewer.showImagesToggleButton.hide.text=Hide Images",
|
||||
"MessageContentViewer.showImagesToggleButton.text=Show Images"})
|
||||
private void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showImagesToggleButtonActionPerformed
|
||||
try {
|
||||
String htmlText = getAttributeValueSafe(artifact, TSK_EMAIL_CONTENT_HTML);
|
||||
if (false == htmlText.isEmpty()) {
|
||||
if (showImagesToggleButton.isSelected()) {
|
||||
showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_hide_text());
|
||||
this.htmlbodyTextPane.setText(wrapInHtmlBody(htmlText));
|
||||
} else {
|
||||
showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_text());
|
||||
this.htmlbodyTextPane.setText(wrapInHtmlBody(cleanseHTML(htmlText)));
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
|
||||
}
|
||||
}//GEN-LAST:event_showImagesToggleButtonActionPerformed
|
||||
|
||||
private void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInNewWindowButtonActionPerformed
|
||||
new NewWindowViewAction("View in new window", drpExplorerManager.getSelectedNodes()[0]).actionPerformed(evt);
|
||||
}//GEN-LAST:event_viewInNewWindowButtonActionPerformed
|
||||
@ -396,12 +357,10 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
private javax.swing.JScrollPane headersScrollPane;
|
||||
private javax.swing.JTextArea headersTextArea;
|
||||
private javax.swing.JPanel htmlPane;
|
||||
private javax.swing.JScrollPane htmlScrollPane;
|
||||
private javax.swing.JTextPane htmlbodyTextPane;
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
private javax.swing.JTabbedPane msgbodyTabbedPane;
|
||||
private javax.swing.JScrollPane rtfbodyScrollPane;
|
||||
private javax.swing.JTextPane rtfbodyTextPane;
|
||||
private javax.swing.JToggleButton showImagesToggleButton;
|
||||
private javax.swing.JLabel subjectLabel;
|
||||
private javax.swing.JLabel subjectText;
|
||||
private javax.swing.JScrollPane textbodyScrollPane;
|
||||
@ -505,9 +464,8 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
headersTextArea.setText("");
|
||||
rtfbodyTextPane.setText("");
|
||||
htmlbodyTextPane.setText("");
|
||||
htmlPanel.reset();
|
||||
textbodyTextArea.setText("");
|
||||
showImagesToggleButton.setEnabled(false);
|
||||
msgbodyTabbedPane.setEnabled(false);
|
||||
}
|
||||
|
||||
@ -567,12 +525,15 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
String attributeText = getAttributeValueSafe(artifact, type);
|
||||
|
||||
if (index == HTML_TAB_INDEX && StringUtils.isNotBlank(attributeText)) {
|
||||
//special case for HTML, we need to 'cleanse' it
|
||||
attributeText = wrapInHtmlBody(cleanseHTML(attributeText));
|
||||
}
|
||||
htmlPanel.setHtmlText(attributeText);
|
||||
} else {
|
||||
JTextComponent textComponent = textAreas.get(index);
|
||||
if (textComponent != null) {
|
||||
textComponent.setText(attributeText);
|
||||
textComponent.setCaretPosition(0); //make sure we start at the top
|
||||
}
|
||||
}
|
||||
|
||||
final boolean hasText = attributeText.length() > 0;
|
||||
|
||||
msgbodyTabbedPane.setEnabledAt(index, hasText);
|
||||
@ -613,10 +574,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
directionText.setEnabled(false);
|
||||
ccLabel.setEnabled(true);
|
||||
|
||||
showImagesToggleButton.setEnabled(true);
|
||||
showImagesToggleButton.setText("Show Images");
|
||||
showImagesToggleButton.setSelected(false);
|
||||
|
||||
try {
|
||||
this.fromText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
|
||||
this.fromText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
|
||||
|
@ -302,8 +302,9 @@ class MSOfficeEmbeddedContentExtractor {
|
||||
}
|
||||
List<ExtractedFile> listOfExtractedImages = new ArrayList<>();
|
||||
byte[] data = null;
|
||||
int pictureNumber = 0; //added to ensure uniqueness in cases where suggestFullFileName returns duplicates
|
||||
for (Picture picture : listOfAllPictures) {
|
||||
String fileName = picture.suggestFullFileName();
|
||||
String fileName = UNKNOWN_IMAGE_NAME_PREFIX +pictureNumber +"."+ picture.suggestFileExtension();
|
||||
try {
|
||||
data = picture.getContent();
|
||||
} catch (Exception ex) {
|
||||
@ -312,6 +313,7 @@ class MSOfficeEmbeddedContentExtractor {
|
||||
writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data);
|
||||
// TODO Extract more info from the Picture viz ctime, crtime, atime, mtime
|
||||
listOfExtractedImages.add(new ExtractedFile(fileName, getFileRelativePath(fileName), picture.getSize()));
|
||||
pictureNumber++;
|
||||
}
|
||||
|
||||
return listOfExtractedImages;
|
||||
|
@ -38,6 +38,9 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.datamodel.utils.FileTypeUtils.FileTypeCategory;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.FileSystem;
|
||||
@ -47,6 +50,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.datamodel.VolumeSystem;
|
||||
@ -66,7 +70,7 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
FileTypeCategory.EXECUTABLE, FileTypeCategory.IMAGE, FileTypeCategory.VIDEO);
|
||||
|
||||
private Case currentCase = null;
|
||||
private SleuthkitCase skCase = null;
|
||||
private SleuthkitCase portableSkCase = null;
|
||||
private File caseFolder = null;
|
||||
private File copiedFilesFolder = null;
|
||||
|
||||
@ -79,6 +83,15 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
// Maps old TagName to new TagName
|
||||
private final Map<TagName, TagName> oldTagNameToNewTagName = new HashMap<>();
|
||||
|
||||
// Map of old artifact type ID to new artifact type ID. There will only be changes if custom artifact types are present.
|
||||
private final Map<Integer, Integer> oldArtTypeIdToNewArtTypeId = new HashMap<>();
|
||||
|
||||
// Map of old attribute type ID to new attribute type ID. There will only be changes if custom attr types are present.
|
||||
private final Map<Integer, BlackboardAttribute.Type> oldAttrTypeIdToNewAttrType = new HashMap<>();
|
||||
|
||||
// Map of old artifact ID to new artifact
|
||||
private final Map<Long, BlackboardArtifact> oldArtifactIdToNewArtifact = new HashMap<>();
|
||||
|
||||
public CreatePortableCaseModule() {
|
||||
// Nothing to do here
|
||||
}
|
||||
@ -132,6 +145,8 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
"CreatePortableCaseModule.generateReport.copyingTags=Copying tags...",
|
||||
"# {0} - tag name",
|
||||
"CreatePortableCaseModule.generateReport.copyingFiles=Copying files tagged as {0}...",
|
||||
"# {0} - tag name",
|
||||
"CreatePortableCaseModule.generateReport.copyingArtifacts=Copying artifacts tagged as {0}...",
|
||||
"# {0} - output folder",
|
||||
"CreatePortableCaseModule.generateReport.outputDirDoesNotExist=Output folder {0} does not exist",
|
||||
"# {0} - output folder",
|
||||
@ -139,7 +154,10 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
"CreatePortableCaseModule.generateReport.noTagsSelected=No tags selected for export.",
|
||||
"CreatePortableCaseModule.generateReport.caseClosed=Current case has been closed",
|
||||
"CreatePortableCaseModule.generateReport.errorCopyingTags=Error copying tags",
|
||||
"CreatePortableCaseModule.generateReport.errorCopyingFiles=Error copying tagged files"
|
||||
"CreatePortableCaseModule.generateReport.errorCopyingFiles=Error copying tagged files",
|
||||
"CreatePortableCaseModule.generateReport.errorCopyingArtifacts=Error copying tagged artifacts",
|
||||
"# {0} - attribute type name",
|
||||
"CreatePortableCaseModule.generateReport.errorLookingUpAttrType=Error looking up attribute type {0}",
|
||||
})
|
||||
@Override
|
||||
public void generateReport(String reportPath, ReportProgressPanel progressPanel) {
|
||||
@ -182,10 +200,10 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
|
||||
|
||||
// Create the case.
|
||||
// skCase and caseFolder will be set here.
|
||||
// portableSkCase and caseFolder will be set here.
|
||||
progressPanel.updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_creatingCase());
|
||||
createCase(outputDir, progressPanel);
|
||||
if (skCase == null) {
|
||||
if (portableSkCase == null) {
|
||||
// The error has already been handled
|
||||
return;
|
||||
}
|
||||
@ -200,7 +218,7 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
progressPanel.updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_copyingTags());
|
||||
try {
|
||||
for(TagName tagName:tagNames) {
|
||||
TagName newTagName = skCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
|
||||
TagName newTagName = portableSkCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
|
||||
oldTagNameToNewTagName.put(tagName, newTagName);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
@ -223,6 +241,35 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up tracking to support any custom artifact or attribute types
|
||||
for (BlackboardArtifact.ARTIFACT_TYPE type:BlackboardArtifact.ARTIFACT_TYPE.values()) {
|
||||
oldArtTypeIdToNewArtTypeId.put(type.getTypeID(), type.getTypeID());
|
||||
}
|
||||
for (BlackboardAttribute.ATTRIBUTE_TYPE type:BlackboardAttribute.ATTRIBUTE_TYPE.values()) {
|
||||
try {
|
||||
oldAttrTypeIdToNewAttrType.put(type.getTypeID(), portableSkCase.getAttributeType(type.getLabel()));
|
||||
} catch (TskCoreException ex) {
|
||||
handleError("Error looking up attribute name " + type.getLabel(),
|
||||
Bundle.CreatePortableCaseModule_generateReport_errorLookingUpAttrType(type.getLabel()),
|
||||
ex, progressPanel);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the tagged artifacts and associated files
|
||||
try {
|
||||
for(TagName tagName:tagNames) {
|
||||
// Check for cancellation
|
||||
if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) {
|
||||
return;
|
||||
}
|
||||
progressPanel.updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_copyingArtifacts(tagName.getDisplayName()));
|
||||
addArtifactsToPortableCase(tagName, progressPanel);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
handleError("Error copying tagged artifacts", Bundle.CreatePortableCaseModule_generateReport_errorCopyingArtifacts(), ex, progressPanel);
|
||||
return;
|
||||
}
|
||||
|
||||
// Close the case connections and clear out the maps
|
||||
cleanup();
|
||||
|
||||
@ -232,7 +279,7 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
|
||||
/**
|
||||
* Create the case directory and case database.
|
||||
* skCase will be set if this completes without error.
|
||||
* portableSkCase will be set if this completes without error.
|
||||
*
|
||||
* @param outputDir The parent for the case folder
|
||||
* @param progressPanel
|
||||
@ -258,7 +305,7 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
|
||||
// Create the case
|
||||
try {
|
||||
skCase = currentCase.createPortableCase(caseName, caseFolder);
|
||||
portableSkCase = currentCase.createPortableCase(caseName, caseFolder);
|
||||
} catch (TskCoreException ex) {
|
||||
handleError("Error creating case " + caseName + " in folder " + caseFolder.toString(),
|
||||
Bundle.CreatePortableCaseModule_createCase_errorCreatingCase(), ex, progressPanel);
|
||||
@ -294,14 +341,11 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
/**
|
||||
* Add all files with a given tag to the portable case.
|
||||
*
|
||||
* @param oldTagName
|
||||
* @param progressPanel
|
||||
* @param oldTagName The TagName object from the current case
|
||||
* @param progressPanel The progress panel
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"# {0} - File name",
|
||||
"CreatePortableCaseModule.addFilesToPortableCase.copyingFile=Copying file {0}",
|
||||
})
|
||||
private void addFilesToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel) throws TskCoreException {
|
||||
|
||||
// Get all the tags in the current case
|
||||
@ -317,29 +361,201 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
|
||||
Content content = tag.getContent();
|
||||
if (content instanceof AbstractFile) {
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
String filePath = file.getParentPath() + file.getName();
|
||||
progressPanel.updateStatusLabel(Bundle.CreatePortableCaseModule_addFilesToPortableCase_copyingFile(filePath));
|
||||
|
||||
long newFileId;
|
||||
CaseDbTransaction trans = skCase.beginTransaction();
|
||||
try {
|
||||
newFileId = copyContent(file, trans);
|
||||
trans.commit();
|
||||
} catch (TskCoreException ex) {
|
||||
trans.rollback();
|
||||
throw(ex);
|
||||
}
|
||||
long newFileId = copyContentToPortableCase(content, progressPanel);
|
||||
|
||||
// Tag the file
|
||||
if (! oldTagNameToNewTagName.containsKey(tag.getName())) {
|
||||
throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName());
|
||||
}
|
||||
skCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset());
|
||||
portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all artifacts with a given tag to the portable case.
|
||||
*
|
||||
* @param oldTagName The TagName object from the current case
|
||||
* @param progressPanel The progress panel
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private void addArtifactsToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel) throws TskCoreException {
|
||||
|
||||
List<BlackboardArtifactTag> tags = currentCase.getServices().getTagsManager().getBlackboardArtifactTagsByTagName(oldTagName);
|
||||
|
||||
// Copy the artifacts into the portable case along with their content and tag
|
||||
for (BlackboardArtifactTag tag : tags) {
|
||||
|
||||
// Check for cancellation
|
||||
if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the source content
|
||||
Content content = tag.getContent();
|
||||
long newContentId = copyContentToPortableCase(content, progressPanel);
|
||||
|
||||
// Copy the artifact
|
||||
BlackboardArtifact newArtifact = copyArtifact(newContentId, tag.getArtifact());
|
||||
|
||||
// Tag the artfiact
|
||||
if (! oldTagNameToNewTagName.containsKey(tag.getName())) {
|
||||
throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName());
|
||||
}
|
||||
portableSkCase.addBlackboardArtifactTag(newArtifact, oldTagNameToNewTagName.get(tag.getName()), tag.getComment());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an artifact into the new case. Will also copy any associated artifacts
|
||||
*
|
||||
* @param newContentId The content ID (in the portable case) of the source content
|
||||
* @param artifactToCopy The artifact to copy
|
||||
*
|
||||
* @return The new artifact in the portable case
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private BlackboardArtifact copyArtifact(long newContentId, BlackboardArtifact artifactToCopy) throws TskCoreException {
|
||||
|
||||
if (oldArtifactIdToNewArtifact.containsKey(artifactToCopy.getArtifactID())) {
|
||||
return oldArtifactIdToNewArtifact.get(artifactToCopy.getArtifactID());
|
||||
}
|
||||
|
||||
// First create the associated artifact (if present)
|
||||
BlackboardAttribute oldAssociatedAttribute = artifactToCopy.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||
List<BlackboardAttribute> newAttrs = new ArrayList<>();
|
||||
if (oldAssociatedAttribute != null) {
|
||||
BlackboardArtifact oldAssociatedArtifact = currentCase.getSleuthkitCase().getBlackboardArtifact(oldAssociatedAttribute.getValueLong());
|
||||
BlackboardArtifact newAssociatedArtifact = copyArtifact(newContentId, oldAssociatedArtifact);
|
||||
newAttrs.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
|
||||
String.join(",", oldAssociatedAttribute.getSources()), newAssociatedArtifact.getArtifactID()));
|
||||
}
|
||||
|
||||
// Create the new artifact
|
||||
int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy);
|
||||
BlackboardArtifact newArtifact = portableSkCase.newBlackboardArtifact(newArtifactTypeId, newContentId);
|
||||
List<BlackboardAttribute> oldAttrs = artifactToCopy.getAttributes();
|
||||
|
||||
// Copy over each attribute, making sure the type is in the new case.
|
||||
for (BlackboardAttribute oldAttr:oldAttrs) {
|
||||
|
||||
// The associated artifact has already been handled
|
||||
if (oldAttr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlackboardAttribute.Type newAttributeType = getNewAttributeType(oldAttr);
|
||||
switch (oldAttr.getValueType()) {
|
||||
case BYTE:
|
||||
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
|
||||
oldAttr.getValueBytes()));
|
||||
break;
|
||||
case DOUBLE:
|
||||
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
|
||||
oldAttr.getValueDouble()));
|
||||
break;
|
||||
case INTEGER:
|
||||
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
|
||||
oldAttr.getValueInt()));
|
||||
break;
|
||||
case DATETIME:
|
||||
case LONG:
|
||||
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
|
||||
oldAttr.getValueLong()));
|
||||
break;
|
||||
case STRING:
|
||||
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
|
||||
oldAttr.getValueString()));
|
||||
break;
|
||||
default:
|
||||
throw new TskCoreException("Unexpected attribute value type found: " + oldAttr.getValueType().getLabel());
|
||||
}
|
||||
}
|
||||
|
||||
newArtifact.addAttributes(newAttrs);
|
||||
|
||||
oldArtifactIdToNewArtifact.put(artifactToCopy.getArtifactID(), newArtifact);
|
||||
return newArtifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the artifact type ID in the portable case and create new artifact type if needed.
|
||||
* For built-in artifacts this will be the same as the original.
|
||||
*
|
||||
* @param oldArtifactTypeId The artifact type ID in the current case
|
||||
*
|
||||
* @return The corresponding artifact type ID in the portable case
|
||||
*/
|
||||
private int getNewArtifactTypeId(BlackboardArtifact oldArtifact) throws TskCoreException {
|
||||
if (oldArtTypeIdToNewArtTypeId.containsKey(oldArtifact.getArtifactTypeID())) {
|
||||
return oldArtTypeIdToNewArtTypeId.get(oldArtifact.getArtifactTypeID());
|
||||
}
|
||||
|
||||
BlackboardArtifact.Type oldCustomType = currentCase.getSleuthkitCase().getArtifactType(oldArtifact.getArtifactTypeName());
|
||||
try {
|
||||
BlackboardArtifact.Type newCustomType = portableSkCase.addBlackboardArtifactType(oldCustomType.getTypeName(), oldCustomType.getDisplayName());
|
||||
oldArtTypeIdToNewArtTypeId.put(oldArtifact.getArtifactTypeID(), newCustomType.getTypeID());
|
||||
return newCustomType.getTypeID();
|
||||
} catch (TskDataException ex) {
|
||||
throw new TskCoreException("Error creating new artifact type " + oldCustomType.getTypeName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attribute type ID in the portable case and create new attribute type if needed.
|
||||
* For built-in attributes this will be the same as the original.
|
||||
*
|
||||
* @param oldAttributeTypeId The attribute type ID in the current case
|
||||
*
|
||||
* @return The corresponding attribute type in the portable case
|
||||
*/
|
||||
private BlackboardAttribute.Type getNewAttributeType(BlackboardAttribute oldAttribute) throws TskCoreException {
|
||||
BlackboardAttribute.Type oldAttrType = oldAttribute.getAttributeType();
|
||||
if (oldAttrTypeIdToNewAttrType.containsKey(oldAttrType.getTypeID())) {
|
||||
return oldAttrTypeIdToNewAttrType.get(oldAttrType.getTypeID());
|
||||
}
|
||||
|
||||
try {
|
||||
BlackboardAttribute.Type newCustomType = portableSkCase.addArtifactAttributeType(oldAttrType.getTypeName(),
|
||||
oldAttrType.getValueType(), oldAttrType.getDisplayName());
|
||||
oldAttrTypeIdToNewAttrType.put(oldAttribute.getAttributeType().getTypeID(), newCustomType);
|
||||
return newCustomType;
|
||||
} catch (TskDataException ex) {
|
||||
throw new TskCoreException("Error creating new attribute type " + oldAttrType.getTypeName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Top level method to copy a content object to the portable case.
|
||||
*
|
||||
* @param content The content object to copy
|
||||
* @param progressPanel The progress panel
|
||||
*
|
||||
* @return The object ID of the copied content in the portable case
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"# {0} - File name",
|
||||
"CreatePortableCaseModule.copyContentToPortableCase.copyingFile=Copying file {0}",
|
||||
})
|
||||
private long copyContentToPortableCase(Content content, ReportProgressPanel progressPanel) throws TskCoreException {
|
||||
progressPanel.updateStatusLabel(Bundle.CreatePortableCaseModule_copyContentToPortableCase_copyingFile(content.getUniquePath()));
|
||||
|
||||
long newFileId;
|
||||
CaseDbTransaction trans = portableSkCase.beginTransaction();
|
||||
try {
|
||||
newFileId = copyContent(content, trans);
|
||||
trans.commit();
|
||||
return newFileId;
|
||||
} catch (TskCoreException ex) {
|
||||
trans.rollback();
|
||||
throw(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object ID for the given content object in the portable case.
|
||||
*
|
||||
@ -368,18 +584,18 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
Content newContent;
|
||||
if (content instanceof Image) {
|
||||
Image image = (Image)content;
|
||||
newContent = skCase.addImage(image.getType(), image.getSsize(), image.getSize(), image.getName(),
|
||||
newContent = portableSkCase.addImage(image.getType(), image.getSsize(), image.getSize(), image.getName(),
|
||||
new ArrayList<>(), image.getTimeZone(), image.getMd5(), image.getSha1(), image.getSha256(), image.getDeviceId(), trans);
|
||||
} else if (content instanceof VolumeSystem) {
|
||||
VolumeSystem vs = (VolumeSystem)content;
|
||||
newContent = skCase.addVolumeSystem(parentId, vs.getType(), vs.getOffset(), vs.getBlockSize(), trans);
|
||||
newContent = portableSkCase.addVolumeSystem(parentId, vs.getType(), vs.getOffset(), vs.getBlockSize(), trans);
|
||||
} else if (content instanceof Volume) {
|
||||
Volume vs = (Volume)content;
|
||||
newContent = skCase.addVolume(parentId, vs.getAddr(), vs.getStart(), vs.getLength(),
|
||||
newContent = portableSkCase.addVolume(parentId, vs.getAddr(), vs.getStart(), vs.getLength(),
|
||||
vs.getDescription(), vs.getFlags(), trans);
|
||||
} else if (content instanceof FileSystem) {
|
||||
FileSystem fs = (FileSystem)content;
|
||||
newContent = skCase.addFileSystem(parentId, fs.getImageOffset(), fs.getFsType(), fs.getBlock_size(),
|
||||
newContent = portableSkCase.addFileSystem(parentId, fs.getImageOffset(), fs.getFsType(), fs.getBlock_size(),
|
||||
fs.getBlock_count(), fs.getRoot_inum(), fs.getFirst_inum(), fs.getLastInum(),
|
||||
fs.getName(), trans);
|
||||
} else if (content instanceof AbstractFile) {
|
||||
@ -387,10 +603,10 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
|
||||
if (abstractFile instanceof LocalFilesDataSource) {
|
||||
LocalFilesDataSource localFilesDS = (LocalFilesDataSource)abstractFile;
|
||||
newContent = skCase.addLocalFilesDataSource(localFilesDS.getDeviceId(), localFilesDS.getName(), localFilesDS.getTimeZone(), trans);
|
||||
newContent = portableSkCase.addLocalFilesDataSource(localFilesDS.getDeviceId(), localFilesDS.getName(), localFilesDS.getTimeZone(), trans);
|
||||
} else {
|
||||
if (abstractFile.isDir()) {
|
||||
newContent = skCase.addLocalDirectory(parentId, abstractFile.getName(), trans);
|
||||
newContent = portableSkCase.addLocalDirectory(parentId, abstractFile.getName(), trans);
|
||||
} else {
|
||||
try {
|
||||
// Copy the file
|
||||
@ -410,7 +626,7 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
// Construct the relative path to the copied file
|
||||
String relativePath = FILE_FOLDER_NAME + File.separator + exportSubFolder + File.separator + fileName;
|
||||
|
||||
newContent = skCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(),
|
||||
newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(),
|
||||
abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(),
|
||||
abstractFile.getMd5Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(),
|
||||
true, TskData.EncodingType.NONE,
|
||||
@ -459,9 +675,9 @@ public class CreatePortableCaseModule implements GeneralReportModule {
|
||||
newIdToContent.clear();
|
||||
oldTagNameToNewTagName.clear();
|
||||
currentCase = null;
|
||||
if (skCase != null) {
|
||||
if (portableSkCase != null) {
|
||||
// We want to close the database connections here but it is currently not possible. JIRA-4736
|
||||
skCase = null;
|
||||
portableSkCase = null;
|
||||
}
|
||||
caseFolder = null;
|
||||
copiedFilesFolder = null;
|
||||
|
@ -201,10 +201,21 @@ class AddArchiveTask implements Runnable {
|
||||
success = true;
|
||||
newDataSources.addAll(internalDataSource.getContent());
|
||||
|
||||
// Update the names for all new data sources to be the root archive plus the name of the data source
|
||||
// update data source info
|
||||
for (Content c:internalDataSource.getContent()) {
|
||||
if (c instanceof DataSource) {
|
||||
DataSource ds = (DataSource) c;
|
||||
|
||||
// Read existing aquisition details and update them
|
||||
String details = "Extracted from archive: " + archivePath.toString();
|
||||
String existingDetails = ds.getAcquisitionDetails();
|
||||
if (existingDetails != null && !existingDetails.isEmpty()) {
|
||||
ds.setAcquisitionDetails(existingDetails + System.getProperty("line.separator") + details);
|
||||
} else {
|
||||
ds.setAcquisitionDetails(details);
|
||||
}
|
||||
|
||||
// Update the names for all new data sources to be the root archive plus the name of the data source
|
||||
String newName = Paths.get(archivePath).getFileName() + "/" + ds.getName();
|
||||
ds.setDisplayName(newName);
|
||||
currentCase.notifyDataSourceNameChanged(c, newName);
|
||||
@ -253,8 +264,17 @@ class AddArchiveTask implements Runnable {
|
||||
|
||||
archiveDspLock.wait();
|
||||
|
||||
// at this point we got the content object(s) from the current DSP
|
||||
// at this point we got the content object(s) from the current DSP.
|
||||
newDataSources.addAll(internalDataSource.getContent());
|
||||
|
||||
for (Content c : internalDataSource.getContent()) {
|
||||
if (c instanceof DataSource) {
|
||||
DataSource ds = (DataSource) c;
|
||||
// This is a new data source so just write the aquisition details
|
||||
String details = "Extracted from archive: " + archivePath.toString();
|
||||
ds.setAcquisitionDetails(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
@ -42,6 +42,7 @@ import org.netbeans.jellytools.NbDialogOperator;
|
||||
import org.netbeans.jellytools.WizardOperator;
|
||||
import org.netbeans.jemmy.JemmyProperties;
|
||||
import org.netbeans.jemmy.Timeout;
|
||||
import org.netbeans.jemmy.TimeoutExpiredException;
|
||||
import org.netbeans.jemmy.Timeouts;
|
||||
import org.netbeans.jemmy.operators.JButtonOperator;
|
||||
import org.netbeans.jemmy.operators.JCheckBoxOperator;
|
||||
@ -96,14 +97,20 @@ public class AutopsyTestCases {
|
||||
}
|
||||
|
||||
public void testNewCaseWizardOpen(String title) {
|
||||
try {
|
||||
logger.info("New Case");
|
||||
resetTimeouts("WindowWaiter.WaitWindowTimeout", 240000);
|
||||
setTimeout("WindowWaiter.WaitWindowTimeout", 240000);
|
||||
NbDialogOperator nbdo = new NbDialogOperator(title);
|
||||
JButtonOperator jbo = new JButtonOperator(nbdo, 0); // the "New Case" button
|
||||
jbo.pushNoBlock();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNewCaseWizard() {
|
||||
try {
|
||||
logger.info("New Case Wizard");
|
||||
WizardOperator wo = new WizardOperator("New Case Information");
|
||||
JTextFieldOperator jtfo0 = new JTextFieldOperator(wo, 1);
|
||||
@ -117,17 +124,23 @@ public class AutopsyTestCases {
|
||||
jtfo3.typeText("Examiner 1"); // Set the case examiner
|
||||
start = System.currentTimeMillis();
|
||||
wo.btFinish().clickMouse();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartAddImageFileDataSource() {
|
||||
try {
|
||||
/*
|
||||
* This time out is to give time for creating case database and opening solr index
|
||||
* This time out is to give time for creating case database and
|
||||
* opening solr index
|
||||
*/
|
||||
new Timeout("pausing", 120000).sleep();
|
||||
logger.info("Starting Add Image process");
|
||||
resetTimeouts("WindowWaiter.WaitWindowTimeOut", 240000);
|
||||
setTimeout("WindowWaiter.WaitWindowTimeOut", 240000);
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
while(!wo.btNext().isEnabled()){
|
||||
while (!wo.btNext().isEnabled()) {
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
|
||||
}
|
||||
//select the toggle button for Disk Image or VM File it will be the first button created and proceed to next panel
|
||||
@ -141,17 +154,23 @@ public class AutopsyTestCases {
|
||||
JComboBoxOperator comboBoxOperator = new JComboBoxOperator(wo, 0);
|
||||
comboBoxOperator.setSelectedItem("(GMT-5:00) America/New_York");
|
||||
wo.btNext().clickMouse();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartAddLogicalFilesDataSource() {
|
||||
try {
|
||||
/*
|
||||
* This time out is to give time for creating case database and opening solr index
|
||||
* This time out is to give time for creating case database and
|
||||
* opening solr index
|
||||
*/
|
||||
new Timeout("pausing", 120000).sleep();
|
||||
logger.info("Starting Add Logical Files process");
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
wo.setTimeouts(resetTimeouts("WindowWaiter.WaitWindowTimeOut", 240000));
|
||||
while(!wo.btNext().isEnabled()){
|
||||
wo.setTimeouts(setTimeout("WindowWaiter.WaitWindowTimeOut", 240000));
|
||||
while (!wo.btNext().isEnabled()) {
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
|
||||
}
|
||||
//select the toggle button for Logical Files it will be the third button created and proceed to next panel
|
||||
@ -166,27 +185,37 @@ public class AutopsyTestCases {
|
||||
fileChooserOperator.goUpLevel();
|
||||
fileChooserOperator.chooseFile(new File(getEscapedPath(System.getProperty("img_path"))).getName());
|
||||
wo.btNext().clickMouse();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddSourceWizard1() {
|
||||
try {
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
while (!wo.btFinish().isEnabled()) {
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process
|
||||
}
|
||||
logger.log(Level.INFO, "Add image took {0}ms", (System.currentTimeMillis() - start));
|
||||
wo.btFinish().clickMouse();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConfigureIngest1() {
|
||||
try {
|
||||
/*
|
||||
* This timeout is to allow the setup for the ingest job settings panel
|
||||
* to complete.
|
||||
* This timeout is to allow the setup for the ingest job settings
|
||||
* panel to complete.
|
||||
*/
|
||||
new Timeout("pausing", 10000).sleep();
|
||||
|
||||
logger.info("Looking for hash lookup module in ingest job settings panel");
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
while(!wo.btNext().isEnabled()){
|
||||
while (!wo.btNext().isEnabled()) {
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
|
||||
}
|
||||
JTableOperator jto = new JTableOperator(wo, 0);
|
||||
@ -196,9 +225,14 @@ public class AutopsyTestCases {
|
||||
JButtonOperator jbo1 = new JButtonOperator(wo, "Global Settings");
|
||||
jbo1.pushNoBlock();
|
||||
logger.info("Pushed Global Settings button for hash lookup module in ingest job settings panel");
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConfigureHash() {
|
||||
try {
|
||||
logger.info("Hash Configure");
|
||||
JDialog hashMainDialog = JDialogOperator.waitJDialog("Global Hash Lookup Settings", false, false);
|
||||
JDialogOperator hashMainDialogOperator = new JDialogOperator(hashMainDialog);
|
||||
@ -230,12 +264,17 @@ public class AutopsyTestCases {
|
||||
//jbo3.pushNoBlock();
|
||||
JButtonOperator jbo4 = new JButtonOperator(hashMainDialogOperator, "OK", 0);
|
||||
jbo4.pushNoBlock();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConfigureIngest2() {
|
||||
try {
|
||||
logger.info("Looking for keyword search module in ingest job settings panel");
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
while(!wo.btNext().isEnabled()){
|
||||
while (!wo.btNext().isEnabled()) {
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
|
||||
}
|
||||
JTableOperator jto = new JTableOperator(wo, 0);
|
||||
@ -245,9 +284,14 @@ public class AutopsyTestCases {
|
||||
JButtonOperator jbo1 = new JButtonOperator(wo, "Global Settings");
|
||||
jbo1.pushNoBlock();
|
||||
logger.info("Pushed Global Settings button for keyword search module in ingest job settings panel");
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConfigureSearch() {
|
||||
try {
|
||||
logger.info("Search Configure");
|
||||
JDialog jd = JDialogOperator.waitJDialog("Global Keyword Search Settings", false, false);
|
||||
JDialogOperator jdo = new JDialogOperator(jd);
|
||||
@ -273,9 +317,14 @@ public class AutopsyTestCases {
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
new Timeout("pausing", 10000).sleep(); // let things catch up
|
||||
wo.btNext().clickMouse();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testIngest() {
|
||||
try {
|
||||
logger.info("Ingest 3");
|
||||
new Timeout("pausing", 10000).sleep(); // wait for ingest to actually start
|
||||
long startIngest = System.currentTimeMillis();
|
||||
@ -289,31 +338,43 @@ public class AutopsyTestCases {
|
||||
// consistently, making it seem like default behavior
|
||||
Random rand = new Random();
|
||||
new Timeout("pausing", 10000 + (rand.nextInt(15000) + 5000)).sleep();
|
||||
screenshot("Finished Ingest");
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testExpandDataSourcesTree() {
|
||||
try {
|
||||
logger.info("Data Sources Node");
|
||||
MainWindowOperator mwo = MainWindowOperator.getDefault();
|
||||
JTreeOperator jto = new JTreeOperator(mwo, "Data Sources");
|
||||
String [] nodeNames = {"Data Sources"};
|
||||
String[] nodeNames = {"Data Sources"};
|
||||
TreePath tp = jto.findPath(nodeNames);
|
||||
expandNodes(jto, tp);
|
||||
screenshot("Data Sources Tree");
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGenerateReportToolbar() {
|
||||
try {
|
||||
logger.info("Generate Report Toolbars");
|
||||
MainWindowOperator mwo = MainWindowOperator.getDefault();
|
||||
JButtonOperator jbo = new JButtonOperator(mwo, "Generate Report");
|
||||
jbo.pushNoBlock();
|
||||
new Timeout("pausing", 5000).sleep();
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGenerateReportButton() throws IOException {
|
||||
try {
|
||||
logger.info("Generate Report Button");
|
||||
resetTimeouts("ComponentOperator.WaitComponentTimeout", 240000);
|
||||
setTimeout("ComponentOperator.WaitComponentTimeout", 240000);
|
||||
JDialog reportDialog = JDialogOperator.waitJDialog("Generate Report", false, false);
|
||||
JDialogOperator reportDialogOperator = new JDialogOperator(reportDialog);
|
||||
JListOperator listOperator = new JListOperator(reportDialogOperator);
|
||||
@ -327,38 +388,42 @@ public class AutopsyTestCases {
|
||||
JButtonOperator jbo1 = new JButtonOperator(reportDialogOperator, "Finish");
|
||||
jbo1.pushNoBlock();
|
||||
JDialog previewDialog = JDialogOperator.waitJDialog("Progress", false, false);
|
||||
screenshot("Progress");
|
||||
JDialogOperator previewDialogOperator = new JDialogOperator(previewDialog);
|
||||
JLabelOperator.waitJLabel(previewDialog, "Complete", false, false);
|
||||
JButtonOperator jbo2 = new JButtonOperator(previewDialogOperator, "Close");
|
||||
jbo2.pushNoBlock();
|
||||
new Timeout("pausing", 10000).sleep();
|
||||
System.setProperty("ReportStr", datenotime);
|
||||
screenshot("Done Testing");
|
||||
} catch (TimeoutExpiredException ex) {
|
||||
screenshot("TimeoutScreenshot");
|
||||
logger.log(Level.SEVERE, "AutopsyTestCases.testNewCaseWizard encountered timed out", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void screenshot(String name) {
|
||||
String outPath = getEscapedPath(System.getProperty("out_path"));
|
||||
File screenShotFile = new File(outPath + "\\" + name + ".png");
|
||||
if (!screenShotFile.exists()) {
|
||||
logger.info("Taking screenshot.");
|
||||
try {
|
||||
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
|
||||
BufferedImage capture = new Robot().createScreenCapture(screenRect);
|
||||
String outPath = getEscapedPath(System.getProperty("out_path"));
|
||||
ImageIO.write(capture, "png", new File(outPath + "\\" + name + ".png"));
|
||||
ImageIO.write(capture, "png", screenShotFile);
|
||||
new Timeout("pausing", 1000).sleep(); // give it a second to save
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "IOException taking screenshot.", ex);
|
||||
} catch (AWTException ex) {
|
||||
logger.log(Level.WARNING, "AWTException taking screenshot.", ex);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Nightly test failed at WindowWaiter.WaitWindowTimeOut because of TimeoutExpiredException. So we
|
||||
* use this conveninent method to override the default Jemmy Timeouts value.
|
||||
* Nightly test failed at WindowWaiter.WaitWindowTimeOut because of
|
||||
* TimeoutExpiredException. So we use this conveninent method to override
|
||||
* the default Jemmy Timeouts value.
|
||||
*/
|
||||
|
||||
private Timeouts resetTimeouts(String name, int value) {
|
||||
private Timeouts setTimeout(String name, int value) {
|
||||
Timeouts timeouts = JemmyProperties.getCurrentTimeouts();
|
||||
timeouts.setTimeout(name, value);
|
||||
return timeouts;
|
||||
@ -394,7 +459,7 @@ public class AutopsyTestCases {
|
||||
}
|
||||
}
|
||||
|
||||
private void expandNodes (JTreeOperator jto, TreePath tp) {
|
||||
private void expandNodes(JTreeOperator jto, TreePath tp) {
|
||||
try {
|
||||
jto.expandPath(tp);
|
||||
for (TreePath t : jto.getChildPaths(tp)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user