mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into search_improvements
This commit is contained in:
commit
0517f5065e
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -23,8 +23,6 @@ import org.openide.nodes.Children.Keys;
|
|||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
@ -109,7 +107,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
public AbstractContentNode<? extends Content> visit(VirtualDirectory ld) {
|
public AbstractContentNode<? extends Content> visit(VirtualDirectory ld) {
|
||||||
return new VirtualDirectoryNode(ld);
|
return new VirtualDirectoryNode(ld);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractContentNode<? extends Content> visit(SlackFile sf) {
|
public AbstractContentNode<? extends Content> visit(SlackFile sf) {
|
||||||
return new SlackFileNode(sf);
|
return new SlackFileNode(sf);
|
||||||
@ -137,8 +135,8 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypeExtensionFilters sf) {
|
public AbstractNode visit(FileTypesByExtension sf) {
|
||||||
return new FileTypesByExtNode(sf.getSleuthkitCase(), null);
|
return new org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileTypesByExtNode(sf.getSleuthkitCase(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -220,7 +218,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) {
|
public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) {
|
||||||
return ftByMimeTypeItem.new FileTypesByMimeTypeNode(ftByMimeTypeItem.getSleuthkitCase());
|
return ftByMimeTypeItem.new ByMimeTypeNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
@ -42,7 +41,7 @@ public class ArtifactStringContent implements StringContent {
|
|||||||
BlackboardArtifact artifact;
|
BlackboardArtifact artifact;
|
||||||
private String stringContent = "";
|
private String stringContent = "";
|
||||||
static final Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
|
static final Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
|
||||||
private static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
public ArtifactStringContent(BlackboardArtifact art) {
|
public ArtifactStringContent(BlackboardArtifact art) {
|
||||||
artifact = art;
|
artifact = art;
|
||||||
@ -74,7 +73,7 @@ public class ArtifactStringContent implements StringContent {
|
|||||||
buffer.append("<tr><td>"); //NON-NLS
|
buffer.append("<tr><td>"); //NON-NLS
|
||||||
buffer.append(attr.getAttributeType().getDisplayName());
|
buffer.append(attr.getAttributeType().getDisplayName());
|
||||||
buffer.append("</td>"); //NON-NLS
|
buffer.append("</td>"); //NON-NLS
|
||||||
|
|
||||||
// value column
|
// value column
|
||||||
buffer.append("<td>"); //NON-NLS
|
buffer.append("<td>"); //NON-NLS
|
||||||
switch (attr.getAttributeType().getValueType()) {
|
switch (attr.getAttributeType().getValueType()) {
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This visitor goes over the AutopsyVisitableItems, which are currently the
|
* This visitor goes over the AutopsyVisitableItems, which are currently the
|
||||||
@ -33,13 +31,13 @@ public interface AutopsyItemVisitor<T> {
|
|||||||
|
|
||||||
T visit(Views v);
|
T visit(Views v);
|
||||||
|
|
||||||
T visit(FileTypeExtensionFilters sf);
|
T visit(FileTypesByExtension sf);
|
||||||
|
|
||||||
T visit(FileTypeExtensionFilters.RootFilter fsf);
|
T visit(FileTypesByExtension.RootFilter fsf);
|
||||||
|
|
||||||
T visit(FileTypeExtensionFilters.DocumentFilter df);
|
T visit(FileTypesByExtension.DocumentFilter df);
|
||||||
|
|
||||||
T visit(FileTypeExtensionFilters.ExecutableFilter ef);
|
T visit(FileTypesByExtension.ExecutableFilter ef);
|
||||||
|
|
||||||
T visit(RecentFiles rf);
|
T visit(RecentFiles rf);
|
||||||
|
|
||||||
@ -86,22 +84,22 @@ public interface AutopsyItemVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeExtensionFilters sf) {
|
public T visit(FileTypesByExtension sf) {
|
||||||
return defaultVisit(sf);
|
return defaultVisit(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeExtensionFilters.RootFilter fsf) {
|
public T visit(FileTypesByExtension.RootFilter fsf) {
|
||||||
return defaultVisit(fsf);
|
return defaultVisit(fsf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeExtensionFilters.DocumentFilter df) {
|
public T visit(FileTypesByExtension.DocumentFilter df) {
|
||||||
return defaultVisit(df);
|
return defaultVisit(df);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeExtensionFilters.ExecutableFilter ef) {
|
public T visit(FileTypesByExtension.ExecutableFilter ef) {
|
||||||
return defaultVisit(ef);
|
return defaultVisit(ef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -118,16 +118,16 @@ FileSize.createSheet.filterType.displayName=Filter Type
|
|||||||
FileSize.createSheet.filterType.desc=no description
|
FileSize.createSheet.filterType.desc=no description
|
||||||
FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||||
FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||||
FileTypeNode.createSheet.filterType.name=Filter Type
|
FileTypesByExtNode.createSheet.filterType.name=Filter Type
|
||||||
FileTypeNode.createSheet.filterType.displayName=Filter Type
|
FileTypesByExtNode.createSheet.filterType.displayName=Filter Type
|
||||||
FileTypeNode.createSheet.filterType.desc=no description
|
FileTypesByExtNode.createSheet.filterType.desc=no description
|
||||||
FileTypeNode.createSheet.fileExt.name=File Extensions
|
FileTypesByExtNode.createSheet.fileExt.name=File Extensions
|
||||||
FileTypeNode.createSheet.fileExt.displayName=File Extensions
|
FileTypesByExtNode.createSheet.fileExt.displayName=File Extensions
|
||||||
FileTypeNode.createSheet.fileExt.desc=no description
|
FileTypesByExtNode.createSheet.fileExt.desc=no description
|
||||||
FileTypesNode.fname.text=By Extension
|
FileTypesByExtNode.fname.text=By Extension
|
||||||
FileTypesNode.createSheet.name.name=Name
|
FileTypesByExtNode.createSheet.name.name=Name
|
||||||
FileTypesNode.createSheet.name.displayName=Name
|
FileTypesByExtNode.createSheet.name.displayName=Name
|
||||||
FileTypesNode.createSheet.name.desc=no description
|
FileTypesByExtNode.createSheet.name.desc=no description
|
||||||
HashsetHits.createSheet.name.name=Name
|
HashsetHits.createSheet.name.name=Name
|
||||||
HashsetHits.createSheet.name.displayName=Name
|
HashsetHits.createSheet.name.displayName=Name
|
||||||
HashsetHits.createSheet.name.desc=no description
|
HashsetHits.createSheet.name.desc=no description
|
||||||
@ -274,4 +274,15 @@ AbstractAbstractFileNode.addFileProperty.desc=no description
|
|||||||
AbstractAbstractFileNode.addFileProperty.tags.name=Tags
|
AbstractAbstractFileNode.addFileProperty.tags.name=Tags
|
||||||
AbstractAbstractFileNode.addFileProperty.tags.displayName=Tags
|
AbstractAbstractFileNode.addFileProperty.tags.displayName=Tags
|
||||||
BlackboardArtifactNode.createSheet.tags.name=Tags
|
BlackboardArtifactNode.createSheet.tags.name=Tags
|
||||||
BlackboardArtifactNode.createSheet.tags.displayName=Tags
|
BlackboardArtifactNode.createSheet.tags.displayName=Tags
|
||||||
|
FileTypeExtensionFilters.tskImgFilter.text=Images
|
||||||
|
FileTypeExtensionFilters.tskVideoFilter.text=Videos
|
||||||
|
FileTypeExtensionFilters.tskAudioFilter.text=Audio
|
||||||
|
FileTypeExtensionFilters.tskArchiveFilter.text=Archives
|
||||||
|
FileTypeExtensionFilters.tskDocumentFilter.text=Documents
|
||||||
|
FileTypeExtensionFilters.tskExecFilter.text=Executable
|
||||||
|
FileTypeExtensionFilters.autDocHtmlFilter.text=HTML
|
||||||
|
FileTypeExtensionFilters.autDocOfficeFilter.text=Office
|
||||||
|
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
|
||||||
|
FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text
|
||||||
|
FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text
|
@ -112,16 +112,15 @@ FileTypeExtensionFilters.autDocOfficeFilter.text=\u30aa\u30d5\u30a3\u30b9
|
|||||||
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
|
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
|
||||||
FileTypeExtensionFilters.autDocTxtFilter.text=\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8
|
FileTypeExtensionFilters.autDocTxtFilter.text=\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8
|
||||||
FileTypeExtensionFilters.autDocRtfFilter.text=\u30ea\u30c3\u30c1\u30c6\u30ad\u30b9\u30c8
|
FileTypeExtensionFilters.autDocRtfFilter.text=\u30ea\u30c3\u30c1\u30c6\u30ad\u30b9\u30c8
|
||||||
FileTypeNode.createSheet.filterType.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
FileTypesByExtNode.createSheet.filterType.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||||
FileTypeNode.createSheet.filterType.displayName=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
FileTypesByExtNode.createSheet.filterType.displayName=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||||
FileTypeNode.createSheet.filterType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
FileTypesByExtNode.createSheet.filterType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||||
FileTypeNode.createSheet.fileExt.name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
FileTypesByExtNode.createSheet.fileExt.name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
||||||
FileTypeNode.createSheet.fileExt.displayName=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
FileTypesByExtNode.createSheet.fileExt.displayName=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
||||||
FileTypeNode.createSheet.fileExt.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
FileTypesByExtNode.createSheet.fileExt.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||||
FileTypesNode.fname.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7
|
FileTypesByExtNode.createSheet.name.name=\u540d\u524d
|
||||||
FileTypesNode.createSheet.name.name=\u540d\u524d
|
FileTypesByExtNode.createSheet.name.displayName=\u540d\u524d
|
||||||
FileTypesNode.createSheet.name.displayName=\u540d\u524d
|
FileTypesByExtNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||||
FileTypesNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
|
||||||
HashsetHits.createSheet.name.name=\u540d\u524d
|
HashsetHits.createSheet.name.name=\u540d\u524d
|
||||||
HashsetHits.createSheet.name.displayName=\u540d\u524d
|
HashsetHits.createSheet.name.displayName=\u540d\u524d
|
||||||
HashsetHits.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
HashsetHits.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||||
|
@ -49,16 +49,16 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
T visit(ImageNode in);
|
T visit(ImageNode in);
|
||||||
|
|
||||||
T visit(VolumeNode vn);
|
T visit(VolumeNode vn);
|
||||||
|
|
||||||
T visit(SlackFileNode sfn);
|
T visit(SlackFileNode sfn);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Views Area
|
* Views Area
|
||||||
*/
|
*/
|
||||||
T visit(ViewsNode vn);
|
T visit(ViewsNode vn);
|
||||||
|
|
||||||
T visit(FileTypeByExtNode fsfn);
|
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn);
|
||||||
|
|
||||||
T visit(DeletedContentNode dcn);
|
T visit(DeletedContentNode dcn);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(FileSizeNode fsn);
|
T visit(FileSizeNode fsn);
|
||||||
|
|
||||||
T visit(FileTypesByExtNode sfn);
|
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileTypesByExtNode sfn);
|
||||||
|
|
||||||
T visit(RecentFilesNode rfn);
|
T visit(RecentFilesNode rfn);
|
||||||
|
|
||||||
@ -146,14 +146,13 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(FileTypes.FileTypesNode fileTypes);
|
T visit(FileTypes.FileTypesNode fileTypes);
|
||||||
|
|
||||||
T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode);
|
T visit(FileTypesByMimeType.ByMimeTypeNode ftByMimeTypeNode);
|
||||||
|
|
||||||
T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaType);
|
T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaType);
|
||||||
|
|
||||||
T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType);
|
T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType);
|
||||||
|
|
||||||
T visit(FileTypesByMimeType.EmptyNode.MessageNode aThis);
|
T visit(EmptyNode.MessageNode emptyNode);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor with an implementable default behavior for all types. Override
|
* Visitor with an implementable default behavior for all types. Override
|
||||||
@ -213,30 +212,30 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeByExtNode fsfn) {
|
public T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn) {
|
||||||
return defaultVisit(fsfn);
|
return defaultVisit(fsfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode) {
|
public T visit(FileTypesByMimeType.ByMimeTypeNode ftByMimeTypeNode) {
|
||||||
return defaultVisit(ftByMimeTypeNode);
|
return defaultVisit(ftByMimeTypeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) {
|
public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) {
|
||||||
return defaultVisit(ftByMimeTypeMediaTypeNode);
|
return defaultVisit(ftByMimeTypeMediaTypeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) {
|
public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) {
|
||||||
return defaultVisit(ftByMimeTypeMediaTypeNode);
|
return defaultVisit(ftByMimeTypeMediaTypeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesByMimeType.EmptyNode.MessageNode ftByMimeTypeEmptyNode) {
|
public T visit(EmptyNode.MessageNode ftByMimeTypeEmptyNode) {
|
||||||
return defaultVisit(ftByMimeTypeEmptyNode);
|
return defaultVisit(ftByMimeTypeEmptyNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(DeletedContentNode dcn) {
|
public T visit(DeletedContentNode dcn) {
|
||||||
return defaultVisit(dcn);
|
return defaultVisit(dcn);
|
||||||
@ -258,7 +257,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesByExtNode sfn) {
|
public T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileTypesByExtNode sfn) {
|
||||||
return defaultVisit(sfn);
|
return defaultVisit(sfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,11 +295,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
public T visit(ResultsNode rn) {
|
public T visit(ResultsNode rn) {
|
||||||
return defaultVisit(rn);
|
return defaultVisit(rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesNode ft) {
|
public T visit(FileTypesNode ft) {
|
||||||
return defaultVisit(ft);
|
return defaultVisit(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(DataSourcesNode in) {
|
public T visit(DataSourcesNode in) {
|
||||||
return defaultVisit(in);
|
return defaultVisit(in);
|
||||||
@ -425,6 +425,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
public T visit(Accounts.BINNode node) {
|
public T visit(Accounts.BINNode node) {
|
||||||
return defaultVisit(node);
|
return defaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(Accounts.DefaultAccountTypeNode node) {
|
public T visit(Accounts.DefaultAccountTypeNode node) {
|
||||||
return defaultVisit(node);
|
return defaultVisit(node);
|
||||||
|
97
Core/src/org/sleuthkit/autopsy/datamodel/EmptyNode.java
Normal file
97
Core/src/org/sleuthkit/autopsy/datamodel/EmptyNode.java
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.openide.nodes.AbstractNode;
|
||||||
|
import org.openide.nodes.ChildFactory;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a root node for the results views with a single child node that
|
||||||
|
* displays a message as the sole item in its property sheet, useful for
|
||||||
|
* displaying explanatory text in the result views when there is a node with no
|
||||||
|
* children in the tree view.
|
||||||
|
*/
|
||||||
|
public final class EmptyNode extends AbstractNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a root node for the results views with a single child node that
|
||||||
|
* displays a message as the sole item in its property sheet, useful for
|
||||||
|
* displaying explanatory text in the result views when there is a node with
|
||||||
|
* no children in the tree view.
|
||||||
|
*
|
||||||
|
* @param displayedMessage The text for the property sheet of the child
|
||||||
|
* node.
|
||||||
|
*/
|
||||||
|
public EmptyNode(String displayedMessage) {
|
||||||
|
super(Children.create(new EmptyNodeChildren(displayedMessage), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class EmptyNodeChildren extends ChildFactory<String> {
|
||||||
|
|
||||||
|
String displayedMessage;
|
||||||
|
|
||||||
|
private EmptyNodeChildren(String displayedMessage) {
|
||||||
|
this.displayedMessage = displayedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<String> keys) {
|
||||||
|
keys.add(displayedMessage);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(String key) {
|
||||||
|
return new MessageNode(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The single child node of an EmptyNode, responsible for displaying a
|
||||||
|
* message as the sole item in its property sheet.
|
||||||
|
*/
|
||||||
|
static class MessageNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
MessageNode(String name) {
|
||||||
|
super(Children.LEAF);
|
||||||
|
super.setName(name);
|
||||||
|
setName(name);
|
||||||
|
setDisplayName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,277 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Basis Technology Corp.
|
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.Observer;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.openide.nodes.AbstractNode;
|
|
||||||
import org.openide.nodes.ChildFactory;
|
|
||||||
import org.openide.nodes.Children;
|
|
||||||
import org.openide.nodes.Node;
|
|
||||||
import org.openide.nodes.Sheet;
|
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.openide.util.lookup.Lookups;
|
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
|
||||||
import org.sleuthkit.datamodel.Directory;
|
|
||||||
import org.sleuthkit.datamodel.File;
|
|
||||||
import org.sleuthkit.datamodel.LayoutFile;
|
|
||||||
import org.sleuthkit.datamodel.LocalFile;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
|
||||||
import org.sleuthkit.datamodel.TskData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Node for a specific file type / extension. Children of it will be the files
|
|
||||||
* of that type.
|
|
||||||
*/
|
|
||||||
public class FileTypeByExtNode extends DisplayableItemNode {
|
|
||||||
|
|
||||||
FileTypeExtensionFilters.SearchFilterInterface filter;
|
|
||||||
SleuthkitCase skCase;
|
|
||||||
|
|
||||||
// deprecated in favor of the version that takes an observable to provide refresh updates
|
|
||||||
@Deprecated
|
|
||||||
FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
|
|
||||||
super(Children.create(new FileTypeChildFactory(filter, skCase), true), Lookups.singleton(filter.getDisplayName()));
|
|
||||||
this.filter = filter;
|
|
||||||
this.skCase = skCase;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param filter Extensions that will be shown for this node
|
|
||||||
* @param skCase
|
|
||||||
* @param o Observable that sends updates when the child factories
|
|
||||||
* should refresh
|
|
||||||
*/
|
|
||||||
FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
|
||||||
super(Children.create(new FileTypeChildFactory(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
|
||||||
this.filter = filter;
|
|
||||||
this.skCase = skCase;
|
|
||||||
init();
|
|
||||||
o.addObserver(new FileTypeNodeObserver());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
super.setName(filter.getName());
|
|
||||||
updateDisplayName();
|
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the display name when new events are fired
|
|
||||||
private class FileTypeNodeObserver implements Observer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
updateDisplayName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplayName() {
|
|
||||||
final long count = FileTypeChildFactory.calculateItems(skCase, filter);
|
|
||||||
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Sheet createSheet() {
|
|
||||||
Sheet s = super.createSheet();
|
|
||||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
|
||||||
if (ss == null) {
|
|
||||||
ss = Sheet.createPropertiesSet();
|
|
||||||
s.put(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.filterType.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.filterType.displayName"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.filterType.desc"),
|
|
||||||
filter.getDisplayName()));
|
|
||||||
String extensions = "";
|
|
||||||
for (String ext : filter.getFilter()) {
|
|
||||||
extensions += "'" + ext + "', ";
|
|
||||||
}
|
|
||||||
extensions = extensions.substring(0, extensions.lastIndexOf(','));
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.fileExt.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.fileExt.displayName"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypeNode.createSheet.fileExt.desc"),
|
|
||||||
extensions));
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Consider allowing different configurations for Images, Videos, etc
|
|
||||||
* (in which case we'd return getClass().getName() + filter.getName()
|
|
||||||
* for all filters).
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Child node factory for a specific file type - does the database query.
|
|
||||||
*/
|
|
||||||
public static class FileTypeChildFactory extends ChildFactory.Detachable<Content> {
|
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
|
||||||
private final FileTypeExtensionFilters.SearchFilterInterface filter;
|
|
||||||
private final static Logger logger = Logger.getLogger(FileTypeChildFactory.class.getName());
|
|
||||||
private Observable notifier;
|
|
||||||
|
|
||||||
// use the constructor that gets an observable passed in for updates
|
|
||||||
@Deprecated
|
|
||||||
FileTypeChildFactory(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
|
|
||||||
super();
|
|
||||||
this.filter = filter;
|
|
||||||
this.skCase = skCase;
|
|
||||||
notifier = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param filter Extensions to display
|
|
||||||
* @param skCase
|
|
||||||
* @param o Observable that will notify when there could be new
|
|
||||||
* data to display
|
|
||||||
*/
|
|
||||||
FileTypeChildFactory(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
|
||||||
super();
|
|
||||||
this.filter = filter;
|
|
||||||
this.skCase = skCase;
|
|
||||||
notifier = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addNotify() {
|
|
||||||
if (notifier != null) {
|
|
||||||
notifier.addObserver(observer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void removeNotify() {
|
|
||||||
if (notifier != null) {
|
|
||||||
notifier.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private final Observer observer = new FileTypeChildFactoryObserver();
|
|
||||||
|
|
||||||
// Cause refresh of children if there are changes
|
|
||||||
private class FileTypeChildFactoryObserver implements Observer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
refresh(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get children count without actually loading all nodes
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static long calculateItems(SleuthkitCase sleuthkitCase, FileTypeExtensionFilters.SearchFilterInterface filter) {
|
|
||||||
try {
|
|
||||||
return sleuthkitCase.countFilesWhere(createQuery(filter));
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<Content> list) {
|
|
||||||
try {
|
|
||||||
List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(filter));
|
|
||||||
list.addAll(files);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createQuery(FileTypeExtensionFilters.SearchFilterInterface filter) {
|
|
||||||
StringBuilder query = new StringBuilder();
|
|
||||||
query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
|
|
||||||
if (UserPreferences.hideKnownFilesInViewsTree()) {
|
|
||||||
query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
|
|
||||||
}
|
|
||||||
query.append(" AND (NULL"); //NON-NLS
|
|
||||||
for (String s : filter.getFilter()) {
|
|
||||||
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
|
||||||
}
|
|
||||||
query.append(')');
|
|
||||||
return query.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(Content key) {
|
|
||||||
return key.accept(new ContentVisitor.Default<AbstractNode>() {
|
|
||||||
@Override
|
|
||||||
public FileNode visit(File f) {
|
|
||||||
return new FileNode(f, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DirectoryNode visit(Directory d) {
|
|
||||||
return new DirectoryNode(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LayoutFileNode visit(LayoutFile lf) {
|
|
||||||
return new LayoutFileNode(lf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalFileNode visit(DerivedFile df) {
|
|
||||||
return new LocalFileNode(df);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalFileNode visit(LocalFile lf) {
|
|
||||||
return new LocalFileNode(lf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractNode defaultVisit(Content di) {
|
|
||||||
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2013 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -74,4 +74,8 @@ public class FileTypeExtensions {
|
|||||||
public static List<String> getArchiveExtensions() {
|
public static List<String> getArchiveExtensions() {
|
||||||
return ARCHIVE_EXTENSIONS;
|
return ARCHIVE_EXTENSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FileTypeExtensions() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,15 +22,14 @@ import java.util.Arrays;
|
|||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File Types node support
|
* File Types node support
|
||||||
*/
|
*/
|
||||||
public class FileTypes implements AutopsyVisitableItem {
|
public final class FileTypes implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
|
|
||||||
FileTypes(SleuthkitCase skCase) {
|
FileTypes(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
@ -48,14 +47,14 @@ public class FileTypes implements AutopsyVisitableItem {
|
|||||||
/**
|
/**
|
||||||
* Node which will contain By Mime Type and By Extension nodes.
|
* Node which will contain By Mime Type and By Extension nodes.
|
||||||
*/
|
*/
|
||||||
public static class FileTypesNode extends DisplayableItemNode {
|
public static final class FileTypesNode extends DisplayableItemNode {
|
||||||
|
|
||||||
@NbBundle.Messages("FileTypesNew.name.text=File Types")
|
@NbBundle.Messages("FileTypes.name.text=File Types")
|
||||||
private static final String NAME = Bundle.FileTypesNew_name_text();
|
private static final String NAME = Bundle.FileTypes_name_text();
|
||||||
|
|
||||||
public FileTypesNode(SleuthkitCase sleuthkitCase) {
|
FileTypesNode(SleuthkitCase sleuthkitCase) {
|
||||||
super(new RootContentChildren(Arrays.asList(
|
super(new RootContentChildren(Arrays.asList(
|
||||||
new FileTypeExtensionFilters(sleuthkitCase),
|
new FileTypesByExtension(sleuthkitCase),
|
||||||
new FileTypesByMimeType(sleuthkitCase)
|
new FileTypesByMimeType(sleuthkitCase)
|
||||||
)), Lookups.singleton(NAME));
|
)), Lookups.singleton(NAME));
|
||||||
setName(NAME);
|
setName(NAME);
|
||||||
@ -75,9 +74,9 @@ public class FileTypes implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"FileTypesNew.createSheet.name.name=Name",
|
"FileTypes.createSheet.name.name=Name",
|
||||||
"FileTypesNew.createSheet.name.displayName=Name",
|
"FileTypes.createSheet.name.displayName=Name",
|
||||||
"FileTypesNew.createSheet.name.desc=no description"})
|
"FileTypes.createSheet.name.desc=no description"})
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet s = super.createSheet();
|
Sheet s = super.createSheet();
|
||||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||||
@ -86,9 +85,9 @@ public class FileTypes implements AutopsyVisitableItem {
|
|||||||
s.put(ss);
|
s.put(ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(),
|
ss.put(new NodeProperty<>(Bundle.FileTypes_createSheet_name_name(),
|
||||||
Bundle.FileTypesNew_createSheet_name_displayName(),
|
Bundle.FileTypes_createSheet_name_displayName(),
|
||||||
Bundle.FileTypesNew_createSheet_name_desc(),
|
Bundle.FileTypes_createSheet_name_desc(),
|
||||||
NAME
|
NAME
|
||||||
));
|
));
|
||||||
return s;
|
return s;
|
||||||
|
@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 2011-2015 Basis Technology Corp.
|
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import java.beans.PropertyChangeEvent;
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Observable;
|
|
||||||
import org.openide.nodes.ChildFactory;
|
|
||||||
import org.openide.nodes.Children;
|
|
||||||
import org.openide.nodes.Node;
|
|
||||||
import org.openide.nodes.Sheet;
|
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.openide.util.lookup.Lookups;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Node for root of file types view. Children are nodes for specific types.
|
|
||||||
*/
|
|
||||||
public class FileTypesByExtNode extends DisplayableItemNode {
|
|
||||||
|
|
||||||
private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesNode.fname.text");
|
|
||||||
private final FileTypeExtensionFilters.RootFilter filter;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param skCase
|
|
||||||
* @param filter null to display root node of file type tree, pass in
|
|
||||||
* something to provide a sub-node.
|
|
||||||
*/
|
|
||||||
FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) {
|
|
||||||
super(Children.create(new FileTypesByExtChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
|
||||||
this.filter = filter;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param skCase
|
|
||||||
* @param filter
|
|
||||||
* @param o Observable that was created by a higher-level node that
|
|
||||||
* provides updates on events
|
|
||||||
*/
|
|
||||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) {
|
|
||||||
super(Children.create(new FileTypesByExtChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
|
||||||
this.filter = filter;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
// root node of tree
|
|
||||||
if (filter == null) {
|
|
||||||
super.setName(FNAME);
|
|
||||||
super.setDisplayName(FNAME);
|
|
||||||
} // sub-node in file tree (i.e. documents, exec, etc.)
|
|
||||||
else {
|
|
||||||
super.setName(filter.getName());
|
|
||||||
super.setDisplayName(filter.getDisplayName());
|
|
||||||
}
|
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Sheet createSheet() {
|
|
||||||
Sheet s = super.createSheet();
|
|
||||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
|
||||||
if (ss == null) {
|
|
||||||
ss = Sheet.createPropertiesSet();
|
|
||||||
s.put(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesNode.createSheet.name.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypesNode.createSheet.name.displayName"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "FileTypesNode.createSheet.name.desc"),
|
|
||||||
getName()));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
/**
|
|
||||||
* Because Documents and Executable are further expandable, their
|
|
||||||
* column order settings should be stored separately.
|
|
||||||
*/
|
|
||||||
if(filter == null)
|
|
||||||
return getClass().getName();
|
|
||||||
if (filter.equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER) ||
|
|
||||||
filter.equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER))
|
|
||||||
return getClass().getName() + filter.getName();
|
|
||||||
return getClass().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static class FileTypesByExtChildren extends ChildFactory<FileTypeExtensionFilters.SearchFilterInterface> {
|
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
|
||||||
private FileTypeExtensionFilters.RootFilter filter;
|
|
||||||
private Observable notifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param skCase
|
|
||||||
* @param filter Is null for root node
|
|
||||||
* @param o Observable that provides updates based on events being
|
|
||||||
* fired (or null if one needs to be created)
|
|
||||||
*/
|
|
||||||
public FileTypesByExtChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) {
|
|
||||||
super();
|
|
||||||
this.skCase = skCase;
|
|
||||||
this.filter = filter;
|
|
||||||
if (o == null) {
|
|
||||||
this.notifier = new FileTypesByExtChildrenObservable();
|
|
||||||
} else {
|
|
||||||
this.notifier = o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens for case and ingest invest. Updates observers when events are
|
|
||||||
* fired. FileType and FileTypes nodes are all listening to this.
|
|
||||||
*/
|
|
||||||
private final class FileTypesByExtChildrenObservable extends Observable {
|
|
||||||
|
|
||||||
FileTypesByExtChildrenObservable() {
|
|
||||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
|
||||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
|
||||||
Case.addPropertyChangeListener(pcl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeListeners() {
|
|
||||||
deleteObservers();
|
|
||||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
|
||||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
|
||||||
Case.removePropertyChangeListener(pcl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
|
||||||
String eventType = evt.getPropertyName();
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
|
||||||
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
|
||||||
/**
|
|
||||||
* Checking for a current case is a stop gap measure
|
|
||||||
* until a different way of handling the closing of
|
|
||||||
* cases is worked out. Currently, remote events may be
|
|
||||||
* received for a case that is already closed.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
Case.getCurrentCase();
|
|
||||||
update();
|
|
||||||
} catch (IllegalStateException notUsed) {
|
|
||||||
/**
|
|
||||||
* Case is closed, do nothing.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
|
||||||
if (evt.getNewValue() == null) {
|
|
||||||
removeListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void update() {
|
|
||||||
setChanged();
|
|
||||||
notifyObservers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<FileTypeExtensionFilters.SearchFilterInterface> list) {
|
|
||||||
// root node
|
|
||||||
if (filter == null) {
|
|
||||||
list.addAll(Arrays.asList(FileTypeExtensionFilters.RootFilter.values()));
|
|
||||||
} // document and executable has another level of nodes
|
|
||||||
else if (filter.equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER)) {
|
|
||||||
list.addAll(Arrays.asList(FileTypeExtensionFilters.DocumentFilter.values()));
|
|
||||||
} else if (filter.equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER)) {
|
|
||||||
list.addAll(Arrays.asList(FileTypeExtensionFilters.ExecutableFilter.values()));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(FileTypeExtensionFilters.SearchFilterInterface key) {
|
|
||||||
// make new nodes for the sub-nodes
|
|
||||||
if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
|
|
||||||
return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER, notifier);
|
|
||||||
} else if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER.getName())) {
|
|
||||||
return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER, notifier);
|
|
||||||
} else {
|
|
||||||
return new FileTypeByExtNode(key, skCase, notifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,639 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.openide.nodes.AbstractNode;
|
||||||
|
import org.openide.nodes.ChildFactory;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.lookup.Lookups;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
|
import org.sleuthkit.datamodel.Directory;
|
||||||
|
import org.sleuthkit.datamodel.File;
|
||||||
|
import org.sleuthkit.datamodel.LayoutFile;
|
||||||
|
import org.sleuthkit.datamodel.LocalFile;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters database results by file extension.
|
||||||
|
*/
|
||||||
|
final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||||
|
|
||||||
|
private final SleuthkitCase skCase;
|
||||||
|
|
||||||
|
public FileTypesByExtension(SleuthkitCase skCase) {
|
||||||
|
this.skCase = skCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SleuthkitCase getSleuthkitCase() {
|
||||||
|
return this.skCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for case and ingest invest. Updates observers when events are
|
||||||
|
* fired. FileType and FileTypes nodes are all listening to this.
|
||||||
|
*/
|
||||||
|
private static class FileTypesByExtObservable extends Observable {
|
||||||
|
|
||||||
|
private FileTypesByExtObservable() {
|
||||||
|
super();
|
||||||
|
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||||
|
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||||
|
Case.addPropertyChangeListener(pcl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeListeners() {
|
||||||
|
deleteObservers();
|
||||||
|
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||||
|
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||||
|
Case.removePropertyChangeListener(pcl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||||
|
String eventType = evt.getPropertyName();
|
||||||
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
|
/**
|
||||||
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked out.
|
||||||
|
* Currently, remote events may be received for a case that is
|
||||||
|
* already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
|
if (evt.getNewValue() == null) {
|
||||||
|
removeListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node for root of file types view. Children are nodes for specific types.
|
||||||
|
*/
|
||||||
|
static class FileTypesByExtNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesByExtNode.fname.text");
|
||||||
|
private final FileTypesByExtension.RootFilter filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param skCase
|
||||||
|
* @param filter null to display root node of file type tree, pass in
|
||||||
|
* something to provide a sub-node.
|
||||||
|
*/
|
||||||
|
FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter) {
|
||||||
|
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||||
|
this.filter = filter;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param skCase
|
||||||
|
* @param filter
|
||||||
|
* @param o Observable that was created by a higher-level node that
|
||||||
|
* provides updates on events
|
||||||
|
*/
|
||||||
|
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||||
|
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||||
|
this.filter = filter;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
// root node of tree
|
||||||
|
if (filter == null) {
|
||||||
|
super.setName(FNAME);
|
||||||
|
super.setDisplayName(FNAME);
|
||||||
|
} // sub-node in file tree (i.e. documents, exec, etc.)
|
||||||
|
else {
|
||||||
|
super.setName(filter.getName());
|
||||||
|
super.setDisplayName(filter.getDisplayName());
|
||||||
|
}
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
Sheet s = super.createSheet();
|
||||||
|
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||||
|
if (ss == null) {
|
||||||
|
ss = Sheet.createPropertiesSet();
|
||||||
|
s.put(ss);
|
||||||
|
}
|
||||||
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getName()));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
/**
|
||||||
|
* Because Documents and Executable are further expandable, their
|
||||||
|
* column order settings should be stored separately.
|
||||||
|
*/
|
||||||
|
if (filter == null) {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
if (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER) || filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER)) {
|
||||||
|
return getClass().getName() + filter.getName();
|
||||||
|
}
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FileTypesByExtNodeChildren extends ChildFactory<FileTypesByExtension.SearchFilterInterface> {
|
||||||
|
|
||||||
|
private final SleuthkitCase skCase;
|
||||||
|
private final FileTypesByExtension.RootFilter filter;
|
||||||
|
private final Observable notifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param skCase
|
||||||
|
* @param filter Is null for root node
|
||||||
|
* @param o Observable that provides updates based on events
|
||||||
|
* being fired (or null if one needs to be created)
|
||||||
|
*/
|
||||||
|
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||||
|
super();
|
||||||
|
this.skCase = skCase;
|
||||||
|
this.filter = filter;
|
||||||
|
if (o == null) {
|
||||||
|
this.notifier = new FileTypesByExtObservable();
|
||||||
|
} else {
|
||||||
|
this.notifier = o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<FileTypesByExtension.SearchFilterInterface> list) {
|
||||||
|
// root node
|
||||||
|
if (filter == null) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.RootFilter.values()));
|
||||||
|
} // document and executable has another level of nodes
|
||||||
|
else if (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER)) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.DocumentFilter.values()));
|
||||||
|
} else if (filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER)) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.ExecutableFilter.values()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(FileTypesByExtension.SearchFilterInterface key) {
|
||||||
|
// make new nodes for the sub-nodes
|
||||||
|
if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
|
||||||
|
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER, notifier);
|
||||||
|
} else if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER.getName())) {
|
||||||
|
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER, notifier);
|
||||||
|
} else {
|
||||||
|
return new FileExtensionNode(key, skCase, notifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node for a specific file type / extension. Children of it will be the
|
||||||
|
* files of that type.
|
||||||
|
*/
|
||||||
|
static class FileExtensionNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
FileTypesByExtension.SearchFilterInterface filter;
|
||||||
|
SleuthkitCase skCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param filter Extensions that will be shown for this node
|
||||||
|
* @param skCase
|
||||||
|
* @param o Observable that sends updates when the child factories
|
||||||
|
* should refresh
|
||||||
|
*/
|
||||||
|
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
||||||
|
super(Children.create(new FileExtensionNodeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
|
this.filter = filter;
|
||||||
|
this.skCase = skCase;
|
||||||
|
init();
|
||||||
|
o.addObserver(new ByExtNodeObserver());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
super.setName(filter.getName());
|
||||||
|
updateDisplayName();
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the display name when new events are fired
|
||||||
|
private class ByExtNodeObserver implements Observer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDisplayName() {
|
||||||
|
final long count = FileExtensionNodeChildren.calculateItems(skCase, filter);
|
||||||
|
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
Sheet s = super.createSheet();
|
||||||
|
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||||
|
if (ss == null) {
|
||||||
|
ss = Sheet.createPropertiesSet();
|
||||||
|
s.put(ss);
|
||||||
|
}
|
||||||
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.desc"), filter.getDisplayName()));
|
||||||
|
String extensions = "";
|
||||||
|
for (String ext : filter.getFilter()) {
|
||||||
|
extensions += "'" + ext + "', ";
|
||||||
|
}
|
||||||
|
extensions = extensions.substring(0, extensions.lastIndexOf(','));
|
||||||
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consider allowing different configurations for Images, Videos, etc
|
||||||
|
* (in which case we'd return getClass().getName() + filter.getName()
|
||||||
|
* for all filters).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Child node factory for a specific file type - does the database
|
||||||
|
* query.
|
||||||
|
*/
|
||||||
|
private static class FileExtensionNodeChildren extends ChildFactory.Detachable<Content> {
|
||||||
|
|
||||||
|
private final SleuthkitCase skCase;
|
||||||
|
private final FileTypesByExtension.SearchFilterInterface filter;
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(FileExtensionNodeChildren.class.getName());
|
||||||
|
private final Observable notifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param filter Extensions to display
|
||||||
|
* @param skCase
|
||||||
|
* @param o Observable that will notify when there could be new
|
||||||
|
* data to display
|
||||||
|
*/
|
||||||
|
private FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
||||||
|
super();
|
||||||
|
this.filter = filter;
|
||||||
|
this.skCase = skCase;
|
||||||
|
notifier = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
if (notifier != null) {
|
||||||
|
notifier.addObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeNotify() {
|
||||||
|
if (notifier != null) {
|
||||||
|
notifier.deleteObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private final Observer observer = new FileTypeChildFactoryObserver();
|
||||||
|
|
||||||
|
// Cause refresh of children if there are changes
|
||||||
|
private class FileTypeChildFactoryObserver implements Observer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get children count without actually loading all nodes
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static long calculateItems(SleuthkitCase sleuthkitCase, FileTypesByExtension.SearchFilterInterface filter) {
|
||||||
|
try {
|
||||||
|
return sleuthkitCase.countFilesWhere(createQuery(filter));
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<Content> list) {
|
||||||
|
try {
|
||||||
|
List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(filter));
|
||||||
|
list.addAll(files);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
||||||
|
StringBuilder query = new StringBuilder();
|
||||||
|
query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
|
||||||
|
if (UserPreferences.hideKnownFilesInViewsTree()) {
|
||||||
|
query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
|
||||||
|
}
|
||||||
|
query.append(" AND (NULL"); //NON-NLS
|
||||||
|
for (String s : filter.getFilter()) {
|
||||||
|
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
||||||
|
}
|
||||||
|
query.append(')');
|
||||||
|
return query.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(Content key) {
|
||||||
|
return key.accept(new ContentVisitor.Default<AbstractNode>() {
|
||||||
|
@Override
|
||||||
|
public FileNode visit(File f) {
|
||||||
|
return new FileNode(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryNode visit(Directory d) {
|
||||||
|
return new DirectoryNode(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutFileNode visit(LayoutFile lf) {
|
||||||
|
return new LayoutFileNode(lf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalFileNode visit(DerivedFile df) {
|
||||||
|
return new LocalFileNode(df);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalFileNode visit(LocalFile lf) {
|
||||||
|
return new LocalFileNode(lf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractNode defaultVisit(Content di) {
|
||||||
|
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// root node filters
|
||||||
|
enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
||||||
|
|
||||||
|
TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskImgFilter.text"),
|
||||||
|
FileTypeExtensions.getImageExtensions()),
|
||||||
|
TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskVideoFilter.text"),
|
||||||
|
FileTypeExtensions.getVideoExtensions()),
|
||||||
|
TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskAudioFilter.text"),
|
||||||
|
FileTypeExtensions.getAudioExtensions()),
|
||||||
|
TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskArchiveFilter.text"),
|
||||||
|
FileTypeExtensions.getArchiveExtensions()),
|
||||||
|
TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"),
|
||||||
|
Arrays.asList(".doc", ".docx", ".pdf", ".xls", ".rtf", ".txt")), //NON-NLS
|
||||||
|
TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskExecFilter.text"),
|
||||||
|
Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final String name;
|
||||||
|
private final String displayName;
|
||||||
|
private final List<String> filter;
|
||||||
|
|
||||||
|
private RootFilter(int id, String name, String displayName, List<String> filter) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return this.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFilter() {
|
||||||
|
return this.filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// document sub-node filters
|
||||||
|
enum DocumentFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
||||||
|
|
||||||
|
AUT_DOC_HTML(0, "AUT_DOC_HTML", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocHtmlFilter.text"),
|
||||||
|
Arrays.asList(".htm", ".html")), //NON-NLS
|
||||||
|
AUT_DOC_OFFICE(1, "AUT_DOC_OFFICE", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocOfficeFilter.text"),
|
||||||
|
Arrays.asList(".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx")), //NON-NLS
|
||||||
|
AUT_DOC_PDF(2, "AUT_DOC_PDF", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autoDocPdfFilter.text"),
|
||||||
|
Arrays.asList(".pdf")), //NON-NLS
|
||||||
|
AUT_DOC_TXT(3, "AUT_DOC_TXT", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocTxtFilter.text"),
|
||||||
|
Arrays.asList(".txt")), //NON-NLS
|
||||||
|
AUT_DOC_RTF(4, "AUT_DOC_RTF", //NON-NLS
|
||||||
|
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocRtfFilter.text"),
|
||||||
|
Arrays.asList(".rtf")); //NON-NLS
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final String name;
|
||||||
|
private final String displayName;
|
||||||
|
private final List<String> filter;
|
||||||
|
|
||||||
|
private DocumentFilter(int id, String name, String displayName, List<String> filter) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return this.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFilter() {
|
||||||
|
return this.filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// executable sub-node filters
|
||||||
|
enum ExecutableFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
||||||
|
|
||||||
|
ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")), //NON-NLS
|
||||||
|
ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")), //NON-NLS
|
||||||
|
ExecutableFilter_BAT(2, "ExecutableFilter_BAT", ".bat", Arrays.asList(".bat")), //NON-NLS
|
||||||
|
ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS
|
||||||
|
ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final String name;
|
||||||
|
private final String displayName;
|
||||||
|
private final List<String> filter;
|
||||||
|
|
||||||
|
private ExecutableFilter(int id, String name, String displayName, List<String> filter) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return this.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFilter() {
|
||||||
|
return this.filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchFilterInterface {
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
public int getId();
|
||||||
|
|
||||||
|
public String getDisplayName();
|
||||||
|
|
||||||
|
public List<String> getFilter();
|
||||||
|
}
|
||||||
|
}
|
@ -57,9 +57,9 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
* Listener which is checking for changes in IngestJobEvent Completed or
|
* Listener which is checking for changes in IngestJobEvent Completed or
|
||||||
* Cancelled and IngestModuleEvent Content Changed.
|
* Cancelled and IngestModuleEvent Content Changed.
|
||||||
*/
|
*/
|
||||||
public class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private static SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
/**
|
/**
|
||||||
* The nodes of this tree will be determined dynamically by the mimetypes
|
* The nodes of this tree will be determined dynamically by the mimetypes
|
||||||
* which exist in the database. This hashmap will store them with the media
|
* which exist in the database. This hashmap will store them with the media
|
||||||
@ -72,28 +72,25 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
* The pcl is in the class because it has the easiest mechanisms to add
|
* The pcl is in the class because it has the easiest mechanisms to add
|
||||||
* and remove itself during its life cycles.
|
* and remove itself during its life cycles.
|
||||||
*/
|
*/
|
||||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||||
@Override
|
String eventType = evt.getPropertyName();
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
String eventType = evt.getPropertyName();
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
// || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
|| eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||||
// || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())
|
/**
|
||||||
|| eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked out.
|
||||||
|
* Currently, remote events may be received for a case that is
|
||||||
|
* already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
populateHashMap();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
/**
|
/**
|
||||||
* Checking for a current case is a stop gap measure until a
|
* Case is closed, do nothing.
|
||||||
* different way of handling the closing of cases is worked out.
|
|
||||||
* Currently, remote events may be received for a case that is
|
|
||||||
* already closed.
|
|
||||||
*/
|
*/
|
||||||
try {
|
|
||||||
Case.getCurrentCase();
|
|
||||||
populateHashMap();
|
|
||||||
} catch (IllegalStateException notUsed) {
|
|
||||||
/**
|
|
||||||
* Case is closed, do nothing.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -128,11 +125,11 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
existingMimeTypes.clear();
|
existingMimeTypes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSleuthkitCase() == null) {
|
if (skCase == null) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try (SleuthkitCase.CaseDbQuery dbQuery = getSleuthkitCase().executeQuery(allDistinctMimeTypesQuery.toString())) {
|
try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) {
|
||||||
ResultSet resultSet = dbQuery.getResultSet();
|
ResultSet resultSet = dbQuery.getResultSet();
|
||||||
synchronized (existingMimeTypes) {
|
synchronized (existingMimeTypes) {
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
@ -158,35 +155,44 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
FileTypesByMimeType(SleuthkitCase skCase) {
|
FileTypesByMimeType(SleuthkitCase skCase) {
|
||||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||||
FileTypesByMimeType.skCase = skCase;
|
this.skCase = skCase;
|
||||||
populateHashMap();
|
populateHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return skCase - the sluethkit case
|
|
||||||
*/
|
|
||||||
SleuthkitCase getSleuthkitCase() {
|
|
||||||
return skCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to check if the node in question is a ByMimeTypeNode which is
|
||||||
|
* empty.
|
||||||
|
*
|
||||||
|
* @param node the Node which you wish to check.
|
||||||
|
* @return True if originNode is an instance of ByMimeTypeNode and is empty,
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isEmptyMimeTypeNode(Node node) {
|
||||||
|
boolean isEmptyMimeNode = false;
|
||||||
|
if (node instanceof FileTypesByMimeType.ByMimeTypeNode && ((FileTypesByMimeType.ByMimeTypeNode) node).isEmpty()) {
|
||||||
|
isEmptyMimeNode = true;
|
||||||
|
}
|
||||||
|
return isEmptyMimeNode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which represents the root node of the "By MIME Type" tree, will
|
* Class which represents the root node of the "By MIME Type" tree, will
|
||||||
* have children of each media type present in the database or no children
|
* have children of each media type present in the database or no children
|
||||||
* when the file detection module has not been run and MIME type is
|
* when the file detection module has not been run and MIME type is
|
||||||
* currently unknown.
|
* currently unknown.
|
||||||
*/
|
*/
|
||||||
public class FileTypesByMimeTypeNode extends DisplayableItemNode {
|
class ByMimeTypeNode extends DisplayableItemNode {
|
||||||
|
|
||||||
@NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type")
|
@NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type")
|
||||||
final String NAME = Bundle.FileTypesByMimeType_name_text();
|
final String NAME = Bundle.FileTypesByMimeType_name_text();
|
||||||
|
|
||||||
FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) {
|
ByMimeTypeNode() {
|
||||||
super(Children.create(new FileTypesByMimeTypeNodeChildren(), true));
|
super(Children.create(new ByMimeTypeNodeChildren(), true));
|
||||||
super.setName(NAME);
|
super.setName(NAME);
|
||||||
super.setDisplayName(NAME);
|
super.setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
||||||
@ -207,7 +213,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
return getClass().getName();
|
return getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
boolean isEmpty() {
|
||||||
return existingMimeTypes.isEmpty();
|
return existingMimeTypes.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,9 +223,9 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
* Creates the children for the "By MIME Type" node these children will each
|
* Creates the children for the "By MIME Type" node these children will each
|
||||||
* represent a distinct media type present in the DB
|
* represent a distinct media type present in the DB
|
||||||
*/
|
*/
|
||||||
class FileTypesByMimeTypeNodeChildren extends ChildFactory<String> implements Observer {
|
private class ByMimeTypeNodeChildren extends ChildFactory<String> implements Observer {
|
||||||
|
|
||||||
public FileTypesByMimeTypeNodeChildren() {
|
private ByMimeTypeNodeChildren() {
|
||||||
super();
|
super();
|
||||||
addObserver(this);
|
addObserver(this);
|
||||||
}
|
}
|
||||||
@ -245,14 +251,13 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Media type node created by the FileTypesByMimeTypeNodeChildren and
|
* The Media type node created by the ByMimeTypeNodeChildren and contains
|
||||||
* contains one of the unique media types present in the database for this
|
* one of the unique media types present in the database for this case.
|
||||||
* case.
|
|
||||||
*/
|
*/
|
||||||
class MediaTypeNode extends DisplayableItemNode {
|
class MediaTypeNode extends DisplayableItemNode {
|
||||||
|
|
||||||
MediaTypeNode(String name) {
|
MediaTypeNode(String name) {
|
||||||
super(Children.create(new MediaTypeChildren(name), true));
|
super(Children.create(new MediaTypeNodeChildren(name), true));
|
||||||
setName(name);
|
setName(name);
|
||||||
setDisplayName(name);
|
setDisplayName(name);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
||||||
@ -276,15 +281,15 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates children fro media type nodes, children will be MediaSubTypeNodes
|
* Creates children for media type nodes, children will be MediaSubTypeNodes
|
||||||
* and represent one of the subtypes which are present in the database of
|
* and represent one of the subtypes which are present in the database of
|
||||||
* their media type.
|
* their media type.
|
||||||
*/
|
*/
|
||||||
class MediaTypeChildren extends ChildFactory<String> implements Observer {
|
private class MediaTypeNodeChildren extends ChildFactory<String> implements Observer {
|
||||||
|
|
||||||
String mediaType;
|
String mediaType;
|
||||||
|
|
||||||
MediaTypeChildren(String name) {
|
MediaTypeNodeChildren(String name) {
|
||||||
addObserver(this);
|
addObserver(this);
|
||||||
this.mediaType = name;
|
this.mediaType = name;
|
||||||
}
|
}
|
||||||
@ -335,7 +340,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
*/
|
*/
|
||||||
private void updateDisplayName(String mimeType) {
|
private void updateDisplayName(String mimeType) {
|
||||||
|
|
||||||
final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(getSleuthkitCase(), mimeType);
|
final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType);
|
||||||
|
|
||||||
super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")");
|
super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")");
|
||||||
}
|
}
|
||||||
@ -376,7 +381,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
|
|
||||||
private final String mimeType;
|
private final String mimeType;
|
||||||
|
|
||||||
MediaSubTypeNodeChildren(String mimeType) {
|
private MediaSubTypeNodeChildren(String mimeType) {
|
||||||
super();
|
super();
|
||||||
addObserver(this);
|
addObserver(this);
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
@ -388,7 +393,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
* @return count(*) - the number of items that will be shown in this
|
* @return count(*) - the number of items that will be shown in this
|
||||||
* items Directory Listing
|
* items Directory Listing
|
||||||
*/
|
*/
|
||||||
private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) {
|
private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) {
|
||||||
try {
|
try {
|
||||||
return sleuthkitCase.countFilesWhere(createQuery(mime_type));
|
return sleuthkitCase.countFilesWhere(createQuery(mime_type));
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
@ -440,13 +445,12 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS
|
query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS
|
||||||
return query.toString();
|
return query.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the content to populate the Directory Listing Table view for
|
* Creates the content to populate the Directory Listing Table view for
|
||||||
* each file
|
* each file
|
||||||
@ -490,66 +494,4 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* EmptyNode Class made for edge case where no mime exist in the database
|
|
||||||
* yet. Creates a node to display information on why the tree is empty.
|
|
||||||
*
|
|
||||||
* Swapped for the FileTypesByMimeType node in
|
|
||||||
* DirectoryTreeTopComponent.respondSelection
|
|
||||||
*/
|
|
||||||
static public class EmptyNode extends AbstractNode {
|
|
||||||
|
|
||||||
public EmptyNode() {
|
|
||||||
super(Children.create(new EmptyChildFactory(), true));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class EmptyChildFactory extends ChildFactory<String> {
|
|
||||||
|
|
||||||
String FILE_ID_MSG = "Data not available. Run file type identification module."; //NON-NLS
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<String> list) {
|
|
||||||
list.add(FILE_ID_MSG);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(String key) {
|
|
||||||
return new MessageNode(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MessageNode is is the info message that displays in the table view,
|
|
||||||
* by also extending a DisplayableItemNode type, rather than an
|
|
||||||
* AbstractNode type it doesn't throw an error when right clicked.
|
|
||||||
*/
|
|
||||||
static class MessageNode extends DisplayableItemNode {
|
|
||||||
|
|
||||||
MessageNode(String name) {
|
|
||||||
super(Children.LEAF);
|
|
||||||
super.setName(name);
|
|
||||||
setName(name);
|
|
||||||
setDisplayName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
return getClass().getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel.accounts;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.AutopsyVisitableItem;
|
import org.sleuthkit.autopsy.datamodel.AutopsyVisitableItem;
|
||||||
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles;
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -28,7 +28,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles.RecentFilesFilter;
|
import org.sleuthkit.autopsy.datamodel.RecentFiles.RecentFilesFilter;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
|
@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles.RecentFilesFilter;
|
import org.sleuthkit.autopsy.datamodel.RecentFiles.RecentFilesFilter;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
FileTypeExtensionFilters.tskImgFilter.text=Images
|
|
||||||
FileTypeExtensionFilters.tskVideoFilter.text=Videos
|
|
||||||
FileTypeExtensionFilters.tskAudioFilter.text=Audio
|
|
||||||
FileTypeExtensionFilters.tskArchiveFilter.text=Archives
|
|
||||||
FileTypeExtensionFilters.tskDocumentFilter.text=Documents
|
|
||||||
FileTypeExtensionFilters.tskExecFilter.text=Executable
|
|
||||||
FileTypeExtensionFilters.autDocHtmlFilter.text=HTML
|
|
||||||
FileTypeExtensionFilters.autDocOfficeFilter.text=Office
|
|
||||||
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
|
|
||||||
FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text
|
|
||||||
FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 2011 Basis Technology Corp.
|
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.datamodel.accounts;
|
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.AutopsyVisitableItem;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypeExtensions;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters database results by file extension.
|
|
||||||
*/
|
|
||||||
public class FileTypeExtensionFilters implements AutopsyVisitableItem {
|
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
|
||||||
|
|
||||||
// root node filters
|
|
||||||
public enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
|
||||||
|
|
||||||
TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskImgFilter.text"),
|
|
||||||
FileTypeExtensions.getImageExtensions()),
|
|
||||||
TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskVideoFilter.text"),
|
|
||||||
FileTypeExtensions.getVideoExtensions()),
|
|
||||||
TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskAudioFilter.text"),
|
|
||||||
FileTypeExtensions.getAudioExtensions()),
|
|
||||||
TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskArchiveFilter.text"),
|
|
||||||
FileTypeExtensions.getArchiveExtensions()),
|
|
||||||
TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskDocumentFilter.text"),
|
|
||||||
Arrays.asList(".doc", ".docx", ".pdf", ".xls", ".rtf", ".txt")), //NON-NLS
|
|
||||||
TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskExecFilter.text"),
|
|
||||||
Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
private final String name;
|
|
||||||
private final String displayName;
|
|
||||||
private final List<String> filter;
|
|
||||||
|
|
||||||
private RootFilter(int id, String name, String displayName, List<String> filter) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.filter = filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDisplayName() {
|
|
||||||
return this.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getFilter() {
|
|
||||||
return this.filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// document sub-node filters
|
|
||||||
public enum DocumentFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
|
||||||
|
|
||||||
AUT_DOC_HTML(0, "AUT_DOC_HTML", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocHtmlFilter.text"),
|
|
||||||
Arrays.asList(".htm", ".html")), //NON-NLS
|
|
||||||
AUT_DOC_OFFICE(1, "AUT_DOC_OFFICE", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocOfficeFilter.text"),
|
|
||||||
Arrays.asList(".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx")), //NON-NLS
|
|
||||||
AUT_DOC_PDF(2, "AUT_DOC_PDF", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autoDocPdfFilter.text"),
|
|
||||||
Arrays.asList(".pdf")), //NON-NLS
|
|
||||||
AUT_DOC_TXT(3, "AUT_DOC_TXT", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocTxtFilter.text"),
|
|
||||||
Arrays.asList(".txt")), //NON-NLS
|
|
||||||
AUT_DOC_RTF(4, "AUT_DOC_RTF", //NON-NLS
|
|
||||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocRtfFilter.text"),
|
|
||||||
Arrays.asList(".rtf")); //NON-NLS
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
private final String name;
|
|
||||||
private final String displayName;
|
|
||||||
private final List<String> filter;
|
|
||||||
|
|
||||||
private DocumentFilter(int id, String name, String displayName, List<String> filter) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.filter = filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDisplayName() {
|
|
||||||
return this.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getFilter() {
|
|
||||||
return this.filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// executable sub-node filters
|
|
||||||
public enum ExecutableFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
|
||||||
|
|
||||||
ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")), //NON-NLS
|
|
||||||
ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")), //NON-NLS
|
|
||||||
ExecutableFilter_BAT(2, "ExecutableFilter_BAT", ".bat", Arrays.asList(".bat")), //NON-NLS
|
|
||||||
ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS
|
|
||||||
ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
private final String name;
|
|
||||||
private final String displayName;
|
|
||||||
private final List<String> filter;
|
|
||||||
|
|
||||||
private ExecutableFilter(int id, String name, String displayName, List<String> filter) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.filter = filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDisplayName() {
|
|
||||||
return this.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getFilter() {
|
|
||||||
return this.filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileTypeExtensionFilters(SleuthkitCase skCase) {
|
|
||||||
this.skCase = skCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
|
||||||
return v.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SleuthkitCase getSleuthkitCase() {
|
|
||||||
return this.skCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SearchFilterInterface {
|
|
||||||
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
public int getId();
|
|
||||||
|
|
||||||
public String getDisplayName();
|
|
||||||
|
|
||||||
public List<String> getFilter();
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.directorytree;
|
package org.sleuthkit.autopsy.directorytree;
|
||||||
|
|
||||||
|
import org.sleuthkit.autopsy.datamodel.EmptyNode;
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
@ -61,7 +62,6 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.DataSources;
|
import org.sleuthkit.autopsy.datamodel.DataSources;
|
||||||
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType.EmptyNode;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
|
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||||
@ -96,7 +96,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
private final LinkedList<String[]> backList;
|
private final LinkedList<String[]> backList;
|
||||||
private final LinkedList<String[]> forwardList;
|
private final LinkedList<String[]> forwardList;
|
||||||
private static final String PREFERRED_ID = "DirectoryTreeTopComponent"; //NON-NLS
|
private static final String PREFERRED_ID = "DirectoryTreeTopComponent"; //NON-NLS
|
||||||
private static final Logger logger = Logger.getLogger(DirectoryTreeTopComponent.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(DirectoryTreeTopComponent.class.getName());
|
||||||
private RootContentChildren contentChildren;
|
private RootContentChildren contentChildren;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +135,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
refreshContentTreeSafe();
|
refreshContentTreeSafe();
|
||||||
break;
|
break;
|
||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
||||||
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
||||||
// TODO: Need a way to refresh the Views subtree
|
// TODO: Need a way to refresh the Views subtree
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -313,14 +313,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
WindowManager winManager = WindowManager.getDefault();
|
WindowManager winManager = WindowManager.getDefault();
|
||||||
TopComponent win = winManager.findTopComponent(PREFERRED_ID);
|
TopComponent win = winManager.findTopComponent(PREFERRED_ID);
|
||||||
if (win == null) {
|
if (win == null) {
|
||||||
logger.warning(
|
LOGGER.warning(
|
||||||
"Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); //NON-NLS
|
"Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); //NON-NLS
|
||||||
return getDefault();
|
return getDefault();
|
||||||
}
|
}
|
||||||
if (win instanceof DirectoryTreeTopComponent) {
|
if (win instanceof DirectoryTreeTopComponent) {
|
||||||
return (DirectoryTreeTopComponent) win;
|
return (DirectoryTreeTopComponent) win;
|
||||||
}
|
}
|
||||||
logger.warning(
|
LOGGER.warning(
|
||||||
"There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS
|
"There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS
|
||||||
+ "' ID. That is a potential source of errors and unexpected behavior."); //NON-NLS
|
+ "' ID. That is a potential source of errors and unexpected behavior."); //NON-NLS
|
||||||
return getDefault();
|
return getDefault();
|
||||||
@ -435,7 +435,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
try {
|
try {
|
||||||
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)});
|
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,6 +604,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages("DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.")
|
||||||
/**
|
/**
|
||||||
* Event handler to run when selection changed
|
* Event handler to run when selection changed
|
||||||
*
|
*
|
||||||
@ -645,18 +646,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode));
|
Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode));
|
||||||
Node sffn = new SlackFileFilterNode(kffn, SlackFileFilterNode.getSelectionContext(originNode));
|
Node sffn = new SlackFileFilterNode(kffn, SlackFileFilterNode.getSelectionContext(originNode));
|
||||||
|
|
||||||
|
|
||||||
// Create a TableFilterNode with knowledge of the node's type to allow for column order settings
|
// Create a TableFilterNode with knowledge of the node's type to allow for column order settings
|
||||||
|
|
||||||
//Special case for when File Type Identification has not yet been run and
|
//Special case for when File Type Identification has not yet been run and
|
||||||
//there are no mime types to populate Files by Mime Type Tree
|
//there are no mime types to populate Files by Mime Type Tree
|
||||||
if (originNode instanceof FileTypesByMimeType.FileTypesByMimeTypeNode
|
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
|
||||||
&& ((FileTypesByMimeType.FileTypesByMimeTypeNode) originNode).isEmpty()) {
|
EmptyNode emptyNode = new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
|
||||||
EmptyNode emptyNode = new EmptyNode();
|
|
||||||
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em);
|
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em);
|
||||||
Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode));
|
Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode));
|
||||||
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
|
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
|
||||||
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty"));
|
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty")); //NON-NLS
|
||||||
} else if (originNode instanceof DisplayableItemNode) {
|
} else if (originNode instanceof DisplayableItemNode) {
|
||||||
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
|
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
|
||||||
} else {
|
} else {
|
||||||
@ -669,7 +667,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
try {
|
try {
|
||||||
displayName = content.getUniquePath();
|
displayName = content.getUniquePath();
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); //NON-NLS
|
||||||
}
|
}
|
||||||
} else if (originNode.getLookup().lookup(String.class) != null) {
|
} else if (originNode.getLookup().lookup(String.class) != null) {
|
||||||
displayName = originNode.getLookup().lookup(String.class);
|
displayName = originNode.getLookup().lookup(String.class);
|
||||||
@ -776,13 +774,13 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
Children rootChildren = em.getRootContext().getChildren();
|
Children rootChildren = em.getRootContext().getChildren();
|
||||||
Node dataSourcesFilterNode = rootChildren.findChild(DataSourcesNode.NAME);
|
Node dataSourcesFilterNode = rootChildren.findChild(DataSourcesNode.NAME);
|
||||||
if (dataSourcesFilterNode == null) {
|
if (dataSourcesFilterNode == null) {
|
||||||
logger.log(Level.SEVERE, "Cannot find data sources filter node, won't refresh the content tree"); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Cannot find data sources filter node, won't refresh the content tree"); //NON-NLS
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
|
DirectoryTreeFilterNode.OriginalNode imagesNodeOrig = dataSourcesFilterNode.getLookup().lookup(DirectoryTreeFilterNode.OriginalNode.class);
|
||||||
|
|
||||||
if (imagesNodeOrig == null) {
|
if (imagesNodeOrig == null) {
|
||||||
logger.log(Level.SEVERE, "Cannot find data sources node, won't refresh the content tree"); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Cannot find data sources node, won't refresh the content tree"); //NON-NLS
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +823,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
for (int i = 0; i < previouslySelectedNodePath.length; ++i) {
|
for (int i = 0; i < previouslySelectedNodePath.length; ++i) {
|
||||||
nodePath.append(previouslySelectedNodePath[i]).append("/");
|
nodePath.append(previouslySelectedNodePath[i]).append("/");
|
||||||
}
|
}
|
||||||
logger.log(Level.WARNING, "Failed to find any nodes to select on path " + nodePath.toString(), ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Failed to find any nodes to select on path " + nodePath.toString(), ex); //NON-NLS
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -840,7 +838,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
try {
|
try {
|
||||||
em.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode});
|
em.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode});
|
||||||
} catch (PropertyVetoException ex) {
|
} catch (PropertyVetoException ex) {
|
||||||
logger.log(Level.WARNING, "Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,7 +878,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
treeNode = hashsetRootChilds.findChild(setName);
|
treeNode = hashsetRootChilds.findChild(setName);
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||||
Node keywordRootNode = resultsChilds.findChild(typeName);
|
Node keywordRootNode = resultsChilds.findChild(typeName);
|
||||||
@ -907,7 +905,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
treeNode = listChildren.findChild(keywordName);
|
treeNode = listChildren.findChild(keywordName);
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||||
|| typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
|| typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||||
@ -924,7 +922,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
treeNode = interestingItemsRootChildren.findChild(setName);
|
treeNode = interestingItemsRootChildren.findChild(setName);
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Node extractedContent = resultsChilds.findChild(ExtractedContent.NAME);
|
Node extractedContent = resultsChilds.findChild(ExtractedContent.NAME);
|
||||||
@ -942,7 +940,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
try {
|
try {
|
||||||
em.setExploredContextAndSelection(treeNode, new Node[]{treeNode});
|
em.setExploredContextAndSelection(treeNode, new Node[]{treeNode});
|
||||||
} catch (PropertyVetoException ex) {
|
} catch (PropertyVetoException ex) {
|
||||||
logger.log(Level.WARNING, "Property Veto: ", ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "Property Veto: ", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Another thread is needed because we have to wait for dataResult to populate
|
// Another thread is needed because we have to wait for dataResult to populate
|
||||||
@ -977,7 +975,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
try {
|
try {
|
||||||
firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
|
firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
|
LOGGER.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); //NON-NLS
|
||||||
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
|
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
|
||||||
NbBundle.getMessage(this.getClass(),
|
NbBundle.getMessage(this.getClass(),
|
||||||
"DirectoryTreeTopComponent.moduleErr.msg"),
|
"DirectoryTreeTopComponent.moduleErr.msg"),
|
||||||
|
@ -717,7 +717,7 @@ public final class ImageGalleryController implements Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({"BulkTask.committingDb.status=commiting image/video database",
|
@NbBundle.Messages({"BulkTask.committingDb.status=committing image/video database",
|
||||||
"BulkTask.stopCopy.status=Stopping copy to drawable db task.",
|
"BulkTask.stopCopy.status=Stopping copy to drawable db task.",
|
||||||
"BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
"BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
||||||
abstract static private class BulkTransferTask extends BackgroundTask {
|
abstract static private class BulkTransferTask extends BackgroundTask {
|
||||||
@ -821,7 +821,7 @@ public final class ImageGalleryController implements Executor {
|
|||||||
* adds them to the Drawable DB. Uses the presence of a mimetype as an
|
* adds them to the Drawable DB. Uses the presence of a mimetype as an
|
||||||
* approximation to 'analyzed'.
|
* approximation to 'analyzed'.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"CopyAnalyzedFiles.committingDb.status=commiting image/video database",
|
@NbBundle.Messages({"CopyAnalyzedFiles.committingDb.status=committing image/video database",
|
||||||
"CopyAnalyzedFiles.stopCopy.status=Stopping copy to drawable db task.",
|
"CopyAnalyzedFiles.stopCopy.status=Stopping copy to drawable db task.",
|
||||||
"CopyAnalyzedFiles.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
"CopyAnalyzedFiles.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
||||||
static private class CopyAnalyzedFiles extends BulkTransferTask {
|
static private class CopyAnalyzedFiles extends BulkTransferTask {
|
||||||
@ -875,7 +875,7 @@ public final class ImageGalleryController implements Executor {
|
|||||||
* TODO: create methods to simplify progress value/text updates to both
|
* TODO: create methods to simplify progress value/text updates to both
|
||||||
* netbeans and ImageGallery progress/status
|
* netbeans and ImageGallery progress/status
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"PrePopulateDataSourceFiles.committingDb.status=commiting image/video database"})
|
@NbBundle.Messages({"PrePopulateDataSourceFiles.committingDb.status=committing image/video database"})
|
||||||
static private class PrePopulateDataSourceFiles extends BulkTransferTask {
|
static private class PrePopulateDataSourceFiles extends BulkTransferTask {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(PrePopulateDataSourceFiles.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(PrePopulateDataSourceFiles.class.getName());
|
||||||
|
@ -0,0 +1,185 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<NonVisualComponents>
|
||||||
|
<Component class="javax.swing.ButtonGroup" name="keywordTypeButtonGroup">
|
||||||
|
</Component>
|
||||||
|
</NonVisualComponents>
|
||||||
|
<Properties>
|
||||||
|
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="enterKeywordsLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" alignment="0" min="-2" pref="249" max="-2" attributes="0"/>
|
||||||
|
<Component id="pasteButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Component id="addButton" min="-2" pref="84" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="cancelButton" min="-2" pref="84" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="keywordTypeLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="substringRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="exactRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="regexRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="enterKeywordsLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Component id="keywordTypeLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Component id="exactRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="substringRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="regexRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="194" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" min="-2" pref="278" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="addButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="pasteButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="exactRadioButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||||
|
<ComponentRef name="keywordTypeButtonGroup"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selected" type="boolean" value="true"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.exactRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="substringRadioButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||||
|
<ComponentRef name="keywordTypeButtonGroup"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.substringRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JRadioButton" name="regexRadioButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||||
|
<ComponentRef name="keywordTypeButtonGroup"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.regexRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JTextArea" name="keywordTextArea">
|
||||||
|
<Properties>
|
||||||
|
<Property name="columns" type="int" value="20"/>
|
||||||
|
<Property name="rows" type="int" value="5"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="keywordTextAreaMouseClicked"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JLabel" name="enterKeywordsLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.enterKeywordsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="keywordTypeLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.keywordTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="addButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="cancelButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="pasteButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="AddKeywordsDialog.pasteButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pasteButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.keywordsearch;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to add one or more keywords to a list
|
||||||
|
*/
|
||||||
|
class AddKeywordsDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
|
List<String> newKeywords = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form AddKeywordsDialog.
|
||||||
|
* Note that this does not display the dialog - call display() after creation.
|
||||||
|
* @param initialKeywords Keywords to populate the list with
|
||||||
|
* @param type Starting keyword type
|
||||||
|
*/
|
||||||
|
AddKeywordsDialog(){
|
||||||
|
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||||
|
NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.addKeywordsTitle.text"),
|
||||||
|
true);
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
// Set the add button to only be active when there is text in the text area
|
||||||
|
addButton.setEnabled(false);
|
||||||
|
keywordTextArea.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
fire();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
fire();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
fire();
|
||||||
|
}
|
||||||
|
private void fire() {
|
||||||
|
enableButtons();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the dialog
|
||||||
|
*/
|
||||||
|
void display() {
|
||||||
|
newKeywords.clear();
|
||||||
|
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the initial contents of the text box.
|
||||||
|
* Intended to be used to redisplay any keywords that contained errors
|
||||||
|
* @param initialKeywords
|
||||||
|
*/
|
||||||
|
void setInitialKeywordList(String initialKeywords){
|
||||||
|
keywordTextArea.setText(initialKeywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void enableButtons(){
|
||||||
|
addButton.setEnabled(! keywordTextArea.getText().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of keywords from the text area
|
||||||
|
* @return list of keywords
|
||||||
|
*/
|
||||||
|
List<String> getKeywords(){
|
||||||
|
return newKeywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the regex option is selected
|
||||||
|
* @return true if the regex radio button is selected
|
||||||
|
*/
|
||||||
|
boolean isKeywordRegex(){
|
||||||
|
return regexRadioButton.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the exact match option is selected
|
||||||
|
* @return true if the exact match radio button is selected
|
||||||
|
*/
|
||||||
|
boolean isKeywordExact(){
|
||||||
|
return exactRadioButton.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
keywordTypeButtonGroup = new javax.swing.ButtonGroup();
|
||||||
|
exactRadioButton = new javax.swing.JRadioButton();
|
||||||
|
substringRadioButton = new javax.swing.JRadioButton();
|
||||||
|
regexRadioButton = new javax.swing.JRadioButton();
|
||||||
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
keywordTextArea = new javax.swing.JTextArea();
|
||||||
|
enterKeywordsLabel = new javax.swing.JLabel();
|
||||||
|
keywordTypeLabel = new javax.swing.JLabel();
|
||||||
|
addButton = new javax.swing.JButton();
|
||||||
|
cancelButton = new javax.swing.JButton();
|
||||||
|
pasteButton = new javax.swing.JButton();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
|
||||||
|
keywordTypeButtonGroup.add(exactRadioButton);
|
||||||
|
exactRadioButton.setSelected(true);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(exactRadioButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.exactRadioButton.text")); // NOI18N
|
||||||
|
|
||||||
|
keywordTypeButtonGroup.add(substringRadioButton);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(substringRadioButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.substringRadioButton.text")); // NOI18N
|
||||||
|
|
||||||
|
keywordTypeButtonGroup.add(regexRadioButton);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(regexRadioButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.regexRadioButton.text")); // NOI18N
|
||||||
|
|
||||||
|
keywordTextArea.setColumns(20);
|
||||||
|
keywordTextArea.setRows(5);
|
||||||
|
keywordTextArea.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||||
|
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||||
|
keywordTextAreaMouseClicked(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jScrollPane1.setViewportView(keywordTextArea);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(enterKeywordsLabel, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.enterKeywordsLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(keywordTypeLabel, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.keywordTypeLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.addButton.text")); // NOI18N
|
||||||
|
addButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
addButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.cancelButton.text")); // NOI18N
|
||||||
|
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cancelButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(pasteButton, org.openide.util.NbBundle.getMessage(AddKeywordsDialog.class, "AddKeywordsDialog.pasteButton.text")); // NOI18N
|
||||||
|
pasteButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
pasteButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(enterKeywordsLabel)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(pasteButton))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(addButton, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addComponent(keywordTypeLabel)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGap(10, 10, 10)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(substringRadioButton)
|
||||||
|
.addComponent(exactRadioButton)
|
||||||
|
.addComponent(regexRadioButton))))
|
||||||
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(enterKeywordsLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(keywordTypeLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(exactRadioButton)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(substringRadioButton)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(regexRadioButton)
|
||||||
|
.addGap(194, 194, 194))
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 278, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addGap(5, 5, 5)))
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(addButton)
|
||||||
|
.addComponent(cancelButton))
|
||||||
|
.addComponent(pasteButton))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void pasteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pasteButtonActionPerformed
|
||||||
|
keywordTextArea.paste();
|
||||||
|
}//GEN-LAST:event_pasteButtonActionPerformed
|
||||||
|
|
||||||
|
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
|
||||||
|
// Save the values from the list
|
||||||
|
newKeywords.addAll(Arrays.asList(keywordTextArea.getText().split("\\r?\\n")));
|
||||||
|
|
||||||
|
setVisible(false);
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_addButtonActionPerformed
|
||||||
|
|
||||||
|
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||||
|
setVisible(false);
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
|
private void keywordTextAreaMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_keywordTextAreaMouseClicked
|
||||||
|
if (SwingUtilities.isRightMouseButton(evt)) {
|
||||||
|
JPopupMenu popup = new JPopupMenu();
|
||||||
|
|
||||||
|
JMenuItem cutMenu = new JMenuItem("Cut"); // NON-NLS
|
||||||
|
cutMenu.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
keywordTextArea.cut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JMenuItem copyMenu = new JMenuItem("Copy"); // NON-NLS
|
||||||
|
copyMenu.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
keywordTextArea.copy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JMenuItem pasteMenu = new JMenuItem("Paste"); // NON-NLS
|
||||||
|
pasteMenu.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
keywordTextArea.paste();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.add(cutMenu);
|
||||||
|
popup.add(copyMenu);
|
||||||
|
popup.add(pasteMenu);
|
||||||
|
popup.show(keywordTextArea, evt.getX(), evt.getY());
|
||||||
|
}
|
||||||
|
}//GEN-LAST:event_keywordTextAreaMouseClicked
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JButton addButton;
|
||||||
|
private javax.swing.JButton cancelButton;
|
||||||
|
private javax.swing.JLabel enterKeywordsLabel;
|
||||||
|
private javax.swing.JRadioButton exactRadioButton;
|
||||||
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
|
private javax.swing.JTextArea keywordTextArea;
|
||||||
|
private javax.swing.ButtonGroup keywordTypeButtonGroup;
|
||||||
|
private javax.swing.JLabel keywordTypeLabel;
|
||||||
|
private javax.swing.JButton pasteButton;
|
||||||
|
private javax.swing.JRadioButton regexRadioButton;
|
||||||
|
private javax.swing.JRadioButton substringRadioButton;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -22,7 +22,7 @@ KeywordSearchEditListPanel.saveListButton.text=Copy List
|
|||||||
KeywordSearchEditListPanel.addWordField.text=
|
KeywordSearchEditListPanel.addWordField.text=
|
||||||
KeywordSearchEditListPanel.addWordButton.text=New keyword
|
KeywordSearchEditListPanel.addWordButton.text=New keyword
|
||||||
KeywordSearchEditListPanel.chRegex.text=Regular Expression
|
KeywordSearchEditListPanel.chRegex.text=Regular Expression
|
||||||
KeywordSearchEditListPanel.deleteWordButton.text=Delete keyword
|
KeywordSearchEditListPanel.deleteWordButton.text=Delete keywords
|
||||||
KeywordSearchEditListPanel.cutMenuItem.text=Cut
|
KeywordSearchEditListPanel.cutMenuItem.text=Cut
|
||||||
KeywordSearchEditListPanel.selectAllMenuItem.text=Select All
|
KeywordSearchEditListPanel.selectAllMenuItem.text=Select All
|
||||||
KeywordSearchEditListPanel.pasteMenuItem.text=Paste
|
KeywordSearchEditListPanel.pasteMenuItem.text=Paste
|
||||||
@ -30,6 +30,7 @@ KeywordSearchEditListPanel.copyMenuItem.text=Copy
|
|||||||
KeywordSearchEditListPanel.exportButton.text=Export List
|
KeywordSearchEditListPanel.exportButton.text=Export List
|
||||||
KeywordSearchEditListPanel.deleteListButton.text=Delete List
|
KeywordSearchEditListPanel.deleteListButton.text=Delete List
|
||||||
KeywordSearchEditListPanel.emptyKeyword.text=Empty keyword
|
KeywordSearchEditListPanel.emptyKeyword.text=Empty keyword
|
||||||
|
KeywordSearchEditListPanel.errorAddingKeywords.text=Error adding keyword(s)
|
||||||
KeywordSearchListsManagementPanel.newListButton.text=New List
|
KeywordSearchListsManagementPanel.newListButton.text=New List
|
||||||
KeywordSearchListsManagementPanel.importButton.text=Import List
|
KeywordSearchListsManagementPanel.importButton.text=Import List
|
||||||
KeywordSearchListsViewerPanel.searchAddButton.text=Search
|
KeywordSearchListsViewerPanel.searchAddButton.text=Search
|
||||||
@ -88,7 +89,7 @@ KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg=Cannot overw
|
|||||||
KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg=Keyword List <{0}> already exists, do you want to replace it?
|
KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg=Keyword List <{0}> already exists, do you want to replace it?
|
||||||
KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg=Keyword List <{0}> saved
|
KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg=Keyword List <{0}> saved
|
||||||
KeywordSearchEditListPanel.customizeComponents.kwReToolTip=Keyword is a regular expression
|
KeywordSearchEditListPanel.customizeComponents.kwReToolTip=Keyword is a regular expression
|
||||||
KeywordSearchEditListPanel.customizeComponents.addWordToolTip=Add a new word to the keyword search list
|
KeywordSearchEditListPanel.customizeComponents.addWordToolTip=Add new words to the keyword search list
|
||||||
KeywordSearchEditListPanel.customizeComponents.enterNewWordToolTip=Enter a new word or regex to search
|
KeywordSearchEditListPanel.customizeComponents.enterNewWordToolTip=Enter a new word or regex to search
|
||||||
KeywordSearchEditListPanel.customizeComponents.exportToFile=Export the current keyword list to a file
|
KeywordSearchEditListPanel.customizeComponents.exportToFile=Export the current keyword list to a file
|
||||||
KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip=Save the current keyword list with a new name
|
KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip=Save the current keyword list with a new name
|
||||||
@ -295,3 +296,20 @@ NewKeywordPanel.exactButton.text=Exact Match
|
|||||||
NewKeywordPanel.substringButton.text=Substring Match
|
NewKeywordPanel.substringButton.text=Substring Match
|
||||||
NewKeywordPanel.keywordTextField.text=
|
NewKeywordPanel.keywordTextField.text=
|
||||||
NewKeywordPanel.newKeywordLabel.text=Enter a new keyword:
|
NewKeywordPanel.newKeywordLabel.text=Enter a new keyword:
|
||||||
|
AddKeywordsDialog.exactRadioButton.text=Exact Match
|
||||||
|
AddKeywordsDialog.substringRadioButton.text=Substring Match
|
||||||
|
AddKeywordsDialog.regexRadioButton.text=Regular Expression
|
||||||
|
AddKeywordsDialog.keywordTypeLabel.text=Select type for keywords:
|
||||||
|
AddKeywordsDialog.enterKeywordsLabel.text=Enter keywords (one per line) below:
|
||||||
|
AddKeywordsDialog.pasteButton.text=Paste From Clipboard
|
||||||
|
AddKeywordsDialog.addButton.text=OK
|
||||||
|
AddKeywordsDialog.cancelButton.text=Cancel
|
||||||
|
AddKeywordsDialog.addKeywordsTitle.text=New keywords
|
||||||
|
GlobalEditListPanel.newKeywordsButton.text=New keywords
|
||||||
|
GlobalEditListPanel.addKeywordResults.text=Add keyword results
|
||||||
|
GlobalEditListPanel.keywordsAdded.text={0} keyword was successfully added.
|
||||||
|
GlobalEditListPanel.keywordsAddedPlural.text={0} keywords were successfully added.
|
||||||
|
GlobalEditListPanel.keywordDupesSkipped.text={0} keyword was already in the list.
|
||||||
|
GlobalEditListPanel.keywordDupesSkippedPlural.text={0} keywords were already in the list.
|
||||||
|
GlobalEditListPanel.keywordErrors.text={0} keyword could not be parsed. Please review and try again.
|
||||||
|
GlobalEditListPanel.keywordErrorsPlural.text={0} keywords could not be parsed. Please review and try again.
|
||||||
|
@ -168,7 +168,7 @@
|
|||||||
<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" alignment="0" attributes="0">
|
||||||
<Component id="newWordButton" min="-2" max="-2" attributes="0"/>
|
<Component id="newKeywordsButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
|
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
@ -180,8 +180,8 @@
|
|||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="newWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="newKeywordsButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="-2" pref="72" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="72" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -189,19 +189,6 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="javax.swing.JButton" name="newWordButton">
|
|
||||||
<Properties>
|
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
|
||||||
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/new16.png"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchEditListPanel.addWordButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
<Events>
|
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newWordButtonActionPerformed"/>
|
|
||||||
</Events>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JButton" name="deleteWordButton">
|
<Component class="javax.swing.JButton" name="deleteWordButton">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
@ -215,6 +202,19 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteWordButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteWordButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="newKeywordsButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||||
|
<Image iconType="3" name="/org/sleuthkit/autopsy/keywordsearch/new16.png"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="GlobalEditListPanel.newKeywordsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newKeywordsButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Component class="javax.swing.JCheckBox" name="ingestMessagesCheckbox">
|
<Component class="javax.swing.JCheckBox" name="ingestMessagesCheckbox">
|
||||||
|
@ -42,7 +42,6 @@ import org.openide.util.NbBundle;
|
|||||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GlobalEditListPanel widget to manage keywords in lists
|
* GlobalEditListPanel widget to manage keywords in lists
|
||||||
@ -64,7 +63,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
newWordButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
|
newKeywordsButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
|
||||||
exportButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile"));
|
exportButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile"));
|
||||||
saveListButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip"));
|
saveListButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip"));
|
||||||
deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
|
deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
|
||||||
@ -125,7 +124,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
// items that need an unlocked list w/out ingest running
|
// items that need an unlocked list w/out ingest running
|
||||||
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isEditable()));
|
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isEditable()));
|
||||||
boolean canAddWord = isListSelected && !isIngestRunning && !isListLocked;
|
boolean canAddWord = isListSelected && !isIngestRunning && !isListLocked;
|
||||||
newWordButton.setEnabled(canAddWord);
|
newKeywordsButton.setEnabled(canAddWord);
|
||||||
keywordOptionsLabel.setEnabled(canAddWord);
|
keywordOptionsLabel.setEnabled(canAddWord);
|
||||||
keywordOptionsSeparator.setEnabled(canAddWord);
|
keywordOptionsSeparator.setEnabled(canAddWord);
|
||||||
deleteListButton.setEnabled(canAddWord);
|
deleteListButton.setEnabled(canAddWord);
|
||||||
@ -155,8 +154,8 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
jScrollPane1 = new javax.swing.JScrollPane();
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
keywordTable = new javax.swing.JTable();
|
keywordTable = new javax.swing.JTable();
|
||||||
addKeywordPanel = new javax.swing.JPanel();
|
addKeywordPanel = new javax.swing.JPanel();
|
||||||
newWordButton = new javax.swing.JButton();
|
|
||||||
deleteWordButton = new javax.swing.JButton();
|
deleteWordButton = new javax.swing.JButton();
|
||||||
|
newKeywordsButton = new javax.swing.JButton();
|
||||||
ingestMessagesCheckbox = new javax.swing.JCheckBox();
|
ingestMessagesCheckbox = new javax.swing.JCheckBox();
|
||||||
keywordsLabel = new javax.swing.JLabel();
|
keywordsLabel = new javax.swing.JLabel();
|
||||||
keywordOptionsLabel = new javax.swing.JLabel();
|
keywordOptionsLabel = new javax.swing.JLabel();
|
||||||
@ -180,14 +179,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
keywordTable.getTableHeader().setReorderingAllowed(false);
|
keywordTable.getTableHeader().setReorderingAllowed(false);
|
||||||
jScrollPane1.setViewportView(keywordTable);
|
jScrollPane1.setViewportView(keywordTable);
|
||||||
|
|
||||||
newWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
|
|
||||||
newWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.addWordButton.text")); // NOI18N
|
|
||||||
newWordButton.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
|
||||||
newWordButtonActionPerformed(evt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
deleteWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
|
deleteWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
|
||||||
deleteWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
|
deleteWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
|
||||||
deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
|
deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
@ -196,12 +187,20 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
newKeywordsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
|
||||||
|
newKeywordsButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.newKeywordsButton.text")); // NOI18N
|
||||||
|
newKeywordsButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
newKeywordsButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
javax.swing.GroupLayout addKeywordPanelLayout = new javax.swing.GroupLayout(addKeywordPanel);
|
javax.swing.GroupLayout addKeywordPanelLayout = new javax.swing.GroupLayout(addKeywordPanel);
|
||||||
addKeywordPanel.setLayout(addKeywordPanelLayout);
|
addKeywordPanel.setLayout(addKeywordPanelLayout);
|
||||||
addKeywordPanelLayout.setHorizontalGroup(
|
addKeywordPanelLayout.setHorizontalGroup(
|
||||||
addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(addKeywordPanelLayout.createSequentialGroup()
|
.addGroup(addKeywordPanelLayout.createSequentialGroup()
|
||||||
.addComponent(newWordButton)
|
.addComponent(newKeywordsButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(deleteWordButton)
|
.addComponent(deleteWordButton)
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
@ -211,8 +210,8 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
.addGroup(addKeywordPanelLayout.createSequentialGroup()
|
.addGroup(addKeywordPanelLayout.createSequentialGroup()
|
||||||
.addGap(0, 0, 0)
|
.addGap(0, 0, 0)
|
||||||
.addGroup(addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(addKeywordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(newWordButton)
|
.addComponent(deleteWordButton)
|
||||||
.addComponent(deleteWordButton))
|
.addComponent(newKeywordsButton))
|
||||||
.addGap(72, 72, 72))
|
.addGap(72, 72, 72))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -333,51 +332,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void newWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newWordButtonActionPerformed
|
|
||||||
NewKeywordPanel panel = new NewKeywordPanel();
|
|
||||||
|
|
||||||
int result = JOptionPane.showConfirmDialog(null, panel,
|
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addKeyword.title"),
|
|
||||||
JOptionPane.OK_CANCEL_OPTION);
|
|
||||||
|
|
||||||
if (result == JOptionPane.OK_OPTION) {
|
|
||||||
String newWord = panel.getKeywordText();
|
|
||||||
if (newWord.isEmpty()) {
|
|
||||||
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.emptyKeyword.text"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Keyword keyword = new Keyword(newWord, !panel.isKeywordRegex(), panel.isKeywordExact());
|
|
||||||
if (currentKeywordList.hasKeyword(keyword)) {
|
|
||||||
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addWordButtonAction.kwAlreadyExistsMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if valid
|
|
||||||
boolean valid = true;
|
|
||||||
try {
|
|
||||||
Pattern.compile(newWord);
|
|
||||||
} catch (PatternSyntaxException ex1) {
|
|
||||||
valid = false;
|
|
||||||
} catch (IllegalArgumentException ex2) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
if (!valid) {
|
|
||||||
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.invalidKwMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add & reset checkbox
|
|
||||||
tableModel.addKeyword(keyword);
|
|
||||||
XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
|
|
||||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
|
||||||
setFocusOnKeywordTextBox();
|
|
||||||
setButtonStates();
|
|
||||||
}
|
|
||||||
}//GEN-LAST:event_newWordButtonActionPerformed
|
|
||||||
|
|
||||||
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
|
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
|
||||||
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg"), NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg"), NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
||||||
|
|
||||||
@ -450,6 +404,100 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
}//GEN-LAST:event_deleteListButtonActionPerformed
|
}//GEN-LAST:event_deleteListButtonActionPerformed
|
||||||
|
|
||||||
|
private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newKeywordsButtonActionPerformed
|
||||||
|
String keywordsToRedisplay = "";
|
||||||
|
AddKeywordsDialog dialog = new AddKeywordsDialog();
|
||||||
|
|
||||||
|
int goodCount;
|
||||||
|
int dupeCount;
|
||||||
|
int badCount = 1; // Default to 1 so we enter the loop the first time
|
||||||
|
|
||||||
|
while(badCount > 0){
|
||||||
|
dialog.setInitialKeywordList(keywordsToRedisplay);
|
||||||
|
dialog.display();
|
||||||
|
|
||||||
|
goodCount = 0;
|
||||||
|
dupeCount = 0;
|
||||||
|
badCount = 0;
|
||||||
|
keywordsToRedisplay = "";
|
||||||
|
|
||||||
|
if(!dialog.getKeywords().isEmpty()){
|
||||||
|
|
||||||
|
|
||||||
|
for(String newWord:dialog.getKeywords()){
|
||||||
|
if (newWord.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Keyword keyword = new Keyword(newWord, !dialog.isKeywordRegex(), dialog.isKeywordExact());
|
||||||
|
if (currentKeywordList.hasKeyword(keyword)) {
|
||||||
|
dupeCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if valid
|
||||||
|
boolean valid = true;
|
||||||
|
try {
|
||||||
|
Pattern.compile(newWord);
|
||||||
|
} catch (PatternSyntaxException ex1) {
|
||||||
|
valid = false;
|
||||||
|
} catch (IllegalArgumentException ex2) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
|
||||||
|
// Invalid keywords will reappear in the UI
|
||||||
|
keywordsToRedisplay += newWord + "\n";
|
||||||
|
badCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new keyword
|
||||||
|
tableModel.addKeyword(keyword);
|
||||||
|
goodCount++;
|
||||||
|
}
|
||||||
|
XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
|
||||||
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
|
|
||||||
|
if((badCount > 0) || (dupeCount > 0)){
|
||||||
|
// Display the error counts to the user
|
||||||
|
// The add keywords dialog will pop up again if any were invalid with any
|
||||||
|
// invalid entries (valid entries and dupes will disappear)
|
||||||
|
|
||||||
|
String summary = "";
|
||||||
|
KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
|
||||||
|
if(goodCount > 0){
|
||||||
|
if(goodCount > 1){
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAddedPlural.text", goodCount) + "\n";
|
||||||
|
} else {
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAdded.text", goodCount) + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dupeCount > 0){
|
||||||
|
if(dupeCount > 1){
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) + "\n";
|
||||||
|
} else {
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) + "\n";
|
||||||
|
}
|
||||||
|
level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
|
||||||
|
}
|
||||||
|
if(badCount > 0){
|
||||||
|
if(badCount > 1){
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrorsPlural.text", badCount) + "\n";
|
||||||
|
} else {
|
||||||
|
summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrors.text", badCount) + "\n";
|
||||||
|
}
|
||||||
|
level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR;
|
||||||
|
}
|
||||||
|
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "GlobalEditListPanel.addKeywordResults.text"),
|
||||||
|
summary, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFocusOnKeywordTextBox();
|
||||||
|
setButtonStates();
|
||||||
|
}//GEN-LAST:event_newKeywordsButtonActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JPanel addKeywordPanel;
|
private javax.swing.JPanel addKeywordPanel;
|
||||||
private javax.swing.JButton deleteListButton;
|
private javax.swing.JButton deleteListButton;
|
||||||
@ -464,7 +512,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
private javax.swing.JPanel listEditorPanel;
|
private javax.swing.JPanel listEditorPanel;
|
||||||
private javax.swing.JLabel listOptionsLabel;
|
private javax.swing.JLabel listOptionsLabel;
|
||||||
private javax.swing.JSeparator listOptionsSeparator;
|
private javax.swing.JSeparator listOptionsSeparator;
|
||||||
private javax.swing.JButton newWordButton;
|
private javax.swing.JButton newKeywordsButton;
|
||||||
private javax.swing.JButton saveListButton;
|
private javax.swing.JButton saveListButton;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
@ -604,6 +652,6 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
* Set the keyboard focus to new keyword textbox.
|
* Set the keyboard focus to new keyword textbox.
|
||||||
*/
|
*/
|
||||||
void setFocusOnKeywordTextBox() {
|
void setFocusOnKeywordTextBox() {
|
||||||
newWordButton.requestFocus();
|
newKeywordsButton.requestFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,6 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
QueryResponse response;
|
QueryResponse response;
|
||||||
SolrDocumentList resultList;
|
SolrDocumentList resultList;
|
||||||
Map<String, Map<String, List<String>>> highlightResponse;
|
Map<String, Map<String, List<String>>> highlightResponse;
|
||||||
Set<SolrDocument> uniqueSolrDocumentsWithHits;
|
|
||||||
|
|
||||||
response = solrServer.query(q, METHOD.POST);
|
response = solrServer.query(q, METHOD.POST);
|
||||||
|
|
||||||
@ -215,9 +214,6 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
// objectId_chunk -> "text" -> List of previews
|
// objectId_chunk -> "text" -> List of previews
|
||||||
highlightResponse = response.getHighlighting();
|
highlightResponse = response.getHighlighting();
|
||||||
|
|
||||||
// get the unique set of files with hits
|
|
||||||
// uniqueSolrDocumentsWithHits = filterOneHitPerDocument(resultList);
|
|
||||||
|
|
||||||
// cycle through results in sets of MAX_RESULTS
|
// cycle through results in sets of MAX_RESULTS
|
||||||
for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) {
|
for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) {
|
||||||
q.setStart(start);
|
q.setStart(start);
|
||||||
@ -297,52 +293,6 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the minimum set of documents. Ignores chunk IDs. Only one hit per
|
|
||||||
* file in results.
|
|
||||||
*
|
|
||||||
* @param resultList
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Set<SolrDocument> filterOneHitPerDocument(SolrDocumentList resultList) {
|
|
||||||
/**
|
|
||||||
* Filtering down to one hit per document is being performed so that we
|
|
||||||
* only create a single keyword hit blackboard artifact per file. This
|
|
||||||
* only makes sense for the case where we are performing an exact match
|
|
||||||
* query. It does not make sense for (a) the TermsComponentQuery which
|
|
||||||
* creates blackboard artifacts for the individual terms that are matched
|
|
||||||
* by the regular expression or (b) HighlightedText.loadPageInfo() which
|
|
||||||
* (i) doesn't create blackboard artifacts and (ii) needs to know about
|
|
||||||
* all hits so that it can correctly set up the paging infrastructure.
|
|
||||||
* Additionally, keyword hit artifact is being performed by
|
|
||||||
* writeSingleFileHitsToBlackboard() above which is being called by
|
|
||||||
* QueryResults.writeAllHitsToBlackboard() which appears to be taking care
|
|
||||||
* of filtering results down to a single hit per document in the
|
|
||||||
* QueryResults.getOneHitPerObject() method.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// sort the list so that we consistently pick the same chunk each time.
|
|
||||||
// note this sort is doing a string comparison and not an integer comparison, so
|
|
||||||
// chunk 10 will be smaller than chunk 9.
|
|
||||||
Collections.sort(resultList, new Comparator<SolrDocument>() {
|
|
||||||
@Override
|
|
||||||
public int compare(SolrDocument left, SolrDocument right) {
|
|
||||||
// ID is in the form of ObjectId_Chunk
|
|
||||||
String leftID = left.getFieldValue(Server.Schema.ID.toString()).toString();
|
|
||||||
String rightID = right.getFieldValue(Server.Schema.ID.toString()).toString();
|
|
||||||
return leftID.compareTo(rightID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// NOTE: We could probably just iterate through the list and compare each ID with the
|
|
||||||
// previous ID to get the unique documents faster than using this set now that the list
|
|
||||||
// is sorted.
|
|
||||||
Set<SolrDocument> solrDocumentsWithMatches = new TreeSet<>(new SolrDocumentComparatorIgnoresChunkId());
|
|
||||||
solrDocumentsWithMatches.addAll(resultList);
|
|
||||||
return solrDocumentsWithMatches;
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeywordHit createKeywordtHit(SolrDocument solrDoc, Map<String, Map<String, List<String>>> highlightResponse, SleuthkitCase caseDb) throws TskException {
|
private KeywordHit createKeywordtHit(SolrDocument solrDoc, Map<String, Map<String, List<String>>> highlightResponse, SleuthkitCase caseDb) throws TskException {
|
||||||
/**
|
/**
|
||||||
* Get the first snippet from the document if keyword search is
|
* Get the first snippet from the document if keyword search is
|
||||||
|
Loading…
x
Reference in New Issue
Block a user