diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index 7ac6b9fc2c..bc99ea014f 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -46,4 +46,4 @@ FileTypeIdGlobalSettingsPanel.jLabel2.text=MIME Types: FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. -FileTypeIdGlobalSettingsPanel.isFooterCheckBox.text=This signature is a footer +FileTypeIdGlobalSettingsPanel.isTrailingCheckBox.text=This signature is a trailing diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java index cc12a95b5a..133c1c6f84 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java @@ -51,7 +51,7 @@ class FileType { */ FileType(String mimeType, final Signature signature, String filesSetName, boolean alert) { this.mimeType = mimeType; - this.signature = new Signature(signature.getSignatureBytes(), signature.getOffset(), signature.getType()); + this.signature = new Signature(signature.getSignatureBytes(), signature.getOffset(), signature.getType(), signature.isTrailing()); this.interestingFilesSetName = filesSetName; this.alert = alert; } @@ -71,7 +71,7 @@ class FileType { * @return The signature. */ Signature getSignature() { - return new Signature(signature.getSignatureBytes(), signature.getOffset(), signature.getType()); + return new Signature(signature.getSignatureBytes(), signature.getOffset(), signature.getType(), signature.isTrailing()); } /** @@ -148,6 +148,7 @@ class FileType { private final byte[] signatureBytes; private final long offset; private final Type type; + private final boolean trailing; /** * Creates a file signature consisting of a sequence of bytes at a @@ -162,6 +163,7 @@ class FileType { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.offset = offset; this.type = type; + this.trailing = false; } /** @@ -175,6 +177,7 @@ class FileType { this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); this.offset = offset; this.type = Type.ASCII; + this.trailing = false; } /** @@ -190,49 +193,56 @@ class FileType { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.offset = offset; this.type = Type.RAW; + this.trailing = false; } /** * Creates a file signature consisting of a sequence of bytes at a - * specific offset within a file with default offset. + * specific offset within a file. * * @param signatureBytes The signature bytes. - * @param isFooter Whether this is a footer or not + * @param offset The offset of the signature bytes. * @param type The type of data in the byte array. Impacts - * how it is displayed to the user in the UI. + * how it is displayed to the user in the UI. + * @param trailing Determines whether this signature is trailing. */ - Signature(final byte[] signatureBytes, boolean isFooter, Type type) { + Signature(final byte[] signatureBytes, long offset, Type type, boolean trailing) { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); - this.offset = isFooter ? -1 : 0; + this.offset = offset; this.type = type; + this.trailing = trailing; } /** * Creates a file signature consisting of an ASCII string at a - * specific offset within a file with default offset. + * specific offset within a file. * * @param signatureString The ASCII string - * @param isFooter Whether this is a footer or not + * @param offset The offset of the signature bytes. + * @param trailing Determines whether this signature is trailing. */ - Signature(String signatureString, boolean isFooter) { + Signature(String signatureString, long offset, boolean trailing) { this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); - this.offset = isFooter ? -1 : 0; + this.offset = offset; this.type = Type.ASCII; + this.trailing = trailing; } /** * Creates a file signature consisting of a sequence of bytes at a - * specific offset within a file with default offset. If bytes - * correspond to an ASCII string, use one of the other constructors - * so that the string is displayed to the user instead of the raw bytes. + * specific offset within a file. If bytes correspond to an ASCII + * string, use one of the other constructors so that the string is + * displayed to the user instead of the raw bytes. * * @param signatureBytes The signature bytes. - * @param isFooter Whether this is a footer or not + * @param offset The offset of the signature bytes. + * @param trailing Determines whether this signature is trailing. */ - Signature(final byte[] signatureBytes, boolean isFooter) { + Signature(final byte[] signatureBytes, long offset, boolean trailing) { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); - this.offset = isFooter ? -1 : 0; + this.offset = offset; this.type = Type.RAW; + this.trailing = trailing; } /** @@ -261,6 +271,10 @@ class FileType { Type getType() { return type; } + + boolean isTrailing() { + return trailing; + } /** * Determines whether or not the signature is contained within a given @@ -270,15 +284,16 @@ class FileType { * * @return True or false. */ - boolean containedIn(final AbstractFile file) { - if(offset == -1) - return containedAsFooter(file); - if (file.getSize() < (offset + signatureBytes.length)) { + boolean containedIn(final AbstractFile file) { + long actualOffset = offset; + if(trailing) + actualOffset = file.getSize() - signatureBytes.length - offset; + if (file.getSize() < (actualOffset + signatureBytes.length)) { return false; /// too small, can't contain this signature } try { byte[] buffer = new byte[signatureBytes.length]; - int bytesRead = file.read(buffer, offset, signatureBytes.length); + int bytesRead = file.read(buffer, actualOffset, signatureBytes.length); return ((bytesRead == signatureBytes.length) && (Arrays.equals(buffer, signatureBytes))); } catch (TskCoreException ex) { /** @@ -291,14 +306,6 @@ class FileType { } } - private boolean containedAsFooter(final AbstractFile file) { - if(file.getSize() < signatureBytes.length) - return false; - long newOffset = file.getSize() - signatureBytes.length; - Signature newSignature = new Signature(signatureBytes, newOffset); - return newSignature.containedIn(file); - } - @Override public boolean equals(Object other) { if (other != null && other instanceof Signature) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form index 030695446f..0e51a3c6bc 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form @@ -83,7 +83,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -353,14 +353,14 @@ - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java index f45be34df6..58afdd266a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java @@ -203,7 +203,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane boolean requiredFieldsPopulated = !mimeTypeTextField.getText().isEmpty() - && (isFooterCheckBox.isSelected() ? true : !offsetTextField.getText().isEmpty()) + && !offsetTextField.getText().isEmpty() && !signatureTextField.getText().isEmpty() && (postHitCheckBox.isSelected() ? !filesSetNameTextField.getText().isEmpty() : true); saveTypeButton.setEnabled(!ingestIsRunning && requiredFieldsPopulated); @@ -270,16 +270,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane } } signatureTextField.setText(signatureBytes); - if(signature.getOffset() == -1) { - isFooterCheckBox.setSelected(true); - offsetTextField.setEnabled(false); - offsetTextField.setText(""); - } - else { - isFooterCheckBox.setSelected(false); - offsetTextField.setEnabled(true); - offsetTextField.setText(Long.toString(signature.getOffset())); - } + isTrailingCheckBox.setSelected(signature.isTrailing()); + offsetTextField.setText(Long.toString(signature.getOffset())); postHitCheckBox.setSelected(fileType.alertOnMatch()); filesSetNameTextField.setEnabled(postHitCheckBox.isSelected()); filesSetNameTextField.setText(fileType.getFilesSetName()); @@ -298,8 +290,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane signatureTypeComboBox.setSelectedItem(FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM); hexPrefixLabel.setVisible(true); signatureTextField.setText("0000"); //NON-NLS - isFooterCheckBox.setSelected(false); - offsetTextField.setEnabled(true); + isTrailingCheckBox.setSelected(false); offsetTextField.setText(""); //NON-NLS postHitCheckBox.setSelected(false); filesSetNameTextField.setText(""); //NON-NLS @@ -371,7 +362,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); - isFooterCheckBox = new javax.swing.JCheckBox(); + isTrailingCheckBox = new javax.swing.JCheckBox(); setMaximumSize(new java.awt.Dimension(500, 300)); setPreferredSize(new java.awt.Dimension(500, 300)); @@ -451,10 +442,10 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel3.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(isFooterCheckBox, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.isFooterCheckBox.text")); // NOI18N - isFooterCheckBox.addActionListener(new java.awt.event.ActionListener() { + org.openide.awt.Mnemonics.setLocalizedText(isTrailingCheckBox, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.isTrailingCheckBox.text")); // NOI18N + isTrailingCheckBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - isFooterCheckBoxActionPerformed(evt); + isTrailingCheckBoxActionPerformed(evt); } }); @@ -511,7 +502,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(saveTypeButton) .addGap(8, 8, 8)) - .addComponent(isFooterCheckBox))) + .addComponent(isTrailingCheckBox))) .addComponent(jLabel1) .addComponent(jLabel3)) .addContainerGap(50, Short.MAX_VALUE)))) @@ -553,7 +544,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addComponent(signatureTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(signatureLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(isFooterCheckBox) + .addComponent(isTrailingCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(offsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -635,7 +626,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane */ long offset; try { - offset = isFooterCheckBox.isSelected() ? -1 : Long.parseUnsignedLong(offsetTextField.getText()); + offset = Long.parseUnsignedLong(offsetTextField.getText()); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message"), @@ -662,7 +653,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane /** * Put it all together and reset the file types list component. */ - FileType.Signature signature = new FileType.Signature(signatureBytes, offset, sigType); + FileType.Signature signature = new FileType.Signature(signatureBytes, offset, sigType, isTrailingCheckBox.isSelected()); FileType fileType = new FileType(typeName, signature, filesSetName, postHitCheckBox.isSelected()); FileType selected = typesList.getSelectedValue(); if (selected != null) { @@ -692,10 +683,9 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane // TODO add your handling code here: }//GEN-LAST:event_signatureTextFieldActionPerformed - private void isFooterCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_isFooterCheckBoxActionPerformed - offsetTextField.setEnabled(!isFooterCheckBox.isSelected()); - enableButtons(); - }//GEN-LAST:event_isFooterCheckBoxActionPerformed + private void isTrailingCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_isTrailingCheckBoxActionPerformed + + }//GEN-LAST:event_isTrailingCheckBoxActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton deleteTypeButton; @@ -703,7 +693,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private javax.swing.JTextField filesSetNameTextField; private javax.swing.JLabel hexPrefixLabel; private javax.swing.JLabel ingestRunningWarningLabel; - private javax.swing.JCheckBox isFooterCheckBox; + private javax.swing.JCheckBox isTrailingCheckBox; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd index 6ae9505c76..63dab70d24 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd @@ -21,17 +21,12 @@ - - - - - - - + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 06098726d0..2a13efd63e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -38,6 +38,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; +import org.w3c.dom.Node; import org.xml.sax.SAXException; /** @@ -67,6 +68,7 @@ final class UserDefinedFileTypesManager { private static final String SIGNATURE_TYPE_ATTRIBUTE = "type"; //NON-NLS private static final String BYTES_TAG_NAME = "Bytes"; //NON-NLS private static final String OFFSET_TAG_NAME = "Offset"; //NON-NLS + private static final String TRAILING_TAG_NAME = "Trailing"; private static final String INTERESTING_FILES_SET_TAG_NAME = "InterestingFileSset"; //NON-NLS private static final String ALERT_ATTRIBUTE = "alert"; //NON-NLS private static final String ENCODING_FOR_XML_FILE = "UTF-8"; //NON-NLS @@ -378,6 +380,10 @@ final class UserDefinedFileTypesManager { Element offsetElem = doc.createElement(OFFSET_TAG_NAME); offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset())); signatureElem.appendChild(offsetElem); + + Element trailingElem = doc.createElement(TRAILING_TAG_NAME); + trailingElem.setTextContent(DatatypeConverter.printBoolean(signature.isTrailing())); + signatureElem.appendChild(trailingElem); signatureElem.setAttribute(SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString()); fileTypeElem.appendChild(signatureElem); @@ -488,8 +494,14 @@ final class UserDefinedFileTypesManager { String offsetString = getChildElementTextContent(signatureElem, OFFSET_TAG_NAME); long offset = DatatypeConverter.parseLong(offsetString); + + String trailingString = getChildElementTextContent(signatureElem, TRAILING_TAG_NAME); + if(trailingString == null) + return new Signature(signatureBytes, offset, signatureType); + + boolean trailing = DatatypeConverter.parseBoolean(trailingString); - return new Signature(signatureBytes, offset, signatureType); + return new Signature(signatureBytes, offset, signatureType, trailing); } /** @@ -531,7 +543,10 @@ final class UserDefinedFileTypesManager { */ private static String getChildElementTextContent(Element elem, String tagName) { NodeList childElems = elem.getElementsByTagName(tagName); - Element childElem = (Element) childElems.item(0); + Node childNode = childElems.item(0); + if(childNode == null) + return null; + Element childElem = (Element) childNode; return childElem.getTextContent(); }