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;
41 class FileType
implements Serializable {
43 private static final long serialVersionUID = 1L;
44 private final String mimeType;
45 private final List<Signature> signatures;
46 private final boolean createInterestingFileHit;
47 private final String interestingFilesSetName;
57 FileType(String mimeType, List<Signature> signatures)
throws IllegalArgumentException {
58 this(mimeType, signatures,
false,
"");
71 FileType(String mimeType, List<Signature> signatures,
boolean createInterestingFileHit, String setName)
throws IllegalArgumentException {
72 if (signatures.isEmpty()) {
73 throw new IllegalArgumentException(
"Must have at least one signature.");
75 this.mimeType = mimeType;
76 this.signatures =
new ArrayList<>(signatures);
77 this.createInterestingFileHit = createInterestingFileHit;
78 this.interestingFilesSetName = setName;
86 String getMimeType() {
96 String getInterestingFilesSetName() {
97 return interestingFilesSetName;
106 boolean createInterestingFileHit() {
107 return createInterestingFileHit;
115 List<Signature> getSignatures() {
116 return Collections.unmodifiableList(this.signatures);
124 void addSignature(Signature sig) {
125 this.signatures.add(sig);
135 boolean matches(
final AbstractFile file) {
136 for (Signature sig : this.signatures) {
137 if (!sig.containedIn(file)) {
145 public String toString() {
146 return this.mimeType;
150 public boolean equals(Object other) {
151 if (other != null && other instanceof FileType) {
152 FileType that = (FileType) other;
153 if (this.getMimeType().equals(that.getMimeType()) && this.getSignatures().equals(that.getSignatures())) {
161 public int hashCode() {
163 hash = 67 * hash + Objects.hashCode(this.mimeType);
164 hash = 67 * hash + Objects.hashCode(this.signatures);
174 static class Signature
implements Serializable {
176 private static final long serialVersionUID = 1L;
177 private static final Logger logger = Logger.getLogger(Signature.class.getName());
187 private final byte[] signatureBytes;
188 private final long offset;
189 private final Type type;
190 private final boolean isRelativeToStart;
201 Signature(
final byte[] signatureBytes,
long offset, Type type) {
202 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
203 this.offset = offset;
205 this.isRelativeToStart =
true;
215 Signature(String signatureString,
long offset) {
216 this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
217 this.offset = offset;
218 this.type = Type.ASCII;
219 this.isRelativeToStart =
true;
231 Signature(
final byte[] signatureBytes,
long offset) {
232 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
233 this.offset = offset;
234 this.type = Type.RAW;
235 this.isRelativeToStart =
true;
249 Signature(
final byte[] signatureBytes,
long offset, Type type,
boolean isRelativeToStart) {
250 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
251 this.offset = offset;
253 this.isRelativeToStart = isRelativeToStart;
265 Signature(String signatureString,
long offset,
boolean isRelativeToStart) {
266 this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
267 this.offset = offset;
268 this.type = Type.ASCII;
269 this.isRelativeToStart = isRelativeToStart;
283 Signature(
final byte[] signatureBytes,
long offset,
boolean isRelativeToStart) {
284 this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
285 this.offset = offset;
286 this.type = Type.RAW;
287 this.isRelativeToStart = isRelativeToStart;
295 byte[] getSignatureBytes() {
296 return Arrays.copyOf(signatureBytes, signatureBytes.length);
317 boolean isRelativeToStart() {
318 return isRelativeToStart;
329 boolean containedIn(
final AbstractFile file) {
330 if (offset >= file.getSize()) {
333 long actualOffset = offset;
334 if (!isRelativeToStart) {
335 actualOffset = file.getSize() - 1 - offset;
337 if (file.getSize() < (actualOffset + signatureBytes.length)) {
341 byte[] buffer =
new byte[signatureBytes.length];
342 int bytesRead = file.read(buffer, actualOffset, signatureBytes.length);
343 return ((bytesRead == signatureBytes.length) && (Arrays.equals(buffer, signatureBytes)));
344 }
catch (TskCoreException ex) {
350 Signature.logger.log(Level.WARNING,
"Error reading from file with objId = " + file.getId(), ex);
356 public boolean equals(Object other) {
357 if (other != null && other instanceof Signature) {
358 Signature that = (Signature) other;
359 if (Arrays.equals(
this.getSignatureBytes(), that.getSignatureBytes())
360 && this.getOffset() == that.getOffset()
361 && this.getType().equals(that.getType())) {
369 public int hashCode() {
371 hash = 97 * hash + Arrays.hashCode(this.signatureBytes);
372 hash = 97 * hash + (int) (this.offset ^ (this.offset >>> 32));
373 hash = 97 * hash + Objects.hashCode(this.type);
378 public String toString() {
379 String signatureBytesString;
380 if (Signature.Type.RAW ==
this.getType()) {
381 signatureBytesString = DatatypeConverter.printHexBinary(this.getSignatureBytes());
382 signatureBytesString =
"0x" + signatureBytesString;
385 signatureBytesString =
new String(this.getSignatureBytes(),
"UTF-8");
386 }
catch (UnsupportedEncodingException ex) {
387 JOptionPane.showMessageDialog(null,
388 ex.getLocalizedMessage(),
389 Bundle.AddFileTypeSignaturePanel_signatureStringFail_text(),
390 JOptionPane.ERROR_MESSAGE);
391 signatureBytesString =
"";
395 if (this.isRelativeToStart) {
396 startOrEnd =
"start";
400 return signatureBytesString +
", " + offset +
" bytes from " + startOrEnd;