19 package org.sleuthkit.autopsy.modules.filetypeid;
21 import java.io.Serializable;
22 import java.io.UnsupportedEncodingException;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Objects;
29 import java.util.logging.Level;
30 import javax.swing.JOptionPane;
31 import javax.xml.bind.DatatypeConverter;
32 import org.openide.windows.WindowManager;
42 class FileType
implements Serializable {
44 private static final long serialVersionUID = 1L;
45 private final String mimeType;
46 private final List<Signature> signatures;
47 private final boolean createInterestingFileHit;
48 private final String interestingFilesSetName;
58 FileType(String mimeType, List<Signature> signatures)
throws IllegalArgumentException {
59 this(mimeType, signatures,
false,
"");
72 FileType(String mimeType, List<Signature> signatures,
boolean createInterestingFileHit, String setName)
throws IllegalArgumentException {
73 if (signatures.isEmpty()) {
74 throw new IllegalArgumentException(
"Must have at least one signature.");
76 this.mimeType = mimeType;
77 this.signatures =
new ArrayList<>(signatures);
78 this.createInterestingFileHit = createInterestingFileHit;
79 this.interestingFilesSetName = setName;
87 String getMimeType() {
97 String getInterestingFilesSetName() {
98 return interestingFilesSetName;
107 boolean shouldCreateInterestingFileHit() {
108 return createInterestingFileHit;
116 List<Signature> getSignatures() {
117 return Collections.unmodifiableList(this.signatures);
125 void addSignature(Signature sig) {
126 this.signatures.add(sig);
136 boolean matches(
final AbstractFile file) {
137 for (Signature sig : this.signatures) {
138 if (!sig.containedIn(file)) {
146 public String toString() {
147 return this.mimeType;
151 public boolean equals(Object other) {
152 if (other != null && other instanceof FileType) {
153 FileType that = (FileType) other;
154 if (this.getMimeType().equals(that.getMimeType()) && this.getSignatures().equals(that.getSignatures())) {
162 public int hashCode() {
164 hash = 67 * hash + Objects.hashCode(this.mimeType);
165 hash = 67 * hash + Objects.hashCode(this.signatures);
175 static class Signature
implements Serializable {
177 private static final long serialVersionUID = 1L;
178 private static final Logger logger = Logger.getLogger(Signature.class.getName());
188 private final byte[] signatureBytes;
189 private final long offset;
190 private final Type type;
191 private final boolean isRelativeToStart;
202 Signature(
final byte[] signatureBytes,
long offset, Type type) {
203 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
204 this.offset = offset;
206 this.isRelativeToStart =
true;
216 Signature(String signatureString,
long offset) {
217 this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
218 this.offset = offset;
219 this.type = Type.ASCII;
220 this.isRelativeToStart =
true;
232 Signature(
final byte[] signatureBytes,
long offset) {
233 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
234 this.offset = offset;
235 this.type = Type.RAW;
236 this.isRelativeToStart =
true;
250 Signature(
final byte[] signatureBytes,
long offset, Type type,
boolean isRelativeToStart) {
251 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
252 this.offset = offset;
254 this.isRelativeToStart = isRelativeToStart;
266 Signature(String signatureString,
long offset,
boolean isRelativeToStart) {
267 this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
268 this.offset = offset;
269 this.type = Type.ASCII;
270 this.isRelativeToStart = isRelativeToStart;
284 Signature(
final byte[] signatureBytes,
long offset,
boolean isRelativeToStart) {
285 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
286 this.offset = offset;
287 this.type = Type.RAW;
288 this.isRelativeToStart = isRelativeToStart;
296 byte[] getSignatureBytes() {
297 return Arrays.copyOf(signatureBytes, signatureBytes.length);
318 boolean isRelativeToStart() {
319 return isRelativeToStart;
330 boolean containedIn(
final AbstractFile file) {
331 if (offset >= file.getSize()) {
334 long actualOffset = offset;
335 if (!isRelativeToStart) {
336 actualOffset = file.getSize() - 1 - offset;
338 if (file.getSize() < (actualOffset + signatureBytes.length)) {
342 byte[] buffer =
new byte[signatureBytes.length];
343 int bytesRead = file.read(buffer, actualOffset, signatureBytes.length);
344 return ((bytesRead == signatureBytes.length) && (Arrays.equals(buffer, signatureBytes)));
345 }
catch (TskCoreException ex) {
351 Signature.logger.log(Level.WARNING,
"Error reading from file with objId = " + file.getId(), ex);
357 public boolean equals(Object other) {
358 if (other != null && other instanceof Signature) {
359 Signature that = (Signature) other;
360 if (Arrays.equals(
this.getSignatureBytes(), that.getSignatureBytes())
361 && this.getOffset() == that.getOffset()
362 && this.getType().equals(that.getType())) {
370 public int hashCode() {
372 hash = 97 * hash + Arrays.hashCode(this.signatureBytes);
373 hash = 97 * hash + (int) (this.offset ^ (this.offset >>> 32));
374 hash = 97 * hash + Objects.hashCode(this.type);
379 public String toString() {
380 String signatureBytesString;
381 if (Signature.Type.RAW ==
this.getType()) {
382 signatureBytesString = DatatypeConverter.printHexBinary(this.getSignatureBytes());
383 signatureBytesString =
"0x" + signatureBytesString;
386 signatureBytesString =
new String(this.getSignatureBytes(),
"UTF-8");
387 }
catch (UnsupportedEncodingException ex) {
388 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
389 ex.getLocalizedMessage(),
390 Bundle.AddFileTypeSignaturePanel_signatureStringFail_text(),
391 JOptionPane.ERROR_MESSAGE);
392 signatureBytesString =
"";
396 if (this.isRelativeToStart) {
397 startOrEnd =
"start";
401 return signatureBytesString +
", " + offset +
" bytes from " + startOrEnd;