updates for extension validation

This commit is contained in:
Greg DiCristofaro 2020-08-04 16:30:16 -04:00
parent 5565d7e6d3
commit 8cd7594afa
5 changed files with 134 additions and 47 deletions

View File

@ -20,7 +20,6 @@ PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings
PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files
PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesHyperlink.text=<html>https://www.cgsecurity.org/wiki/\nFile_Formats_Recovered_By_PhotoRec</html>
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types: PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types:
PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip
PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text= PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text=

View File

@ -8,6 +8,9 @@ OpenIDE-Module-Long-Description=PhotoRec Carver ingest module. \n\n Carves unall
OpenIDE-Module-Short-Description=Carves unallocated space and feeds carved files back into the system for processing. OpenIDE-Module-Short-Description=Carves unallocated space and feeds carved files back into the system for processing.
moduleDisplayName.text=PhotoRec Carver moduleDisplayName.text=PhotoRec Carver
moduleDescription.text=Runs PhotoRec carver against unallocated space in the data source. moduleDescription.text=Runs PhotoRec carver against unallocated space in the data source.
# {0} - extensions
PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_description=The following extensions are invalid and were removed: {0}
PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_title=Invalid Extensions
PhotoRecIngestModule.nonHostnameUNCPathUsed=PhotoRec cannot operate with a UNC path containing IP addresses. PhotoRecIngestModule.nonHostnameUNCPathUsed=PhotoRec cannot operate with a UNC path containing IP addresses.
PhotoRecIngestModule.PermissionsNotSufficient=Insufficient permissions accessing PhotoRecIngestModule.PermissionsNotSufficient=Insufficient permissions accessing
PhotoRecIngestModule.PermissionsNotSufficientSeeReference=See 'Shared Drive Authentication' in Autopsy help. PhotoRecIngestModule.PermissionsNotSufficientSeeReference=See 'Shared Drive Authentication' in Autopsy help.
@ -27,7 +30,6 @@ PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings
PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files
PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesHyperlink.text=<html>https://www.cgsecurity.org/wiki/\nFile_Formats_Recovered_By_PhotoRec</html>
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types: PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types:
PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip
PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text= PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text=

View File

@ -20,25 +20,30 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="detectionSettingsLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="keepCorruptedFilesCheckbox" alignment="0" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="includeExcludeCheckbox" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
</Group> <Component id="detectionSettingsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> <Component id="keepCorruptedFilesCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Component id="includeExcludeCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/> </Group>
<Group type="103" groupAlignment="0" attributes="0"> </Group>
<Component id="includeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0">
<Component id="excludeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
<Component id="exampleLabel" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="extensionListTextfield" min="-2" pref="258" max="-2" attributes="0"/> <Component id="includeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullListOfTypesLabel" min="-2" max="-2" attributes="0"/> <Component id="excludeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullListOfTypesHyperlink" alignment="0" min="-2" pref="250" max="-2" attributes="0"/> <Component id="exampleLabel" min="-2" max="-2" attributes="0"/>
<Component id="extensionListLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="extensionListTextfield" min="-2" pref="258" max="-2" attributes="0"/>
<Component id="fullListOfTypesLabel" min="-2" max="-2" attributes="0"/>
<Component id="extensionListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullListOfTypesHyperlink" alignment="0" min="-2" pref="238" max="-2" attributes="0"/>
</Group>
</Group>
</Group> </Group>
<EmptySpace max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -64,8 +69,7 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="fullListOfTypesLabel" min="-2" max="-2" attributes="0"/> <Component id="fullListOfTypesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="fullListOfTypesHyperlink" max="32767" attributes="0"/> <Component id="fullListOfTypesHyperlink" min="-2" pref="51" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -137,8 +141,17 @@
</Component> </Component>
<Component class="javax.swing.JLabel" name="fullListOfTypesHyperlink"> <Component class="javax.swing.JLabel" name="fullListOfTypesHyperlink">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties" key="PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesHyperlink.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <Connection code="String.format(&quot;&lt;html&gt;%s&lt;/html&gt;&quot;, PHOTOREC_TYPES_URL)" type="code"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[240, 50]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[240, 50]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[240, 50]"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -28,10 +28,13 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.swing.JOptionPane;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -44,7 +47,7 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
private static final Logger logger = Logger.getLogger(PhotoRecCarverIngestJobSettingsPanel.class.getName()); private static final Logger logger = Logger.getLogger(PhotoRecCarverIngestJobSettingsPanel.class.getName());
private static final String EXTENSION_LIST_SEPARATOR = ","; private static final String EXTENSION_LIST_SEPARATOR = ",";
private static final String PHOTOREC_TYPES_URL = "https://www.cgsecurity.org/wiki/File_Formats_Recovered_By_PhotoRec"; private static final String PHOTOREC_TYPES_URL = "http://sleuthkit.org/autopsy/docs/user-docs/latest/photorec_carver_page.html";
/** /**
* Instantiate the ingest job settings panel. * Instantiate the ingest job settings panel.
@ -116,12 +119,72 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
} }
@Override @Override
@Messages({
"PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_title=Invalid Extensions",
"# {0} - extensions",
"PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_description=The following extensions are invalid and were removed: {0}"
})
public IngestModuleIngestJobSettings getSettings() { public IngestModuleIngestJobSettings getSettings() {
return new PhotoRecCarverIngestJobSettings( return new PhotoRecCarverIngestJobSettings(
keepCorruptedFilesCheckbox.isSelected(), keepCorruptedFilesCheckbox.isSelected(),
includeExcludeCheckbox.isSelected(), includeExcludeCheckbox.isSelected(),
includeRadioButton.isSelected(), includeRadioButton.isSelected(),
getExtensions(extensionListTextfield.getText())); getAndUpdateExtensions()
);
}
private List<String> getAndUpdateExtensions() {
PhotoRecExtensions extensions = getExtensions(extensionListTextfield.getText());
if (extensions.getInvalidExtensions().size() > 0) {
JOptionPane.showMessageDialog(
this,
String.format("<html>%s</html>",
Bundle.PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_description(
String.join(",", extensions.getInvalidExtensions()))),
Bundle.PhotoRecCarverIngestJobSettingsPanel_getSettings_invalidExtensions_title(),
JOptionPane.ERROR_MESSAGE);
}
extensionListTextfield.setText(String.join(EXTENSION_LIST_SEPARATOR, extensions.getValidExtensions()));
return extensions.getValidExtensions();
}
/**
* An object defining valid and invalid photorec extensions as provided by the user.
*/
private static class PhotoRecExtensions {
private final List<String> validExtensions;
private final List<String> invalidExtensions;
/**
* Main constructor.
* @param validExtensions A list of strings representing the valid extensions.
* @param invalidExtensions A list of invalid extensions.
*/
PhotoRecExtensions(List<String> validExtensions, List<String> invalidExtensions) {
this.validExtensions = validExtensions == null ? Collections.emptyList() : Collections.unmodifiableList(validExtensions);
this.invalidExtensions = invalidExtensions == null ? Collections.emptyList() : Collections.unmodifiableList(invalidExtensions);
}
/**
* @return The valid extensions.
*/
List<String> getValidExtensions() {
return validExtensions;
}
/**
* @return The invalid extensions.
*/
List<String> getInvalidExtensions() {
return invalidExtensions;
}
} }
/** /**
@ -132,15 +195,18 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
* *
* @return The list of strings to use with photorec. * @return The list of strings to use with photorec.
*/ */
private List<String> getExtensions(String combinedList) { private PhotoRecExtensions getExtensions(String combinedList) {
if (StringUtils.isBlank(combinedList)) { if (StringUtils.isBlank(combinedList)) {
return Collections.emptyList(); return new PhotoRecExtensions(null, null);
} }
return Stream.of(combinedList.split(EXTENSION_LIST_SEPARATOR)) Map<Boolean, List<String>> extensions = Stream.of(combinedList.split(EXTENSION_LIST_SEPARATOR))
.map(ext -> ext.trim()) .map(ext -> ext.trim())
.filter(ext -> StringUtils.isNotBlank(ext)) .filter(ext -> StringUtils.isNotBlank(ext))
.collect(Collectors.toList()); .sorted((a, b) -> a.toLowerCase().compareTo(b.toLowerCase()))
.collect(Collectors.partitioningBy(PhotoRecCarverFileOptExtensions::isValidExtension));
return new PhotoRecExtensions(extensions.get(true), extensions.get(false));
} }
/** /**
@ -185,7 +251,10 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
org.openide.awt.Mnemonics.setLocalizedText(extensionListLabel, org.openide.util.NbBundle.getMessage(PhotoRecCarverIngestJobSettingsPanel.class, "PhotoRecCarverIngestJobSettingsPanel.extensionListLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(extensionListLabel, org.openide.util.NbBundle.getMessage(PhotoRecCarverIngestJobSettingsPanel.class, "PhotoRecCarverIngestJobSettingsPanel.extensionListLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(fullListOfTypesHyperlink, org.openide.util.NbBundle.getMessage(PhotoRecCarverIngestJobSettingsPanel.class, "PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesHyperlink.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(fullListOfTypesHyperlink, String.format("<html>%s</html>", PHOTOREC_TYPES_URL));
fullListOfTypesHyperlink.setMaximumSize(new java.awt.Dimension(240, 50));
fullListOfTypesHyperlink.setMinimumSize(new java.awt.Dimension(240, 50));
fullListOfTypesHyperlink.setPreferredSize(new java.awt.Dimension(240, 50));
extensionListTextfield.setText(org.openide.util.NbBundle.getMessage(PhotoRecCarverIngestJobSettingsPanel.class, "PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text")); // NOI18N extensionListTextfield.setText(org.openide.util.NbBundle.getMessage(PhotoRecCarverIngestJobSettingsPanel.class, "PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text")); // NOI18N
@ -198,21 +267,24 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(detectionSettingsLabel) .addGroup(layout.createSequentialGroup()
.addComponent(keepCorruptedFilesCheckbox) .addContainerGap()
.addComponent(includeExcludeCheckbox))) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(detectionSettingsLabel)
.addGap(31, 31, 31) .addComponent(keepCorruptedFilesCheckbox)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(includeExcludeCheckbox)))
.addComponent(includeRadioButton) .addGroup(layout.createSequentialGroup()
.addComponent(excludeRadioButton) .addGap(31, 31, 31)
.addComponent(exampleLabel) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extensionListTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, 258, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(includeRadioButton)
.addComponent(fullListOfTypesLabel) .addComponent(excludeRadioButton)
.addComponent(fullListOfTypesHyperlink, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(exampleLabel)
.addComponent(extensionListLabel))) .addComponent(extensionListTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, 258, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fullListOfTypesLabel)
.addComponent(extensionListLabel)
.addComponent(fullListOfTypesHyperlink, javax.swing.GroupLayout.PREFERRED_SIZE, 238, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -236,8 +308,7 @@ final class PhotoRecCarverIngestJobSettingsPanel extends IngestModuleIngestJobSe
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fullListOfTypesLabel) .addComponent(fullListOfTypesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fullListOfTypesHyperlink) .addComponent(fullListOfTypesHyperlink, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -1,4 +1,6 @@
The 'bin' folder is the version used when running the PhotoRec ingest module. It is also the 32-bit version. The 'bin' folder is the version used when running the PhotoRec ingest module. It is also the 32-bit version.
When the 64-bit version of the installer is created, the photorec_exec/64-bit/bin folder is placed at photorec_exec/bin. When the 64-bit version of the installer is created, the photorec_exec/64-bit/bin folder is placed at photorec_exec/bin.
When the 32-bit version of the installer is created, the photorec_exec/64-bit folder is deleted. When the 32-bit version of the installer is created, the photorec_exec/64-bit folder is deleted.
See 'build-windows-installer.xml' for more details. See 'build-windows-installer.xml' for more details.
Extensions for PhotoRec need to be placed in the PhotoRecCarverFileOptExtensions class so that only valid extensions will be used with PhotoRec. It can be generated through PhotoRec by launching photorec_win with no arguments, go to "Proceed", go to "File Opt" and press 'b'. This should generate a photorec.cfg file in the current working directory with a list of all the extensions.