1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-06 02:24:30 +00:00

Merge branch 'master' of https://github.com/sleuthkit/autopsy into language_filters

This commit is contained in:
jmillman
2013-09-13 10:07:17 -04:00
29 changed files with 908 additions and 843 deletions

View File

@@ -144,6 +144,8 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer
}
addRow(sb, "MD5", md5);
addRow(sb, "Internal ID", new Long(file.getId()).toString());
endTable(sb);
setText(sb.toString());
}

View File

@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,8 +32,6 @@ import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.datamodel.DataConversion;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.TskException;
/**
@@ -41,11 +39,10 @@ import org.sleuthkit.datamodel.TskException;
*/
@ServiceProvider(service = DataContentViewer.class, position = 1)
public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer {
private static long currentOffset = 0;
private static final long pageLength = 16384;
private final byte[] data = new byte[(int) pageLength];
private static int currentPage = 1;
private int totalPages;
private Content dataSource;
private static final Logger logger = Logger.getLogger(DataContentViewerHex.class.getName());
@@ -243,39 +240,28 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
}// </editor-fold>//GEN-END:initComponents
private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed
//@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar
currentOffset -= pageLength;
currentPage = currentPage - 1;
currentPageLabel.setText(Integer.toString(currentPage));
setDataView(dataSource, currentOffset);
setDataView(currentPage - 1);
}//GEN-LAST:event_prevPageButtonActionPerformed
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
//@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar
currentOffset += pageLength;
currentPage = currentPage + 1;
currentPageLabel.setText(Integer.toString(currentPage));
setDataView(dataSource, currentOffset);
setDataView(currentPage + 1);
}//GEN-LAST:event_nextPageButtonActionPerformed
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
String pageNumberStr = goToPageTextField.getText();
int pageNumber = 0;
int maxPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
try {
pageNumber = Integer.parseInt(pageNumberStr);
} catch (NumberFormatException ex) {
pageNumber = maxPage + 1;
pageNumber = totalPages + 1;
}
if (pageNumber > maxPage || pageNumber < 1) {
JOptionPane.showMessageDialog(this, "Please enter a valid page number between 1 and " + maxPage,
if (pageNumber > totalPages || pageNumber < 1) {
JOptionPane.showMessageDialog(this, "Please enter a valid page number between 1 and " + totalPages,
"Invalid page number", JOptionPane.WARNING_MESSAGE);
return;
}
currentOffset = (pageNumber - 1) * pageLength;
currentPage = pageNumber;
currentPageLabel.setText(Integer.toString(currentPage));
setDataView(dataSource, currentOffset);
setDataView(pageNumber);
}//GEN-LAST:event_goToPageTextFieldActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
@@ -296,30 +282,27 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
// End of variables declaration//GEN-END:variables
@Deprecated
public void setDataView(Content dataSource, long offset, boolean reset) {
if (reset) {
resetComponent();
return;
}
setDataView(dataSource, offset);
}
/**
* Sets the DataView (The tabbed panel)
*
* @param dataSource the content that want to be shown
* @param offset the starting offset
* @param page Page to display (1-based counting)
*/
private void setDataView(Content dataSource, long offset) {
if (dataSource == null) {
private void setDataView(int page) {
if (this.dataSource == null) {
return;
}
if (page == 0) {
return;
}
currentPage = page;
long offset = (currentPage - 1) * pageLength;
// change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
this.dataSource = dataSource;
String errorText = null;
int bytesRead = 0;
@@ -327,7 +310,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
try {
bytesRead = dataSource.read(data, offset, pageLength); // read the data
} catch (TskException ex) {
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
errorText = "(offset " + offset + "-" + (offset + pageLength)
+ " could not be read)";
logger.log(Level.WARNING, "Error while trying to show the hex content.", ex);
}
@@ -335,27 +318,26 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
// set the data on the bottom and show it
if (bytesRead <= 0) {
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
errorText = "(offset " + offset + "-" + (offset + pageLength)
+ " could not be read)";
}
// disable or enable the next button
if ((errorText != null) && (offset + pageLength < dataSource.getSize())) {
if ((errorText == null) && (currentPage < totalPages)) {
nextPageButton.setEnabled(true);
} else {
}
else {
nextPageButton.setEnabled(false);
}
if ((offset == 0) || (errorText == null)) {
prevPageButton.setEnabled(false);
currentPage = 1; // reset the page number
} else {
if ((errorText == null) && (currentPage > 1)) {
prevPageButton.setEnabled(true);
}
else {
prevPageButton.setEnabled(false);
}
int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
totalPageLabel.setText(Integer.toString(totalPage));
currentPageLabel.setText(Integer.toString(currentPage));
setComponentsVisibility(true); // shows the components that not needed
@@ -384,8 +366,15 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
resetComponent();
return;
}
dataSource = content;
totalPages = 0;
if (dataSource.getSize() > 0) {
totalPages = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
}
totalPageLabel.setText(Integer.toString(totalPages));
this.setDataView(content, 0);
this.setDataView(1);
}
@Override
@@ -408,7 +397,6 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
public void resetComponent() {
// clear / reset the fields
currentPage = 1;
currentOffset = 0;
this.dataSource = null;
currentPageLabel.setText("");
totalPageLabel.setText("");

View File

@@ -25,9 +25,7 @@ import java.util.Arrays;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingUtilities;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
@@ -41,16 +39,15 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
@ServiceProvider(service = DataContentViewer.class, position = 5)
})
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
private String[] IMAGES; // use javafx supported
private static final String[] VIDEOS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"};
private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"};
private static final String[] AUDIO_EXTENSIONS = new String[]{".mp3", ".wav", ".wma"};
private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName());
private AbstractFile lastFile;
//UI
private final MediaViewVideoPanel videoPanel;
private final String[] videoExtensions; // get them from the panel
private String[] imageExtensions; // use javafx supported
private final MediaViewImagePanel imagePanel;
private boolean videoPanelInited;
private boolean imagePanelInited;
@@ -72,6 +69,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
videoPanelInited = videoPanel.isInited();
imagePanelInited = imagePanel.isInited();
videoExtensions = videoPanel.getExtensions();
customizeComponents();
logger.log(Level.INFO, "Created MediaView instance: " + this);
}
@@ -80,12 +79,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
//initialize supported image types
//TODO use mime-types instead once we have support
String[] fxSupportedImagesSuffixes = ImageIO.getReaderFileSuffixes();
IMAGES = new String[fxSupportedImagesSuffixes.length];
imageExtensions = new String[fxSupportedImagesSuffixes.length];
//logger.log(Level.INFO, "Supported image formats by javafx image viewer: ");
for (int i = 0; i < fxSupportedImagesSuffixes.length; ++i) {
String suffix = fxSupportedImagesSuffixes[i];
//logger.log(Level.INFO, "suffix: " + suffix);
IMAGES[i] = "." + suffix;
imageExtensions[i] = "." + suffix;
}
add(imagePanel, IMAGE_VIEWER_LAYER);
@@ -132,11 +131,11 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
final Dimension dims = DataContentViewerMedia.this.getSize();
if (imagePanelInited && containsExt(file.getName(), IMAGES)) {
if (imagePanelInited && containsExt(file.getName(), imageExtensions)) {
imagePanel.showImageFx(file, dims);
this.switchPanels(false);
} else if (videoPanelInited
&& (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) {
&& (containsExt(file.getName(), videoExtensions) || containsExt(file.getName(), AUDIO_EXTENSIONS))) {
videoPanel.setupVideo(file, dims);
switchPanels(true);
}
@@ -203,13 +202,13 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
}
String name = file.getName().toLowerCase();
if (imagePanelInited && containsExt(name, IMAGES)) {
if (imagePanelInited && containsExt(name, imageExtensions)) {
return true;
} //for gstreamer formats, check if initialized first, then
//support audio formats, and video formats
else if (videoPanelInited && videoPanel.isInited()
&& (containsExt(name, AUDIOS)
|| (containsExt(name, VIDEOS)))) {
&& (containsExt(name, AUDIO_EXTENSIONS)
|| (containsExt(name, videoExtensions)))) {
return true;
}
@@ -227,7 +226,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
String name = file.getName().toLowerCase();
boolean deleted = file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC);
if (containsExt(name, VIDEOS) && deleted) {
if (containsExt(name, videoExtensions) && deleted) {
return 0;
} else {
return 7;

View File

@@ -188,7 +188,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
// as DataResultViewer service providers when DataResultViewers are updated
// to better handle the ExplorerManager sharing implemented to support actions that operate on
// multiple selected nodes.
addDataResultViewer(new DataResultViewerTable(this.explorerManager));
addDataResultViewer(new DataResultViewerTable(this.explorerManager));
addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager));
// Find all DataResultViewer service providers and add them to the tabbed pane.

View File

@@ -78,7 +78,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
ov.setAllowedDragActions(DnDConstants.ACTION_NONE);
ov.setAllowedDropActions(DnDConstants.ACTION_NONE);
// only allow one item to be selected at a time
ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// don't show the root node

View File

@@ -85,7 +85,6 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private void initialize() {
initComponents();
// only allow one item to be selected at a time
((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
curPage = -1;

View File

@@ -76,6 +76,7 @@ import org.sleuthkit.datamodel.TskData;
})
public class FXVideoPanel extends MediaViewVideoPanel {
private static final String[] EXTENSIONS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"};
private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName());
private boolean fxInited = false;
// FX Components
@@ -639,4 +640,9 @@ public class FXVideoPanel extends MediaViewVideoPanel {
// return frames;
// }
// }
@Override
public String[] getExtensions() {
return EXTENSIONS;
}
}

View File

@@ -67,6 +67,8 @@ import org.sleuthkit.datamodel.TskData;
})
public class GstVideoPanel extends MediaViewVideoPanel {
private static final String[] EXTENSIONS = new String[]{".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"};
private static final Logger logger = Logger.getLogger(GstVideoPanel.class.getName());
private boolean gstInited;
private static final long MIN_FRAME_INTERVAL_MILLIS = 500;
@@ -767,4 +769,9 @@ public class GstVideoPanel extends MediaViewVideoPanel {
});
}
}
@Override
public String[] getExtensions() {
return EXTENSIONS;
}
}

View File

@@ -115,4 +115,9 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture
* @param dims dimension of the parent window
*/
abstract void setupVideo(final AbstractFile file, final Dimension dims);
/**
* Return the extensions supported by this video panel.
*/
abstract public String[] getExtensions();
}

View File

@@ -122,8 +122,8 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
}
@Override
public AbstractNode visit(SearchFilters sf) {
return new SearchFiltersNode(sf.getSleuthkitCase(), null);
public AbstractNode visit(FileTypeExtensionFilters sf) {
return new FileTypesNode(sf.getSleuthkitCase(), null);
}
@Override

View File

@@ -26,13 +26,13 @@ public interface AutopsyItemVisitor<T> {
T visit(ExtractedContent ec);
T visit(SearchFilters sf);
T visit(FileTypeExtensionFilters sf);
T visit(SearchFilters.FileSearchFilter fsf);
T visit(FileTypeExtensionFilters.RootFilter fsf);
T visit(SearchFilters.DocumentFilter df);
T visit(FileTypeExtensionFilters.DocumentFilter df);
T visit(SearchFilters.ExecutableFilter ef);
T visit(FileTypeExtensionFilters.ExecutableFilter ef);
T visit(RecentFiles rf);
@@ -70,22 +70,22 @@ public interface AutopsyItemVisitor<T> {
}
@Override
public T visit(SearchFilters sf) {
public T visit(FileTypeExtensionFilters sf) {
return defaultVisit(sf);
}
@Override
public T visit(SearchFilters.FileSearchFilter fsf) {
public T visit(FileTypeExtensionFilters.RootFilter fsf) {
return defaultVisit(fsf);
}
@Override
public T visit(SearchFilters.DocumentFilter df) {
public T visit(FileTypeExtensionFilters.DocumentFilter df) {
return defaultVisit(df);
}
@Override
public T visit(SearchFilters.ExecutableFilter ef) {
public T visit(FileTypeExtensionFilters.ExecutableFilter ef) {
return defaultVisit(ef);
}

View File

@@ -53,7 +53,7 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(ExtractedContentNode ecn);
T visit(FileSearchFilterNode fsfn);
T visit(FileTypeNode fsfn);
T visit(DeletedContentNode dcn);
@@ -63,7 +63,7 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(FileSizeNode fsn);
T visit(SearchFiltersNode sfn);
T visit(FileTypesNode sfn);
T visit(RecentFilesNode rfn);
@@ -155,7 +155,7 @@ public interface DisplayableItemNodeVisitor<T> {
}
@Override
public T visit(FileSearchFilterNode fsfn) {
public T visit(FileTypeNode fsfn) {
return defaultVisit(fsfn);
}
@@ -180,7 +180,7 @@ public interface DisplayableItemNodeVisitor<T> {
}
@Override
public T visit(SearchFiltersNode sfn) {
public T visit(FileTypesNode sfn) {
return defaultVisit(sfn);
}

View File

@@ -38,16 +38,16 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/**
* Children factory for the file by type view in dir tree
* Children factory for a specific file type - does the database query.
*/
class FileSearchFilterChildren extends ChildFactory<Content> {
class FileTypeChildren extends ChildFactory<Content> {
private SleuthkitCase skCase;
private SearchFilters.SearchFilterInterface filter;
private static final Logger logger = Logger.getLogger(FileSearchFilterChildren.class.getName());
private FileTypeExtensionFilters.SearchFilterInterface filter;
private static final Logger logger = Logger.getLogger(FileTypeChildren.class.getName());
//private final static int MAX_OBJECTS = 2000;
public FileSearchFilterChildren(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
public FileTypeChildren(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
this.filter = filter;
this.skCase = skCase;
}
@@ -61,7 +61,7 @@ class FileSearchFilterChildren extends ChildFactory<Content> {
private String createQuery(){
String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
+ " AND (known IS NULL OR known != 1) AND (0";
+ " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN + ") AND (0";
for(String s : filter.getFilter()){
query += " OR name LIKE '%" + s + "'";
}
@@ -72,7 +72,7 @@ class FileSearchFilterChildren extends ChildFactory<Content> {
private List<AbstractFile> runQuery(){
List<AbstractFile> list = new ArrayList<AbstractFile>();
List<AbstractFile> list = new ArrayList<>();
try {
List<AbstractFile> res = skCase.findAllFilesWhere(createQuery());
for(AbstractFile c : res){

View File

@@ -25,11 +25,12 @@ import org.sleuthkit.datamodel.SleuthkitCase;
/**
* Filters database results by file extension.
*/
public class SearchFilters implements AutopsyVisitableItem {
public class FileTypeExtensionFilters implements AutopsyVisitableItem {
private SleuthkitCase skCase;
public enum FileSearchFilter implements AutopsyVisitableItem,SearchFilterInterface {
// root node filters
public enum RootFilter implements AutopsyVisitableItem,SearchFilterInterface {
TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", "Images", FileTypeExtensions.getImageExtensions()),
TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", "Videos", FileTypeExtensions.getVideoExtensions()),
TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", "Audio", FileTypeExtensions.getAudioExtensions()),
@@ -42,7 +43,7 @@ public class SearchFilters implements AutopsyVisitableItem {
private String displayName;
private List<String> filter;
private FileSearchFilter(int id, String name, String displayName, List<String> filter){
private RootFilter(int id, String name, String displayName, List<String> filter){
this.id = id;
this.name = name;
this.displayName = displayName;
@@ -75,6 +76,7 @@ public class SearchFilters implements AutopsyVisitableItem {
}
}
// document sub-node filters
public enum DocumentFilter implements AutopsyVisitableItem,SearchFilterInterface {
AUT_DOC_HTML(0, "AUT_DOC_HTML", "HTML", Arrays.asList(".htm", ".html")),
AUT_DOC_OFFICE(1, "AUT_DOC_OFFICE", "Office", Arrays.asList(".doc", ".docx",
@@ -122,6 +124,7 @@ public class SearchFilters implements AutopsyVisitableItem {
}
// executable sub-node filters
public enum ExecutableFilter implements AutopsyVisitableItem,SearchFilterInterface {
ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")),
ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")),
@@ -167,7 +170,7 @@ public class SearchFilters implements AutopsyVisitableItem {
}
}
public SearchFilters(SleuthkitCase skCase){
public FileTypeExtensionFilters(SleuthkitCase skCase){
this.skCase = skCase;
}

View File

@@ -1,3 +1,21 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2013 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.Arrays;

View File

@@ -24,15 +24,15 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
* Node for the file search filter
* Node for a specific file type / extension
*/
public class FileSearchFilterNode extends DisplayableItemNode {
public class FileTypeNode extends DisplayableItemNode {
SearchFilters.SearchFilterInterface filter;
FileTypeExtensionFilters.SearchFilterInterface filter;
SleuthkitCase skCase;
FileSearchFilterNode(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
super(Children.create(new FileSearchFilterChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName()));
FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) {
super(Children.create(new FileTypeChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName()));
this.filter = filter;
this.skCase = skCase;
@@ -40,7 +40,7 @@ public class FileSearchFilterNode extends DisplayableItemNode {
super.setName(filter.getName());
//get count of children without preloading all children nodes
final long count = new FileSearchFilterChildren(filter, skCase).calculateItems();
final long count = new FileTypeChildren(filter, skCase).calculateItems();
//final long count = getChildren().getNodesCount(true);
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");

View File

@@ -0,0 +1,75 @@
/*
* 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.util.Arrays;
import java.util.List;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.FileTypeExtensionFilters.RootFilter;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
*/
class FileTypesChildren extends ChildFactory<FileTypeExtensionFilters.SearchFilterInterface> {
private SleuthkitCase skCase;
private FileTypeExtensionFilters.RootFilter filter;
/**
*
* @param skCase
* @param filter Is null for root node
*/
public FileTypesChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) {
this.skCase = skCase;
this.filter = filter;
}
@Override
protected boolean createKeys(List<FileTypeExtensionFilters.SearchFilterInterface> list) {
// root node
if (filter == null) {
list.addAll(Arrays.asList(RootFilter.values()));
}
// document and executable has another level of nodes
else if (filter.equals(RootFilter.TSK_DOCUMENT_FILTER) ){
list.addAll(Arrays.asList(FileTypeExtensionFilters.DocumentFilter.values()));
}
else if (filter.equals(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 FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER);
}
else if(key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER.getName())){
return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER);
}
else {
return new FileTypeNode(key, skCase);
}
}
}

View File

@@ -24,19 +24,27 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
* Node for search filter
* Node for extension/file type filter view
*/
public class SearchFiltersNode extends DisplayableItemNode {
public class FileTypesNode extends DisplayableItemNode {
private static final String FNAME = "File Types";
private SleuthkitCase skCase;
SearchFiltersNode(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) {
super(Children.create(new SearchFiltersChildren(skCase, filter), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
/**
*
* @param skCase
* @param filter null to display root node of file type tree, pass in something to provide a sub-node.
*/
FileTypesNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) {
super(Children.create(new FileTypesChildren(skCase, filter), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
// root node of tree
if (filter == null) {
super.setName(FNAME);
super.setDisplayName(FNAME);
} else {
}
// sub-node in file tree (i.e. documents, exec, etc.)
else {
super.setName(filter.getName());
super.setDisplayName(filter.getDisplayName());
}

View File

@@ -1,68 +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;
import java.util.Arrays;
import java.util.List;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.SearchFilters.FileSearchFilter;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
*/
class SearchFiltersChildren extends ChildFactory<SearchFilters.SearchFilterInterface> {
private SleuthkitCase skCase;
private SearchFilters.FileSearchFilter filter;
public SearchFiltersChildren(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) {
this.skCase = skCase;
this.filter = filter;
}
@Override
protected boolean createKeys(List<SearchFilters.SearchFilterInterface> list) {
if (filter == null) {
list.addAll(Arrays.asList(FileSearchFilter.values()));
}
else if (filter.equals(FileSearchFilter.TSK_DOCUMENT_FILTER) ){
list.addAll(Arrays.asList(SearchFilters.DocumentFilter.values()));
}
else if (filter.equals(FileSearchFilter.TSK_EXECUTABLE_FILTER) ){
list.addAll(Arrays.asList(SearchFilters.ExecutableFilter.values()));
}
return true;
}
@Override
protected Node createNodeForKey(SearchFilters.SearchFilterInterface key){
if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER.getName())){
return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER);
}
else if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER.getName())){
return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER);
}
else {
return new FileSearchFilterNode(key, skCase);
}
}
}

View File

@@ -34,7 +34,7 @@ public class ViewsNode extends DisplayableItemNode {
public ViewsNode(SleuthkitCase sleuthkitCase) {
super(new RootContentChildren(Arrays.asList(
new SearchFilters(sleuthkitCase),
new FileTypeExtensionFilters(sleuthkitCase),
new RecentFiles(sleuthkitCase),
new DeletedContent(sleuthkitCase),
new FileSize(sleuthkitCase)

View File

@@ -219,10 +219,16 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
// change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// update the back and forward List
// the end is the current place,
String[] currentNodePath = backList.pollLast();
String[] newCurrentNodePath = backList.peekLast();
forwardList.addLast(currentNodePath);
forwardButton.setEnabled(true);
/* We peek instead of poll because we use its existence
* in the list later on so that we do not reset the forward list
* after the selection occurs. */
String[] newCurrentNodePath = backList.peekLast();
// enable / disable the back and forward button
if (backList.size() > 1) {
@@ -230,39 +236,31 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} else {
backButton.setEnabled(false);
}
this.forwardButton.setEnabled(true);
// update the selection on directory tree
setSelectedNode(newCurrentNodePath, null);
this.setCursor(null);
}//GEN-LAST:event_backButtonActionPerformed
private void forwardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_forwardButtonActionPerformed
// change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// try {
// update the back and forward List
//int newCurrentIndex = forwardList.size() - 1;
String[] newCurrentNodePath = forwardList.pollLast();
//forwardList.remove(newCurrentIndex);
backList.addLast(newCurrentNodePath);
// enable / disable the back and forward button
String[] newCurrentNodePath = forwardList.pollLast();
if (!forwardList.isEmpty()) {
forwardButton.setEnabled(true);
} else {
forwardButton.setEnabled(false);
}
this.backButton.setEnabled(true);
backList.addLast(newCurrentNodePath);
backButton.setEnabled(true);
// update the selection on directory tree
setSelectedNode(newCurrentNodePath, null);
this.setCursor(null);
}//GEN-LAST:event_forwardButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton backButton;
@@ -337,7 +335,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
} else {
// if there's at least one image, load the image and open the top component
List<Object> items = new ArrayList<Object>();
List<Object> items = new ArrayList<>();
final SleuthkitCase tskCase = currentCase.getSleuthkitCase();
items.add(new DataSources(tskCase));
items.add(new Views(tskCase));
@@ -375,7 +373,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
// Reset the forward and back lists because we're resetting the root context
resetHistoryListAndButtons();
resetHistory();
Children childNodes = em.getRootContext().getChildren();
TreeView tree = getTree();
@@ -533,7 +531,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// case opened
if (newValue != null) {
resetHistoryListAndButtons();
resetHistory();
}
} // if the image is added to the case
else if (changed.equals(Case.CASE_ADD_DATA_SOURCE)) {
@@ -671,31 +669,53 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
});
// update the back and forward list
Node[] selectedNode = em.getSelectedNodes();
if (selectedNode.length > 0) {
Node selectedContext = selectedNode[0];
final String[] selectedPath = NodeOp.createPath(selectedContext, em.getRootContext());
String[] currentLast = backList.peekLast();
String lastNodeName = null;
if (currentLast != null) {
lastNodeName = currentLast[currentLast.length - 1];
}
String selectedNodeName = selectedContext.getName();
if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
//add to the list if the last if not the same as current
backList.addLast(selectedPath); // add the node to the "backList"
if (backList.size() > 1) {
backButton.setEnabled(true);
} else {
backButton.setEnabled(false);
}
forwardList.clear(); // clear the "forwardList"
forwardButton.setEnabled(false); // disable the forward Button
}
updateHistory(em.getSelectedNodes());
}
private void updateHistory(Node[] selectedNodes) {
if (selectedNodes.length == 0) {
return;
}
Node selectedNode = selectedNodes[0];
String selectedNodeName = selectedNode.getName();
/* get the previous entry to make sure we don't duplicate it.
* Motivation for this is also that if we used the back button,
* then we already added the 'current' node to 'back' and we will
* detect that and not reset the forward list.
*/
String[] currentLast = backList.peekLast();
String lastNodeName = null;
if (currentLast != null) {
lastNodeName = currentLast[currentLast.length - 1];
}
if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
//add to the list if the last if not the same as current
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
backList.addLast(selectedPath); // add the node to the "backList"
if (backList.size() > 1) {
backButton.setEnabled(true);
} else {
backButton.setEnabled(false);
}
forwardList.clear(); // clear the "forwardList"
forwardButton.setEnabled(false); // disable the forward Button
}
}
/**
* Resets the back and forward list, and also disable the back and forward
* buttons.
*/
private void resetHistory() {
// clear the back and forward list
backList.clear();
forwardList.clear();
backButton.setEnabled(false);
forwardButton.setEnabled(false);
}
@Override
@@ -708,17 +728,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
pcs.removePropertyChangeListener(listener);
}
/**
* Resets the back and forward list, and also disable the back and forward
* buttons.
*/
private void resetHistoryListAndButtons() {
// clear the back and forward list
backList.clear();
forwardList.clear();
backButton.setEnabled(false);
forwardButton.setEnabled(false);
}
/**
* Gets the tree on this DirectoryTreeTopComponent.
@@ -845,19 +855,17 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
if (path.length > 0 && (rootNodeName == null || path[0].equals(rootNodeName))) {
try {
final TreeView tree = getTree();
Node newSelection = NodeOp.findPath(em.getRootContext(), path);
//resetHistoryListAndButtons();
if (newSelection != null) {
if (rootNodeName != null) {
//called from tree auto refresh context
//remove last from backlist, because auto select will result in duplication
backList.pollLast();
}
//select
//tree.expandNode(newSelection);
em.setExploredContextAndSelection(newSelection, new Node[]{newSelection});
}
// We need to set the selection, which will refresh dataresult and get rid of the oob exception
} catch (NodeNotFoundException ex) {
logger.log(Level.WARNING, "Node not found", ex);

View File

@@ -475,6 +475,9 @@ public final class IngestModuleLoader {
for (final ModuleInfo moduleInfo : moduleInfos) {
if (moduleInfo.isEnabled()) {
/* NOTE: We have an assumption here that the modules in an NBM will
* have the same package name as the NBM name. This means that
* an NBM can have only one package with modules in it. */
String basePackageName = moduleInfo.getCodeNameBase();
// skip the standard ones

View File

@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,9 +21,6 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.logging.Level;
import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation;
@@ -35,7 +32,6 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentatio
abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface {
protected int filesIndexed;
private static final Logger logger = Logger.getLogger(AbstractKeywordSearchPerformer.class.getName());
AbstractKeywordSearchPerformer() {
initListeners();
@@ -47,7 +43,6 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
@Override
public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName();
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if (changed.equals(KeywordSearch.NUM_FILES_CHANGE_EVT)) {
@@ -114,7 +109,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
KeywordSearchUtil.displayDialog("Keyword Search Error", "Keyword list is empty, please add at least one keyword to the list", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return;
}
man = new KeywordSearchQueryManager(keywords, Presentation.COLLAPSE);
man = new KeywordSearchQueryManager(keywords, Presentation.FLAT);
}
else {
QueryType queryType = null;
@@ -128,7 +123,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
KeywordSearchUtil.displayDialog("Keyword Search Error", "Please enter a keyword to search for", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return;
}
man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.COLLAPSE);
man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT);
}
if (man.validate()) {

View File

@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,7 +28,6 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.windows.TopComponent;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.datamodel.KeyValue;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
@@ -41,7 +40,9 @@ public class KeywordSearchQueryManager {
// how to display the results
public enum Presentation {
COLLAPSE, DETAIL
FLAT, // all results are in a single level (even if multiple keywords and reg-exps are used). We made this because we were having problems with multiple-levels of nodes and the thumbnail and table view sharing an ExplorerManager. IconView seemed to change EM so that it did not allow lower levels to be selected.
COLLAPSE, // two levels. Keywords on top, files on bottom.
DETAIL // not currently used, but seems like it has three levels of nodes
};
private List<Keyword> keywords;
@@ -70,7 +71,7 @@ public class KeywordSearchQueryManager {
* @param presentation Presentation Layout
*/
public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) {
keywords = new ArrayList<Keyword>();
keywords = new ArrayList<>();
keywords.add(new Keyword(query, qt == QueryType.REGEX ? false : true));
this.presentation = presentation;
queryType = qt;
@@ -84,7 +85,7 @@ public class KeywordSearchQueryManager {
* @param presentation Presentation layout
*/
public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) {
keywords = new ArrayList<Keyword>();
keywords = new ArrayList<>();
keywords.add(new Keyword(query, isLiteral));
this.presentation = presentation;
queryType = isLiteral ? QueryType.WORD : QueryType.REGEX;
@@ -96,7 +97,7 @@ public class KeywordSearchQueryManager {
* Create a list of queries to later run
*/
private void init() {
queryDelegates = new ArrayList<KeywordSearchQuery>();
queryDelegates = new ArrayList<>();
for (Keyword keyword : keywords) {
KeywordSearchQuery query = null;
switch (queryType) {
@@ -137,18 +138,17 @@ public class KeywordSearchQueryManager {
// } else {
//Collapsed view
Collection<KeyValueQuery> things = new ArrayList<KeyValueQuery>();
Collection<KeyValueQuery> things = new ArrayList<>();
int queryID = 0;
StringBuilder queryConcat = new StringBuilder(); // concatenation of all query strings
for (KeywordSearchQuery q : queryDelegates) {
Map<String, Object> kvs = new LinkedHashMap<String, Object>();
Map<String, Object> kvs = new LinkedHashMap<>();
final String queryStr = q.getQueryString();
queryConcat.append(queryStr).append(" ");
things.add(new KeyValueQuery(queryStr, kvs, ++queryID, q));
}
Node rootNode = null;
Node rootNode;
String queryConcatStr = queryConcat.toString();
final int queryConcatStrLen = queryConcatStr.length();
final String queryStrShort = queryConcatStrLen > 15 ? queryConcatStr.substring(0, 14) + "..." : queryConcatStr;
@@ -156,7 +156,7 @@ public class KeywordSearchQueryManager {
DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle);
if (things.size() > 0) {
Children childThingNodes =
Children.create(new KeywordSearchResultFactory(keywords, things, Presentation.COLLAPSE, searchResultWin), true);
Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin), true);
rootNode = new AbstractNode(childThingNodes);
} else {
@@ -179,7 +179,7 @@ public class KeywordSearchQueryManager {
boolean allValid = true;
for (KeywordSearchQuery tcq : queryDelegates) {
if (!tcq.validate()) {
logger.log(Level.WARNING, "Query has invalid syntax: " + tcq.getQueryString());
logger.log(Level.WARNING, "Query has invalid syntax: {0}", tcq.getQueryString());
allValid = false;
break;
}

View File

@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,7 +36,6 @@ import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Cancellable;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
@@ -109,7 +108,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
KeywordSearchResultFactory(Keyword query, Collection<KeyValueQuery> things, Presentation presentation, DataResultTopComponent viewer) {
queries = new ArrayList<Keyword>();
queries = new ArrayList<>();
queries.add(query);
this.presentation = presentation;
this.things = things;
@@ -134,7 +133,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
for (int i = 0; i < FS_PROPS_LEN; ++i) {
toSet.put(fsTypes[i].toString(), "");
}
}
public static void setCommonProperty(Map<String, Object> toSet, CommonPropertyTypes type, String value) {
@@ -150,10 +148,21 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
@Override
protected boolean createKeys(List<KeyValueQuery> toPopulate) {
int id = 0;
if (presentation == Presentation.DETAIL) {
if (presentation == Presentation.FLAT) {
for (KeyValueQuery thing : things) {
Map<String, Object> map = thing.getMap();
initCommonProperties(map);
final String query = thing.getName();
setCommonProperty(map, CommonPropertyTypes.KEYWORD, query);
setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped()));
ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing);
childFactory.createKeysForFlatNodes(toPopulate);
}
}
else if (presentation == Presentation.DETAIL) {
Iterator<KeyValueQuery> it = things.iterator();
for (Keyword keyword : queries) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Map<String, Object> map = new LinkedHashMap<>();
final String query = keyword.getQuery();
initCommonProperties(map);
setCommonProperty(map, CommonPropertyTypes.KEYWORD, query);
@@ -166,25 +175,26 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
} else {
for (KeyValueQuery thing : things) {
//Map<String, Object> map = new LinkedHashMap<String, Object>();
Map<String, Object> map = thing.getMap();
initCommonProperties(map);
final String query = thing.getName();
setCommonProperty(map, CommonPropertyTypes.KEYWORD, query);
setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped()));
//toPopulate.add(new KeyValue(query, map, ++id));
toPopulate.add(thing);
}
}
return true;
}
@Override
protected Node createNodeForKey(KeyValueQuery thing) {
ChildFactory<KeyValueQuery> childFactory = null;
if (presentation == Presentation.COLLAPSE) {
ChildFactory<KeyValueQuery> childFactory;
if (presentation == Presentation.FLAT) {
ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing);
return factory.createFlatNodeForKey(thing);
}
else if (presentation == Presentation.COLLAPSE) {
childFactory = new ResultCollapsedChildFactory(thing);
final Node ret = new KeyValueNode(thing, Children.create(childFactory, true));
SwingUtilities.invokeLater(new Runnable() {
@@ -199,7 +209,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
});
return ret;
} else {
childFactory = new ResulTermsMatchesChildFactory(things);
return new KeyValueNode(thing, Children.create(childFactory, true));
}
@@ -218,9 +227,13 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
this.queryThing = queryThing;
}
// @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient.
public boolean createKeysForFlatNodes(List<KeyValueQuery> toPopulate) {
return createKeys(toPopulate);
}
@Override
protected boolean createKeys(List<KeyValueQuery> toPopulate) {
//final String origQuery = queryThing.getName();
final KeyValueQuery queryThingQuery = queryThing;
final KeywordSearchQuery tcq = queryThingQuery.getQuery();
@@ -252,7 +265,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
for (final AbstractFile f : hitContents.keySet()) {
final int previewChunk = hitContents.get(f);
//get unique match result files
Map<String, Object> resMap = new LinkedHashMap<String, Object>();
Map<String, Object> resMap = new LinkedHashMap<>();
setCommonProperty(resMap, CommonPropertyTypes.MATCH, f.getName());
try {
@@ -306,12 +319,11 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
//whereas in bb we write every hit per file separately
new ResultWriter(tcqRes, tcq, listName).execute();
return true;
}
private String getHighlightQuery(KeywordSearchQuery tcq, boolean literal_query, Map<String, List<ContentHit>> tcqRes, AbstractFile f) {
String highlightQueryEscaped = null;
String highlightQueryEscaped;
if (literal_query) {
//literal, treat as non-regex, non-term component query
highlightQueryEscaped = tcq.getQueryString();
@@ -326,7 +338,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
highlightQuery.append(term);
} else {
//find terms for this file hit
List<String> hitTerms = new ArrayList<String>();
List<String> hitTerms = new ArrayList<>();
for (String term : tcqRes.keySet()) {
List<ContentHit> hitList = tcqRes.get(term);
@@ -363,10 +375,13 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
return highlightQueryEscaped;
}
// @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient.
public Node createFlatNodeForKey(KeyValueQuery thing) {
return createNodeForKey(thing);
}
@Override
protected Node createNodeForKey(KeyValueQuery thing) {
//return new KeyValueNode(thing, Children.LEAF);
//return new KeyValueNode(thing, Children.create(new ResultFilesChildFactory(thing), true));
final KeyValueQueryContent thingContent = (KeyValueQueryContent) thing;
final Content content = thingContent.getContent();
final String queryStr = thingContent.getQueryStr();
@@ -377,7 +392,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
//wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, queryStr, !thingContent.getQuery().isEscaped(), false, hits);
return new KeywordSearchFilterNode(highlights, kvNode, queryStr, previewChunk);
}
}
@@ -438,12 +452,11 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
for (final AbstractFile f : uniqueMatches.keySet()) {
final int previewChunkId = uniqueMatches.get(f);
Map<String, Object> resMap = new LinkedHashMap<String, Object>();
Map<String, Object> resMap = new LinkedHashMap<>();
if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) {
AbstractFsContentNode.fillPropertyMap(resMap, (FsContent) f);
}
toPopulate.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, keywordQuery, thing.getQuery(), previewChunkId, matchesRes));
}
//write to bb
new ResultWriter(matchesRes, origQuery, "").execute();
@@ -459,7 +472,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
final int previewChunk = thingContent.getPreviewChunk();
final Map<String, List<ContentHit>> hits = thingContent.getHits();
Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content));
//wrap in KeywordSearchFilterNode for the markup content
HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, query, !thingContent.getQuery().isEscaped(), hits);
@@ -475,7 +487,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
private Content content;
private String queryStr;
private KeywordSearchQuery query;
private int previewChunk;
private Map<String, List<ContentHit>> hits;
@@ -510,7 +521,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
*/
static class ResultWriter extends SwingWorker<Object, Void> {
private static List<ResultWriter> writers = new ArrayList<ResultWriter>();
private static List<ResultWriter> writers = new ArrayList<>();
//lock utilized to enqueue writers and limit execution to 1 at a time
private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy
//private static final Lock writerLock = rwLock.writeLock();
@@ -518,14 +529,13 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
private KeywordSearchQuery query;
private String listName;
private Map<String, List<ContentHit>> hits;
final Collection<BlackboardArtifact> na = new ArrayList<BlackboardArtifact>();
final Collection<BlackboardArtifact> na = new ArrayList<>();
private static final int QUERY_DISPLAY_LEN = 40;
ResultWriter(Map<String, List<ContentHit>> hits, KeywordSearchQuery query, String listName) {
this.hits = hits;
this.query = query;
this.listName = listName;
}
protected void finalizeWorker() {
@@ -539,7 +549,6 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
});
if (!this.isCancelled() && !na.isEmpty()) {
IngestServices.getDefault().fireModuleDataEvent(new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na));
}
@@ -573,7 +582,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
for (AbstractFile f : flattened.keySet()) {
int chunkId = flattened.get(f);
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit);
String snippet = null;
String snippet;
try {
snippet = LuceneQuery.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true);
} catch (NoOpenCoreException e) {
@@ -591,15 +600,11 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
}
}
}
} finally {
//writerLock.unlock();
finalizeWorker();
}
return null;
}

View File

@@ -138,7 +138,7 @@ public class Chrome extends Extract {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//TODO Revisit usage of deprecated constructor per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 10000000)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 10000000)));
@@ -232,7 +232,7 @@ public class Chrome extends Extract {
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", (date / 10000000)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", (date / 10000000)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", url));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url)));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", name));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
@@ -299,7 +299,7 @@ public class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "Recent Activity", ((result.get("value").toString() != null) ? result.get("value").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? result.get("host_key").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : "")));
String domain = result.get("host_key").toString();
domain = domain.replaceFirst("^\\.+(?!$)", "");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
@@ -358,7 +358,7 @@ public class Chrome extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", (result.get("full_path").toString())));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), "Recent Activity", Util.findID(dataSource, (result.get("full_path").toString()))));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
Long time = (Long.valueOf(result.get("start_time").toString()));
String Tempdate = time.toString();
time = Long.valueOf(Tempdate) / 10000000;
@@ -417,7 +417,7 @@ public class Chrome extends Extract {
for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : "")));
//TODO Revisit usage of deprecated constructor as per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));

View File

@@ -136,7 +136,7 @@ public class ExtractIE extends Extract {
}
try {
this.parsePascoResults(pascoResults);
this.getHistory(pascoResults);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error parsing IE History", e);
@@ -189,7 +189,7 @@ public class ExtractIE extends Extract {
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", datetime));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", datetime));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", url));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url)));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", name));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer"));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
@@ -238,7 +238,7 @@ public class ExtractIE extends Extract {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", url));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url)));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url)));
//TODO Revisit usage of deprecated Constructor as of TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", "Last Visited", datetime));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", datetime));
@@ -394,7 +394,7 @@ public class ExtractIE extends Extract {
execPasco.execute(writer, JAVA_PATH,
"-cp", PASCO_LIB_PATH,
"isi.pasco2.Main", "-T", "history", indexFilePath );
// @@@ Investigate use of history versus cache as type.
} catch (IOException ex) {
success = false;
logger.log(Level.SEVERE, "Unable to execute Pasco to process Internet Explorer web history.", ex);
@@ -416,7 +416,7 @@ public class ExtractIE extends Extract {
return success;
}
private void parsePascoResults(List<String> filenames) {
private void getHistory(List<String> filenames) {
if (pascoFound == false) {
return;
}
@@ -451,6 +451,15 @@ public class ExtractIE extends Extract {
String line = fileScanner.nextLine();
// lines at end of file
if ((line.startsWith("LEAK entries")) ||
(line.startsWith("REDR entries")) ||
(line.startsWith("URL entries")) ||
(line.startsWith("ent entries")) ||
(line.startsWith("unknown entries"))) {
continue;
}
if (line.startsWith("URL")) {
String[] lineBuff = line.split("\\t");
@@ -466,6 +475,10 @@ public class ExtractIE extends Extract {
String realurl = "";
String domain = "";
/* We've seen two types of lines:
* URL http://XYZ.com ....
* URL Visited: Joe@http://XYZ.com ....
*/
if (lineBuff[1].contains("@")) {
String url[] = lineBuff[1].split("@", 2);
user = url[0];
@@ -505,7 +518,7 @@ public class ExtractIE extends Extract {
BlackboardArtifact bbart = tskCase.getContentById(artObjId).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", realurl));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", ftime));

View File

@@ -119,7 +119,7 @@ public class Firefox extends Extract {
for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//TODO Revisit usage of deprecated constructor as per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("visit_date").toString()))));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", (Long.valueOf(result.get("visit_date").toString()))));
@@ -177,7 +177,7 @@ public class Firefox extends Extract {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", ((result.get("title").toString() != null) ? result.get("title").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "FireFox"));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", (Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""))));
@@ -241,7 +241,7 @@ public class Firefox extends Extract {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? result.get("host").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? EscapeUtil.decodeURL(result.get("host").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? EscapeUtil.decodeURL(result.get("host").toString()) : "")));
//TODO Revisit usage of deprecated constructor as per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", "Title", ((result.get("name").toString() != null) ? result.get("name").toString() : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("lastAccessed").toString()))));
@@ -312,7 +312,7 @@ public class Firefox extends Extract {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
String urldecodedtarget = URLDecoder.decode(result.get("source").toString().replaceAll("file:///", ""), "UTF-8");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? result.get("source").toString() : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
//TODO Revisit usage of deprecated constructor as per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", (Long.valueOf(result.get("startTime").toString()))));