diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index cca8104c38..bf6adc0de3 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -23,10 +23,13 @@ FileTypeIdGlobalSettingsPanel.mimeTypeLabel.text=MIME Type FileTypeIdGlobalSettingsPanel.saveTypeButton.text=Save FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=Bytes (Hex) FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem=String (ASCII) +FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem=Start +FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=End FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.message=MIME type is required. FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.title=Missing MIME Type FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.message=Signature is required. FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.title=Missing Signature +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.length=Offset must not be smaller than signature size. FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message=Offset must be a positive integer. FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title=Invalid Offset FileTypeIdGlobalSettingsPanel.JOptionPane.invalidRawSignatureBytes.message=The signature has one or more invalid hexadecimal digits. @@ -46,4 +49,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.offsetRelativeToLabel.text=Offset is relative to diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java index 30c9525603..84e4186975 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.isRelativeToStart()); 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.isRelativeToStart()); } /** @@ -148,6 +148,7 @@ class FileType { private final byte[] signatureBytes; private final long offset; private final Type type; + private final boolean isRelativeToStart; /** * 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.isRelativeToStart = true; } /** @@ -175,6 +177,7 @@ class FileType { this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); this.offset = offset; this.type = Type.ASCII; + this.isRelativeToStart = true; } /** @@ -190,6 +193,56 @@ class FileType { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.offset = offset; this.type = Type.RAW; + this.isRelativeToStart = true; + } + + /** + * Creates a file signature consisting of a sequence of bytes at a + * specific offset within a file. + * + * @param signatureBytes The signature bytes. + * @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. + * @param isRelativeToStart Determines whether this signature is relative to start. + */ + Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) { + this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); + this.offset = offset; + this.type = type; + this.isRelativeToStart = isRelativeToStart; + } + + /** + * Creates a file signature consisting of an ASCII string at a + * specific offset within a file. + * + * @param signatureString The ASCII string + * @param offset The offset of the signature bytes. + * @param isRelativeToStart Determines whether this signature is relative to start. + */ + Signature(String signatureString, long offset, boolean isRelativeToStart) { + this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); + this.offset = offset; + this.type = Type.ASCII; + this.isRelativeToStart = isRelativeToStart; + } + + /** + * Creates a file signature consisting of a sequence of bytes at a + * 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 offset The offset of the signature bytes. + * @param isRelativeToStart Determines whether this signature is relative to start. + */ + Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) { + this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); + this.offset = offset; + this.type = Type.RAW; + this.isRelativeToStart = isRelativeToStart; } /** @@ -218,6 +271,10 @@ class FileType { Type getType() { return type; } + + boolean isRelativeToStart() { + return isRelativeToStart; + } /** * Determines whether or not the signature is contained within a given @@ -228,12 +285,15 @@ class FileType { * @return True or false. */ boolean containedIn(final AbstractFile file) { - if (file.getSize() < (offset + signatureBytes.length)) { + long actualOffset = offset; + if(!isRelativeToStart) + actualOffset = file.getSize() - 1 - 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) { /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form index bfc83ee709..2b4647356c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form @@ -49,40 +49,50 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -107,7 +117,7 @@ - + @@ -138,12 +148,17 @@ + + + + + - - + + - + @@ -350,5 +365,22 @@ + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java index 5380234490..9e1b1f3320 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java @@ -52,6 +52,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private static final String RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem"); private static final String ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem"); + private static final String START_OFFSET_RELATIVE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem"); + private static final String END_OFFSET_RELATIVE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem"); /** * The list model for the file types list component of this panel is the set * of MIME types associated with the user-defined file types. A mapping of @@ -88,6 +90,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private void customizeComponents() { setFileTypesListModel(); setSignatureTypeComboBoxModel(); + setOffsetRealtiveToComboBoxModel(); clearTypeDetailsComponents(); addTypeListSelectionListener(); addTextFieldListeners(); @@ -111,6 +114,17 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane signatureTypeComboBox.setModel(sigTypeComboBoxModel); signatureTypeComboBox.setSelectedItem(FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM); } + + /** + * Sets the model for the signature type combo box. + */ + private void setOffsetRealtiveToComboBoxModel() { + DefaultComboBoxModel offsetRelComboBoxModel = new DefaultComboBoxModel<>(); + offsetRelComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.START_OFFSET_RELATIVE_COMBO_BOX_ITEM); + offsetRelComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.END_OFFSET_RELATIVE_COMBO_BOX_ITEM); + offsetRelativeToComboBox.setModel(offsetRelComboBoxModel); + offsetRelativeToComboBox.setSelectedItem(FileTypeIdGlobalSettingsPanel.START_OFFSET_RELATIVE_COMBO_BOX_ITEM); + } /** * Adds a listener to the types list component so that the components in the @@ -270,6 +284,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane } } signatureTextField.setText(signatureBytes); + offsetRelativeToComboBox.setSelectedItem(signature.isRelativeToStart() ? FileTypeIdGlobalSettingsPanel.START_OFFSET_RELATIVE_COMBO_BOX_ITEM : FileTypeIdGlobalSettingsPanel.END_OFFSET_RELATIVE_COMBO_BOX_ITEM); offsetTextField.setText(Long.toString(signature.getOffset())); postHitCheckBox.setSelected(fileType.alertOnMatch()); filesSetNameTextField.setEnabled(postHitCheckBox.isSelected()); @@ -289,6 +304,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane signatureTypeComboBox.setSelectedItem(FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM); hexPrefixLabel.setVisible(true); signatureTextField.setText("0000"); //NON-NLS + offsetRelativeToComboBox.setSelectedItem(FileTypeIdGlobalSettingsPanel.START_OFFSET_RELATIVE_COMBO_BOX_ITEM); offsetTextField.setText(""); //NON-NLS postHitCheckBox.setSelected(false); filesSetNameTextField.setText(""); //NON-NLS @@ -360,6 +376,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); + offsetRelativeToComboBox = new javax.swing.JComboBox(); + offsetRelativeToLabel = new javax.swing.JLabel(); setMaximumSize(new java.awt.Dimension(500, 300)); setPreferredSize(new java.awt.Dimension(500, 300)); @@ -439,6 +457,8 @@ 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(offsetRelativeToLabel, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -465,33 +485,40 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(mimeTypeLabel) - .addGap(30, 30, 30) - .addComponent(mimeTypeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(postHitCheckBox) - .addGroup(layout.createSequentialGroup() - .addComponent(signatureTypeLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(signatureTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(signatureLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(hexPrefixLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(signatureTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(offsetLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(offsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(21, 21, 21) .addComponent(filesSetNameLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(filesSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 182, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(filesSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 182, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(mimeTypeLabel) + .addGap(30, 30, 30) + .addComponent(mimeTypeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(postHitCheckBox) + .addGroup(layout.createSequentialGroup() + .addComponent(signatureTypeLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(signatureTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(signatureLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(hexPrefixLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(signatureTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(offsetLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(offsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(6, 6, 6))) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(saveTypeButton) - .addGap(8, 8, 8)))) + .addGap(8, 8, 8)) + .addGroup(layout.createSequentialGroup() + .addComponent(offsetRelativeToLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(offsetRelativeToComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addComponent(jLabel1) .addComponent(jLabel3)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) @@ -509,7 +536,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addGroup(layout.createSequentialGroup() .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(typesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 177, Short.MAX_VALUE) + .addComponent(typesScrollPane) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(deleteTypeButton) @@ -532,11 +559,15 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addComponent(hexPrefixLabel) .addComponent(signatureTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(signatureLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(offsetLabel) + .addComponent(offsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .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) - .addComponent(offsetLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(offsetRelativeToComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(offsetRelativeToLabel)) + .addGap(16, 16, 16) .addComponent(postHitCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -596,6 +627,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane byte[] signatureBytes; if (FileType.Signature.Type.RAW == sigType) { try { + sigString = sigString.replaceAll("\\s", ""); signatureBytes = DatatypeConverter.parseHexBinary(sigString); } catch (IllegalArgumentException ex) { JOptionPane.showMessageDialog(null, @@ -612,8 +644,16 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane * Get the offset. */ long offset; + boolean isRelativeToStart = offsetRelativeToComboBox.getSelectedItem() == FileTypeIdGlobalSettingsPanel.START_OFFSET_RELATIVE_COMBO_BOX_ITEM; try { - offset = Long.parseUnsignedLong(offsetTextField.getText()); + offset = Long.parseUnsignedLong(offsetTextField.getText()); + if(!isRelativeToStart && signatureBytes.length > offset+1) { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.length"), + NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title"), + JOptionPane.ERROR_MESSAGE); + return; + } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message"), @@ -640,7 +680,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, isRelativeToStart); FileType fileType = new FileType(typeName, signature, filesSetName, postHitCheckBox.isSelected()); FileType selected = typesList.getSelectedValue(); if (selected != null) { @@ -683,6 +723,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private javax.swing.JTextField mimeTypeTextField; private javax.swing.JButton newTypeButton; private javax.swing.JLabel offsetLabel; + private javax.swing.JComboBox offsetRelativeToComboBox; + private javax.swing.JLabel offsetRelativeToLabel; private javax.swing.JTextField offsetTextField; private javax.swing.JCheckBox postHitCheckBox; private javax.swing.JButton saveTypeButton; diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd index 26aa720ff1..d5812bcf19 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypes.xsd @@ -13,8 +13,16 @@ - - + + + + + + + + + + @@ -25,7 +33,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index d06750dc66..d8a7275282 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 RELATIVE_ATTRIBUTE = "RelativeToStart"; 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 @@ -376,6 +378,7 @@ final class UserDefinedFileTypesManager { Element offsetElem = doc.createElement(OFFSET_TAG_NAME); offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset())); + offsetElem.setAttribute(RELATIVE_ATTRIBUTE, String.valueOf(signature.isRelativeToStart())); signatureElem.appendChild(offsetElem); signatureElem.setAttribute(SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString()); @@ -485,10 +488,17 @@ final class UserDefinedFileTypesManager { String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME); byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString); - String offsetString = getChildElementTextContent(signatureElem, OFFSET_TAG_NAME); + Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0); + String offsetString = offsetElem.getTextContent(); long offset = DatatypeConverter.parseLong(offsetString); + + String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE); + if(relativeString == null || relativeString.equals("")) + return new Signature(signatureBytes, offset, signatureType); + + boolean isRelative = DatatypeConverter.parseBoolean(relativeString); - return new Signature(signatureBytes, offset, signatureType); + return new Signature(signatureBytes, offset, signatureType, isRelative); } /** @@ -526,11 +536,14 @@ final class UserDefinedFileTypesManager { * @param elem The parent element. * @param tagName The tag name of the child element. * - * @return The text content. + * @return The text content or null if the tag doesn't exist. */ 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(); }