1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-05 18:14:30 +00:00

Merge branch 'develop' of https://github.com/sleuthkit/autopsy into smaller-installer

This commit is contained in:
U-Mhmdfy-PC\Mhmdfy
2015-12-15 17:55:55 -05:00
22 changed files with 207 additions and 181 deletions

View File

@@ -52,7 +52,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
int dotIndex = name.lastIndexOf(".");
if (dotIndex > 0) {
String ext = name.substring(dotIndex).toLowerCase();
// If this is an archive file we will listen for ingest events
// that will notify us when new content has been identified.
for (String s : FileTypeExtensions.getArchiveExtensions()) {
@@ -69,7 +69,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
}
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();

View File

@@ -375,58 +375,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
@Override
public String getItemType() {
switch (type) {
case TSK_WEB_BOOKMARK:
return "ExtractedBookmarks";
case TSK_WEB_COOKIE:
return "ExtractedCookies";
case TSK_WEB_HISTORY:
return "ExtractedHistory";
case TSK_WEB_DOWNLOAD:
return "ExtractedDownloads";
case TSK_INSTALLED_PROG:
return "ExtractedPrograms";
case TSK_RECENT_OBJECT:
return "ExtractedRecent";
case TSK_DEVICE_ATTACHED:
return "ExtractedAttachedDevices";
case TSK_WEB_SEARCH_QUERY:
return "ExtractedSearch";
case TSK_METADATA_EXIF:
return "ExtractedMetadataExif";
case TSK_EMAIL_MSG:
return "ExtractedEmailMsg";
case TSK_CONTACT:
return "ExtractedContants";
case TSK_MESSAGE:
return "ExtractedMessages";
case TSK_CALLLOG:
return "ExtractedCallLog";
case TSK_CALENDAR_ENTRY:
return "ExtractedCalendar";
case TSK_SPEED_DIAL_ENTRY:
return "ExtractedSpeedDial";
case TSK_BLUETOOTH_PAIRING:
return "ExtractedBluetooth";
case TSK_GPS_BOOKMARK:
return "ExtractedGPSBookmarks";
case TSK_GPS_LAST_KNOWN_LOCATION:
return "ExtractedGPSLastLocation";
case TSK_GPS_SEARCH:
return "ExtractedGPSSearch";
case TSK_SERVICE_ACCOUNT:
return "ExtractedServiceAccount";
case TSK_ENCRYPTION_DETECTED:
return "ExtractedEncryption";
case TSK_EXT_MISMATCH_DETECTED:
return "ExtractedExtMismatch";
case TSK_OS_INFO:
return "ExtractedOS";
case TSK_FACE_DETECTED:
return "ExtractedFaceDetected";
}
return "ExtractedContentType";
return type.getDisplayName();
}
}

View File

@@ -396,19 +396,18 @@ class SevenZipExtractor {
if (colonIndex != -1) {
// If alternate data stream is found, fix the name
// so Windows doesn't choke on the colon character.
useName = base + ext.substring(0, colonIndex);
} else {
switch (ext) {
case ".gz": //NON-NLS
useName = base;
break;
case ".tgz": //NON-NLS
useName = base + ".tar"; //NON-NLS
break;
case ".bz2": //NON-NLS
useName = base + ".bz2"; //NON-NLS
break;
}
ext = ext.substring(0, colonIndex);
}
switch (ext) {
case ".gz": //NON-NLS
useName = base;
break;
case ".tgz": //NON-NLS
useName = base + ".tar"; //NON-NLS
break;
case ".bz2": //NON-NLS
useName = base;
break;
}
}

View File

@@ -18,41 +18,76 @@
*/
package org.sleuthkit.autopsy.imagegallery;
import com.google.common.collect.ImmutableSet;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.logging.Level;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableSet;
import javax.swing.SwingUtilities;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.datamodel.TskCoreException;
/** Singleton that manages set of fileIds, as well as last selected fileID.
/**
* Manages set of selected fileIds, as well as last selected fileID. Since some
* actions (e.g. {@link ExtractAction} ) invoked through Image Gallery depend on
* what is available in the Utilities.actionsGlobalContext() lookup, we maintain
* that in sync with the local ObservableList based selection, via the
* ImageGalleryTopComponent's ExplorerManager.
*
* NOTE: When we had synchronization on selected and lastSelectedProp we got
* deadlocks with the tiles during selection
*
* TODO: should this be singleton? selections are only within a single group
* now... -jm
*/
public class FileIDSelectionModel {
private static final Logger LOGGER = Logger.getLogger(FileIDSelectionModel.class.getName());
private static FileIDSelectionModel instance;
private final ObservableSet<Long> selected = FXCollections.observableSet();
private final ReadOnlyObjectWrapper<Long> lastSelectedProp = new ReadOnlyObjectWrapper<>();
public static synchronized FileIDSelectionModel getInstance() {
if (instance == null) {
instance = new FileIDSelectionModel();
}
return instance;
}
public FileIDSelectionModel(ImageGalleryController controller) {
/**
* Since some actions (e.g. {@link ExtractAction} ) invoked through
* Image Gallery depend on what is available in the
* Utilities.actionsGlobalContext() lookup, we maintain that in sync
* with the local ObservableList based selection, via the
* ImageGalleryTopComponent's ExplorerManager.
*/
selected.addListener((Observable observable) -> {
Set<Long> fileIDs = ImmutableSet.copyOf(selected);
SwingUtilities.invokeLater(() -> {
ArrayList<FileNode> fileNodes = new ArrayList<>();
for (Long id : fileIDs) {
try {
fileNodes.add(new FileNode(controller.getSleuthKitCase().getAbstractFileById(id)));
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get abstract file by its ID", ex);
}
}
FileNode[] fileNodeArray = fileNodes.stream().toArray(FileNode[]::new);
Children.Array children = new Children.Array();
children.add(fileNodeArray);
public FileIDSelectionModel() {
super();
ImageGalleryTopComponent etc = (ImageGalleryTopComponent) WindowManager.getDefault().findTopComponent(ImageGalleryTopComponent.PREFERRED_ID);
etc.getExplorerManager().setRootContext(new AbstractNode(children));
try {
etc.getExplorerManager().setSelectedNodes(fileNodeArray);
} catch (PropertyVetoException ex) {
LOGGER.log(Level.SEVERE, "Explorer manager selection was vetoed.", ex);
}
});
});
}
public void toggleSelection(Long id) {
@@ -110,6 +145,10 @@ public class FileIDSelectionModel {
lastSelectedProp.set(id);
}
/**
* expose the list of selected ids so that clients can listen for changes
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
public ObservableSet<Long> getSelected() {
return selected;
}

View File

@@ -127,7 +127,7 @@ public final class ImageGalleryController {
private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false);
private final FileIDSelectionModel selectionModel = FileIDSelectionModel.getInstance();
private final FileIDSelectionModel selectionModel = new FileIDSelectionModel(this);
private DBWorkerThread dbWorkerThread;
@@ -167,7 +167,6 @@ public final class ImageGalleryController {
}
public synchronized FileIDSelectionModel getSelectionModel() {
return selectionModel;
}

View File

@@ -30,7 +30,6 @@ import javafx.scene.control.Menu;
import javax.swing.SwingWorker;
import org.openide.util.Utilities;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager;
@@ -66,7 +65,7 @@ public class AddDrawableTagAction extends AddTagAction {
@Override
public void addTag(TagName tagName, String comment) {
Set<Long> selectedFiles = new HashSet<>(FileIDSelectionModel.getInstance().getSelected());
Set<Long> selectedFiles = new HashSet<>(controller.getSelectionModel().getSelected());
addTagsToFiles(tagName, comment, selectedFiles);
}

View File

@@ -30,7 +30,6 @@ import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javax.swing.JOptionPane;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
@@ -69,13 +68,12 @@ public class CategorizeAction extends AddTagAction {
@Override
public void addTag(TagName tagName, String comment) {
Set<Long> selectedFiles = new HashSet<>(FileIDSelectionModel.getInstance().getSelected());
Set<Long> selectedFiles = new HashSet<>(controller.getSelectionModel().getSelected());
addTagsToFiles(tagName, comment, selectedFiles);
}
@Override
public void addTagsToFiles(TagName tagName, String comment, Set<Long> selectedFiles) {
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{selectedFiles.toString(), tagName.getDisplayName()});
for (Long fileID : selectedFiles) {
@@ -129,7 +127,6 @@ public class CategorizeAction extends AddTagAction {
final CategoryManager categoryManager = controller.getCategoryManager();
final DrawableTagsManager tagsManager = controller.getTagsManager();
try {
DrawableFile<?> file = controller.getFileFromId(fileID); //drawable db
final List<ContentTag> fileTags = tagsManager.getContentTagsByContent(file);

View File

@@ -54,6 +54,8 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy;
import static org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy.GROUP_BY_VALUE;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.SleuthkitCase;
@@ -475,6 +477,32 @@ public final class DrawableDB {
return con.isClosed();
}
/**
* get the names of the hashsets that the given fileID belongs to
*
* @param fileID the fileID to get all the Hashset names for
*
* @return a set of hash set names, each of which the given file belongs to
*
* @throws TskCoreException
*
*
* //TODO: this is mostly a cut and paste from *
* AbstractContent.getHashSetNames, is there away to dedupe?
*/
Set<String> getHashSetsForFile(long fileID) throws TskCoreException {
Set<String> hashNames = new HashSet<>();
ArrayList<BlackboardArtifact> artifacts = tskCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, fileID);
for (BlackboardArtifact a : artifacts) {
List<BlackboardAttribute> attributes = a.getAttributes(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
for (BlackboardAttribute attr : attributes) {
hashNames.add(attr.getValueString());
}
}
return Collections.unmodifiableSet(hashNames);
}
/**
* get all the hash set names used in the db
*

View File

@@ -44,7 +44,7 @@ public class HashSetManager {
*/
private Set<String> getHashSetsForFileHelper(long fileID) {
try {
return db.getFileFromID(fileID).getHashSetNames();
return db.getHashSetsForFile(fileID);
} catch (TskCoreException ex) {
Logger.getLogger(HashSetManager.class.getName()).log(Level.SEVERE, "Failed to get Hash Sets for file", ex);
return Collections.emptySet();

View File

@@ -32,7 +32,6 @@ import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
import org.sleuthkit.autopsy.imagegallery.gui.Toolbar;
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableTileBase.globalSelectionModel;
import org.sleuthkit.datamodel.AbstractContent;
/**
@@ -63,7 +62,7 @@ public class DrawableTile extends DrawableTileBase {
imageView.fitHeightProperty().bind(Toolbar.getDefault(getController()).sizeSliderValue());
imageView.fitWidthProperty().bind(Toolbar.getDefault(getController()).sizeSliderValue());
globalSelectionModel.lastSelectedProperty().addListener((observable, oldValue, newValue) -> {
selectionModel.lastSelectedProperty().addListener((observable, oldValue, newValue) -> {
try {
setEffect(Objects.equals(newValue, getFileID()) ? LAST_SELECTED_EFFECT : null);
} catch (java.lang.IllegalStateException ex) {
@@ -84,7 +83,7 @@ public class DrawableTile extends DrawableTileBase {
@Override
protected void updateSelectionState() {
super.updateSelectionState();
final boolean lastSelected = Objects.equals(globalSelectionModel.lastSelectedProperty().get(), getFileID());
final boolean lastSelected = Objects.equals(selectionModel.lastSelectedProperty().get(), getFileID());
Platform.runLater(() -> {
setEffect(lastSelected ? LAST_SELECTED_EFFECT : null);
});

View File

@@ -92,7 +92,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
protected static final Image followUpIcon = new Image("org/sleuthkit/autopsy/imagegallery/images/flag_red.png");
protected static final Image followUpGray = new Image("org/sleuthkit/autopsy/imagegallery/images/flag_gray.png");
protected static final FileIDSelectionModel globalSelectionModel = FileIDSelectionModel.getInstance();
protected final FileIDSelectionModel selectionModel;
private static ContextMenu contextMenu;
/**
@@ -143,9 +143,9 @@ public abstract class DrawableTileBase extends DrawableUIBase {
*/
protected DrawableTileBase(GroupPane groupPane, final ImageGalleryController controller) {
super(controller);
this.groupPane = groupPane;
globalSelectionModel.getSelected().addListener((Observable observable) -> updateSelectionState());
selectionModel = controller.getSelectionModel();
selectionModel.getSelected().addListener((Observable observable) -> updateSelectionState());
//set up mouse listener
//TODO: split this between DrawableTile and SingleDrawableViewBase
@@ -159,7 +159,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
case PRIMARY:
if (t.getClickCount() == 1) {
if (t.isControlDown()) {
globalSelectionModel.toggleSelection(fileID);
selectionModel.toggleSelection(fileID);
} else {
groupPane.makeSelection(t.isShiftDown(), fileID);
}
@@ -173,7 +173,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
break;
case SECONDARY:
if (t.getClickCount() == 1) {
if (globalSelectionModel.isSelected(fileID) == false) {
if (selectionModel.isSelected(fileID) == false) {
groupPane.makeSelection(false, fileID);
}
}
@@ -257,7 +257,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
getFile().ifPresent(file -> {
if (followUpToggle.isSelected() == true) {
try {
globalSelectionModel.clearAndSelect(file.getId());
selectionModel.clearAndSelect(file.getId());
new AddDrawableTagAction(getController()).addTag(getController().getTagsManager().getFollowUpTagName(), "");
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to add Follow Up tag. Could not load TagName.", ex);
@@ -339,7 +339,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
*/
protected void updateSelectionState() {
getFile().ifPresent(file -> {
final boolean selected = globalSelectionModel.isSelected(file.getId());
final boolean selected = selectionModel.isSelected(file.getId());
Platform.runLater(() -> setBorder(selected ? SELECTED_BORDER : UNSELECTED_BORDER));
});
}

View File

@@ -151,7 +151,7 @@ public class GroupPane extends BorderPane {
new KeyFrame(Duration.millis(400), new KeyValue(DROP_SHADOW.radiusProperty(), 15, Interpolator.LINEAR))
);
private static final FileIDSelectionModel globalSelectionModel = FileIDSelectionModel.getInstance();
private final FileIDSelectionModel selectionModel;
private static final List<KeyCode> categoryKeyCodes = Arrays.asList(KeyCode.NUMPAD0, KeyCode.NUMPAD1, KeyCode.NUMPAD2, KeyCode.NUMPAD3, KeyCode.NUMPAD4, KeyCode.NUMPAD5,
KeyCode.DIGIT0, KeyCode.DIGIT1, KeyCode.DIGIT2, KeyCode.DIGIT3, KeyCode.DIGIT4, KeyCode.DIGIT5);
@@ -257,6 +257,7 @@ public class GroupPane extends BorderPane {
public GroupPane(ImageGalleryController controller) {
this.controller = controller;
this.selectionModel = controller.getSelectionModel();
nextGroupAction = new NextUnseenGroup(controller);
backAction = new Back(controller);
forwardAction = new Forward(controller);
@@ -303,7 +304,7 @@ public class GroupPane extends BorderPane {
slideShowPane.disposeContent();
}
slideShowPane = null;
this.scrollToFileID(globalSelectionModel.lastSelectedProperty().get());
this.scrollToFileID(selectionModel.lastSelectedProperty().get());
}
public DrawableGroup getGroup() {
@@ -311,7 +312,7 @@ public class GroupPane extends BorderPane {
}
private void selectAllFiles() {
globalSelectionModel.clearAndSelectAll(getGroup().fileIds());
selectionModel.clearAndSelectAll(getGroup().fileIds());
}
/**
@@ -363,7 +364,7 @@ public class GroupPane extends BorderPane {
if (slideShowPane != null) {
slideShowPane.getFileID().ifPresent(fileID -> {
if (newValue) {
FileIDSelectionModel.getInstance().clearAndSelect(fileID);
selectionModel.clearAndSelect(fileID);
new CategorizeAction(controller).addTag(controller.getTagsManager().getTagName(cat), "");
}
});
@@ -428,10 +429,10 @@ public class GroupPane extends BorderPane {
HBox.setHgrow(spacer, Priority.ALWAYS);
spacer.setMinWidth(Region.USE_PREF_SIZE);
FileIDSelectionModel.getInstance().getSelected().addListener((Observable o) -> {
selectionModel.getSelected().addListener((Observable o) -> {
Platform.runLater(() -> {
catSelectedSplitMenu.setDisable(FileIDSelectionModel.getInstance().getSelected().isEmpty());
tagSelectedSplitMenu.setDisable(FileIDSelectionModel.getInstance().getSelected().isEmpty());
catSelectedSplitMenu.setDisable(selectionModel.getSelected().isEmpty());
tagSelectedSplitMenu.setDisable(selectionModel.getSelected().isEmpty());
});
});
@@ -491,7 +492,7 @@ public class GroupPane extends BorderPane {
//listen to toggles and update view state
slideShowToggle.setOnAction((ActionEvent t) -> {
activateSlideShowViewer(globalSelectionModel.lastSelectedProperty().get());
activateSlideShowViewer(selectionModel.lastSelectedProperty().get());
});
tileToggle.setOnAction((ActionEvent t) -> {
@@ -543,7 +544,7 @@ public class GroupPane extends BorderPane {
switch (t.getButton()) {
case PRIMARY:
if (t.getClickCount() == 1) {
globalSelectionModel.clearSelection();
selectionModel.clearSelection();
if (contextMenu != null) {
contextMenu.hide();
}
@@ -554,7 +555,7 @@ public class GroupPane extends BorderPane {
if (t.getClickCount() == 1) {
selectAllFiles();
}
if (globalSelectionModel.getSelected().isEmpty() == false) {
if (selectionModel.getSelected().isEmpty() == false) {
if (contextMenu == null) {
contextMenu = buildContextMenu();
}
@@ -590,7 +591,7 @@ public class GroupPane extends BorderPane {
//listen to tile selection and make sure it is visible in scroll area
//TODO: make sure we are testing complete visability not just bounds intersection
globalSelectionModel.lastSelectedProperty().addListener((observable, oldFileID, newFileId) -> {
selectionModel.lastSelectedProperty().addListener((observable, oldFileID, newFileId) -> {
if (groupViewMode.get() == GroupViewMode.SLIDE_SHOW) {
slideShowPane.setFile(newFileId);
} else {
@@ -736,11 +737,11 @@ public class GroupPane extends BorderPane {
endIndex = IntStream.of(0, selectionAnchorIndex, endIndex).max().getAsInt();
List<Long> subList = grouping.get().fileIds().subList(Math.max(0, startIndex), Math.min(endIndex, grouping.get().fileIds().size()) + 1);
globalSelectionModel.clearAndSelectAll(subList.toArray(new Long[subList.size()]));
globalSelectionModel.select(newFileID);
selectionModel.clearAndSelectAll(subList.toArray(new Long[subList.size()]));
selectionModel.select(newFileID);
} else {
selectionAnchorIndex = null;
globalSelectionModel.clearAndSelect(newFileID);
selectionModel.clearAndSelect(newFileID);
}
}
@@ -796,7 +797,7 @@ public class GroupPane extends BorderPane {
switch (t.getCode()) {
case SHIFT:
if (selectionAnchorIndex == null) {
selectionAnchorIndex = grouping.get().fileIds().indexOf(globalSelectionModel.lastSelectedProperty().get());
selectionAnchorIndex = grouping.get().fileIds().indexOf(selectionModel.lastSelectedProperty().get());
}
t.consume();
break;
@@ -827,7 +828,7 @@ public class GroupPane extends BorderPane {
break;
case SPACE:
if (groupViewMode.get() == GroupViewMode.TILE) {
activateSlideShowViewer(globalSelectionModel.lastSelectedProperty().get());
activateSlideShowViewer(selectionModel.lastSelectedProperty().get());
} else {
activateTileViewer();
}
@@ -839,7 +840,7 @@ public class GroupPane extends BorderPane {
selectAllFiles();
t.consume();
}
if (globalSelectionModel.getSelected().isEmpty() == false) {
if (selectionModel.getSelected().isEmpty() == false) {
switch (t.getCode()) {
case NUMPAD0:
case DIGIT0:
@@ -871,7 +872,7 @@ public class GroupPane extends BorderPane {
}
private void handleArrows(KeyEvent t) {
Long lastSelectFileId = globalSelectionModel.lastSelectedProperty().get();
Long lastSelectFileId = selectionModel.lastSelectedProperty().get();
int lastSelectedIndex = lastSelectFileId != null
? grouping.get().fileIds().indexOf(lastSelectFileId)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -89,7 +89,7 @@ To this:
Note the removal of the leading number symbol-this uncomments that entry.
<br><br>
8. Still in <i>"C:\Program Files\PostgreSQL\9.4\data\postgresql.conf"</i>, find the entry named _max_connections_ and set it to the number of suggested connections for your configuration. A rule of thumb is add 100 connections for each Automated Ingest Node and 100 connections for each Reviewer node you plan to have in the network. More information is available at 5.1.1. See the screenshot below.
8. Still in <i id="max_connections">"C:\Program Files\PostgreSQL\9.4\data\postgresql.conf"</i>, find the entry named _max_connections_ and set it to the number of suggested connections for your configuration. A rule of thumb is add 100 connections for each Automated Ingest Node and 100 connections for each Reviewer node you plan to have in the network. More information is available at 5.1.1. See the screenshot below.
<br><br>
\image html maxConnections.PNG
<br><br>

View File

@@ -35,12 +35,11 @@ The following steps will configure Solr to run using an account that will have a
5. When the installation completes, clear the "Launch Bitnami Apache Solr Stack Now?" checkbox and click _Finish_.
\subsection install_solr_config Solr Configuration
1. Stop _solrApache_ and _solrJetty_ services by pressing _Start_, typing _services.msc_, pressing _Enter_, and locating the _solrApache_ and _solrJetty_ Windows services. Select the services one at a time, and press _Stop the service_ once for each of them. If the service is already stopped and there is no _Stop the service_ available, this is okay.
1. Stop the _solrJetty_ service by pressing _Start_, typing _services.msc_, pressing _Enter_, and locating the _solrJetty_ Windows service. Select the service and press _Stop the service_. If the service is already stopped and there is no _Stop the service_ available, this is okay.
2. Edit the <i>C:\\Bitnami\\solr-4.10.3-0\\apache-solr\\scripts\\serviceinstall.bat</i> script. You need administrator permission to change this file. The easiest way around this is to save a copy on the Desktop, edit the Desktop version, and copy the new one back over the top of the old. Windows will ask for permission to overwrite the old file; allow it. You should make the following changes to this file:
<br>
<br>
- Add the following options in the _JvmOptions_ section of the line that begins with <i>"C:\Bitnami\solr-4.10.3-0/apache-solr\scripts\prunsrv.exe"</i> :
+ <i>++JvmOptions=-DzkRun</i>
+ <i>++JvmOptions=-Dcollection.configName=AutopsyConfig</i>
+ <i>++JvmOptions=-Dbootstrap_confdir="C:\Bitnami\solr-4.10.3-0\apache-solr\solr\configsets\AutopsyConfig\conf"</i>
- Replace the path to <i>JavaHome</i> with the path to your 64-bit version of the JRE. If you do not know the path, the correct _JavaHome_ path can be obtained by running the command <i>"where java"</i> from the Windows command line. An example is shown below. The text in yellow is what we are interested in. Do not include the <i>"bin"</i> folder in the path you place into the _JavaHome_ variable. A correct example of the final result will look something like this:&nbsp;&nbsp;&nbsp;<i>--JavaHome="C:\Program Files\Java\jre1.8.0_45"</i>
@@ -66,24 +65,7 @@ The added part is highlighted in yellow below. Ensure that it is inside the <i>\
<br>
\image html transientcache.PNG
<br><br>
4. Edit the file <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr\zoo.cfg"</i> to increase the _tickTime_ value to 15000 as shown in the screenshot below.
<br><br>
\image html tickTime.PNG
<br><br>
5. Create a folder on your local hard drive named _C:/Bitnami/zookeeper_
6. Edit the file <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr\zoo.cfg"</i> to set the value <i>dataDir=C:/Bitnami/zookeeper</i> as shown in the screenshot below.
<br><br>
\image html dataDir.PNG
<br><br>
7. Edit the file <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr\zoo.cfg"</i> to add the lines <i>autopurge.snapRetainCount=3</i> and <i>autopurge.purgeInterval=1</i> as shown in the screenshot below.
<br><br>
\image html autoPurge.PNG
<br><br>
8. Install _ZkJanitor_ by right clicking on _InstallJanitor.bat_, and selecting "Run as administrator". You should see a confirmation that ZkJanitor is installed, as shown in the screenshot below.
<br><br>
\image html InstallZkJanitor.PNG
<br><br>
9. Edit <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\resources/log4j.properties"</i> to configure Solr log settings:
4. Edit <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\resources/log4j.properties"</i> to configure Solr log settings:
- Increase the log rotation size threshold (_log4j\.appender\.file\.MaxFileSize_) from 4MB to 100MB.
- Remove the _CONSOLE_ appender from the _log4j\.rootLogger_ line.
<br><br>
@@ -93,9 +75,9 @@ The log file should end up looking like this (modified lines are highlighted in
<br><br>
\image html log4j.PNG
<br><br>
10. From an Autopsy installation, copy the folder <i>"C:\Program Files\Autopsy-4.0\autopsy\solr\solr\configsets"</i> to <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr"</i>.
11. From an Autopsy installation, copy the folder <i>"C:\Program Files\Autopsy-4.0\autopsy\solr\solr\lib"</i> to <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr"</i>.
12. Start a Windows command prompt as administrator by pressing _Start_, typing _command_, right clicking on _Command Prompt_, and clicking on _Run as administrator_. Then run the following command to install the _solrJetty_ service:
5. From an Autopsy installation, copy the folder <i>"C:\Program Files\Autopsy-4.0\autopsy\solr\solr\configsets"</i> to <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr"</i>.
6. From an Autopsy installation, copy the folder <i>"C:\Program Files\Autopsy-4.0\autopsy\solr\solr\lib"</i> to <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\solr"</i>.
7. Start a Windows command prompt as administrator by pressing _Start_, typing _command_, right clicking on _Command Prompt_, and clicking on _Run as administrator_. Then run the following command to install the _solrJetty_ service:
<br><br>
<i>cmd /c C:\\Bitnami\\solr-4.10.3-0\\apache-solr\\scripts\\serviceinstall.bat INSTALL</i>
<br><br>
@@ -103,13 +85,13 @@ The log file should end up looking like this (modified lines are highlighted in
<br><br>
\image html solrinstall1.PNG
<br><br>
13. Press _Start_, type _services.msc_, and press _Enter_. Find _solrJetty_. If the service is running, press _Stop the service_, then double click it, and switch to the _Log On_ tab to change the logon credentials to a user who will have access to read and write the primary shared drive. If the machine is on a domain, the Account Name will be in the form of _DOMAINNAME\\username_ as shown in the example below. Note that in the screenshot below, the domain name is _DOMAIN_ and the user name is _username_. These are just examples, not real values.
8. Press _Start_, type _services.msc_, and press _Enter_. Find _solrJetty_. If the service is running, press _Stop the service_, then double click it, and switch to the _Log On_ tab to change the logon credentials to a user who will have access to read and write the primary shared drive. If the machine is on a domain, the Account Name will be in the form of _DOMAINNAME\\username_ as shown in the example below. Note that in the screenshot below, the domain name is _DOMAIN_ and the user name is _username_. These are just examples, not real values.
<br><br>
\image html solrinstall2.PNG
<br>
If the machine is on a domain, **make sure** to select the domain with the mouse by going to the _Log On_ tab, clicking _Browse_, then clicking _Locations_ and selecting the domain of interest. Then enter the user name desired and press _Check Names_. When that completes, press _OK_, type in the password once for each box and press _OK_. You may see "The user has been granted the log on as a service right."
14. You should be able to see the Solr service in a web browser via the URL <i>http://localhost:8983/solr/#/</i> as shown in the screenshot below.
9. You should be able to see the Solr service in a web browser via the URL <i>http://localhost:8983/solr/#/</i> as shown in the screenshot below.
<br><br>
\image html solrinstall3.PNG
<br><br>

View File

@@ -2,11 +2,24 @@
<!--
This file is an example configuration file for regression.py.
List of tags:
image: An image to be ingested
build: the path to the build.xml file
indir: the path to input directory
outdir: the path to output directory
global_csv: path to global csv file
golddir: the path to gold directory
jenkins: can be set to True or False. If enabled, check for diffdir
diffdir: (only if jenkins tag is true) the diff directory
timing: can be set to True or False. If enabled, record the timing.
NOTE: Make sure to use windows style for paths!
None of these tags are mandatory, and if nothing is provided the file will be
looked over and ignored.
If the -i tag is not set as an argument, images from the input directory will
be tested after the images provided in this file are.
If the -i flag is not set as an argument to regression.py, images from
the input directory will be tested after the images provided in this file are.
By default the input directory will be ./input, however if the indir tag
is set, that value will become the new input directory. This directory must
have the required hash/keyword search files, and if -i is not set, this
@@ -23,6 +36,7 @@ All paths given to the script have to be full paths from the root directoy.
NOTE: Some image formats can only be parsed by Autopsy using a Windows path
(i.e. X:\this\is\a\windows\path /this/is/not/a/windows/path)
It is up to the user to distinguish between the paths when adding to this file.
-->
<Properties>

View File

@@ -84,15 +84,16 @@ Day = 0
def usage():
print ("-f PATH single file")
print ("-r rebuild")
print ("-l PATH path to config file")
print ("-u Ignore unallocated space")
print ("-k Do not delete SOLR index")
print ("-o PATH path to output folder for Diff files")
print ("-v verbose mode")
print ("-e ARG Enable exception mode with given string")
print ("-h help")
print ("-f PATH single file")
print ("-r rebuild")
print ("-b run both compare and rebuild")
print ("-l PATH path to config file")
print ("-u Ignore unallocated space")
print ("-k Do not delete SOLR index")
print ("-o PATH path to output folder for Diff files")
print ("-v verbose mode")
print ("-e ARG Enable exception mode with given string")
print ("-h help")
#----------------------#
# Main #
@@ -103,10 +104,12 @@ def main():
parse_result = args.parse()
# The arguments were given wrong:
if not parse_result:
return
Errors.print_error("The arguments were given wrong")
exit(1)
test_config = TestConfiguration(args)
TestRunner.run_tests(test_config)
exit(0)
class TestRunner(object):
@@ -125,6 +128,7 @@ class TestRunner(object):
Reports.html_add_images(test_config.html_log, test_config.images)
# Test each image
gold_exists = False
logres =[]
for test_data in test_data_list:
Errors.clear_print_logs()
@@ -133,6 +137,11 @@ class TestRunner(object):
Errors.print_error(msg)
Errors.print_error(test_data.gold_archive)
continue
# At least one test has gold
gold_exists = True
# Analyze the given image
TestRunner._run_autopsy_ingest(test_data)
@@ -140,9 +149,12 @@ class TestRunner(object):
# Generate HTML report
Reports.write_html_foot(test_config.html_log)
# Either copy the data or compare the data
# Either copy the data or compare the data or both
if test_config.args.rebuild:
TestRunner.rebuild(test_data)
elif test_config.args.both:
logres.append(TestRunner._compare_results(test_data))
TestRunner.rebuild(test_data)
else:
logres.append(TestRunner._compare_results(test_data))
@@ -152,9 +164,11 @@ class TestRunner(object):
time.sleep(10)
TestRunner._cleanup(test_data)
if all([ test_data.overall_passed for test_data in test_data_list ]):
pass
else:
if not gold_exists:
Errors.print_error("No image had any gold; Regression did not run")
exit(1)
if not all([ test_data.overall_passed for test_data in test_data_list ]):
html = open(test_config.html_log)
Errors.add_errors_out(html.name)
html.close()
@@ -179,13 +193,17 @@ class TestRunner(object):
TestRunner._run_ant(test_data)
time.sleep(2) # Give everything a second to process
# exit if .db was not created
if not file_exists(test_data.get_db_path(DBType.OUTPUT)):
Errors.print_error("Autopsy did not run properly; No .db file was created")
sys.exit(1)
try:
# Dump the database before we diff or use it for rebuild
TskDbDiff.dump_output_db(test_data.get_db_path(DBType.OUTPUT), test_data.get_db_dump_path(DBType.OUTPUT),
test_data.get_sorted_data_path(DBType.OUTPUT))
except sqlite3.OperationalError as e:
print("Ingest did not run properly.",
"Make sure no other instances of Autopsy are open and try again.")
Errors.print_error("Ingest did not run properly.\nMake sure no other instances of Autopsy are open and try again.")
sys.exit(1)
# merges logs into a single log for later diff / rebuild
@@ -396,8 +414,7 @@ class TestRunner(object):
test_data.ant.append("-Dkeyword_path=" + test_config.keyword_path)
test_data.ant.append("-Dnsrl_path=" + test_config.nsrl_path)
test_data.ant.append("-Dgold_path=" + test_config.gold)
test_data.ant.append("-Dout_path=" +
make_local_path(test_data.output_path))
test_data.ant.append("-Dout_path=" + make_local_path(test_data.output_path))
if test_config.jenkins:
test_data.ant.append("-Ddiff_dir="+ test_config.diff_dir)
test_data.ant.append("-Dignore_unalloc=" + "%s" % test_config.args.unallocated)
@@ -657,6 +674,7 @@ class TestConfiguration(object):
"""
self.args = args
# Paths:
self.output_parent_dir = make_path("..", "output", "results")
self.output_dir = ""
self.input_dir = make_local_path("..","input")
self.gold = make_path("..", "output", "gold")
@@ -703,17 +721,19 @@ class TestConfiguration(object):
counts = {}
if parsed_config.getElementsByTagName("indir"):
self.input_dir = parsed_config.getElementsByTagName("indir")[0].getAttribute("value").encode().decode("utf_8")
if parsed_config.getElementsByTagName("outdir"):
self.output_parent_dir = parsed_config.getElementsByTagName("outdir")[0].getAttribute("value").encode().decode("utf_8")
if parsed_config.getElementsByTagName("global_csv"):
self.global_csv = parsed_config.getElementsByTagName("global_csv")[0].getAttribute("value").encode().decode("utf_8")
self.global_csv = make_local_path(self.global_csv)
if parsed_config.getElementsByTagName("golddir"):
self.gold = parsed_config.getElementsByTagName("golddir")[0].getAttribute("value").encode().decode("utf_8")
if parsed_config.getElementsByTagName("jenkins"):
self.jenkins = True
if parsed_config.getElementsByTagName("diffdir"):
self.jenkins = parsed_config.getElementsByTagName("jenkins")[0].getAttribute("value").encode().decode("utf_8")
if self.jenkins and parsed_config.getElementsByTagName("diffdir"):
self.diff_dir = parsed_config.getElementsByTagName("diffdir")[0].getAttribute("value").encode().decode("utf_8")
else:
self.jenkins = False
else:
self.jenkins = False
if parsed_config.getElementsByTagName("timing"):
self.timing = parsed_config.getElementsByTagName("timing")[0].getAttribute("value").encode().decode("utf_8")
self._init_imgs(parsed_config)
@@ -727,9 +747,9 @@ class TestConfiguration(object):
def _init_logs(self):
"""Setup output folder, logs, and reporting infrastructure."""
if(not dir_exists(make_path("..", "output", "results"))):
os.makedirs(make_path("..", "output", "results",))
self.output_dir = make_path("..", "output", "results", time.strftime("%Y.%m.%d-%H.%M.%S"))
if not dir_exists(self.output_parent_dir):
os.makedirs(self.output_parent_dir)
self.output_dir = make_path(self.output_parent_dir, time.strftime("%Y.%m.%d-%H.%M.%S"))
os.makedirs(self.output_dir)
self.csv = make_local_path(self.output_dir, "CSV.txt")
self.html_log = make_path(self.output_dir, "AutopsyTestCase.html")
@@ -757,6 +777,9 @@ class TestConfiguration(object):
image_count = len(self.images)
# Sanity check to see if there are obvious gold images that we are not testing
if not dir_exists(self.gold):
Errors.print_error("Gold folder does not exist")
sys.exit(1)
gold_count = 0
for file in os.listdir(self.gold):
if not(file == 'tmp'):
@@ -885,7 +908,7 @@ class TestResultsDiffer(object):
(subprocess.check_output(["diff", '-r', '-N', '-x', '*.png', '-x', '*.ico', '--ignore-matching-lines',
'HTML Report Generated on \|Autopsy Report for case \|Case:\|Case Number:'
'\|Examiner:', gold_report_path, output_report_path]))
print_report("", "REPORT COMPARISON", "The test reports matched the gold reports")
print_report("", "REPORT COMPARISON", "The test html reports matched the gold reports")
return True
except subprocess.CalledProcessError as e:
if e.returncode == 1:
@@ -1644,6 +1667,7 @@ class Args(object):
self.single = False
self.single_file = ""
self.rebuild = False
self.both = False
self.list = False
self.config_file = ""
self.unallocated = False
@@ -1672,6 +1696,9 @@ class Args(object):
elif(arg == "-r" or arg == "--rebuild"):
print("Running in rebuild mode.\n")
self.rebuild = True
elif(arg == "-b" or arg == "--both"):
print("Comparing then creating gold")
self.both = True
elif(arg == "-l" or arg == "--list"):
try:
arg = sys.argv.pop(0)
@@ -1709,7 +1736,7 @@ class Args(object):
elif arg == "-o" or arg == "--output":
try:
arg = sys.argv.pop(0)
if not os.path.exists(arg):
if not dir_exists(arg):
print("Invalid output folder given.\n")
return False
nxtproc.append(arg)
@@ -1995,3 +2022,4 @@ if __name__ == "__main__":
main()
else:
print("We only support Windows and Cygwin at this time.")
sys.exit(1)

View File

@@ -44,8 +44,6 @@ class TskDbDiff(object):
self.output_dir = output_dir
self.gold_bb_dump = gold_bb_dump
self.gold_dump = gold_dump
self._generate_gold_dump = True
self._generate_gold_bb_dump = True
self._bb_dump_diff = ""
self._dump_diff = ""
self._bb_dump = ""
@@ -61,12 +59,6 @@ class TskDbDiff(object):
self._init_diff()
# generate the gold database dumps if necessary
if self._generate_gold_dump:
TskDbDiff._dump_output_db_nonbb(self.gold_db_file, self.gold_dump)
if self._generate_gold_bb_dump:
TskDbDiff._dump_output_db_bb(self.gold_db_file, self.gold_bb_dump)
# generate the output database dumps (both DB and BB)
TskDbDiff._dump_output_db_nonbb(self.output_db_file, self._dump)
TskDbDiff._dump_output_db_bb(self.output_db_file, self._bb_dump)