Initial import into github

This commit is contained in:
Brian Carrier 2011-11-09 13:10:50 -05:00
parent 4df5a591d8
commit 8d72f95d11
343 changed files with 26673 additions and 0 deletions

8
Case/build.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="org.sleuthkit.autopsy.casemodule" default="netbeans" basedir=".">
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.casemodule.</description>
<import file="nbproject/build-impl.xml"/>
</project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -0,0 +1,51 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>About Image</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>About Images</h2>
<p>
In Autopsy, an "Image" refers to the "Disk Image". Before an image can be analyzed, it must be added to a <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html">case</a>.
</p>
<p>Autopsy creates a database for each image that it imports. This database is a SQLite database and it contains all of the file system metadata from the image. When adding an image, it will take a little bit of time to populate the database. The database is stored in the case directory, but the image will stay in its original location.</p>
<h2>Supported Formats</h2>
<p>
Currently, Autopsy only supports these formats of image:
<ul type="circle">
<li>Raw Single (For example: *.img, *.dd, etc)</li>
<li>Raw Split (For example: *.001, *.002, *.aa, *.ab, etc)</li>
<li>EnCase (For example: *.e01, *e02, etc)</li>
</ul>
<h2>Adding an Image</h2>
<p>
To see how to add image to the current opened case, click <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/addImage.html">here</a>.
</p>
<h2>Removing an Image</h2>
<p>
You can remove an image in the <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/caseProperties.html">Case Properties</a> window.
</p>
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,45 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Adding An Image</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Adding An Image</h2>
<p>
There are several ways to add an image to the currently opened case:
<ul type="circle">
<li>Go to "File" and select "Add Image..." </li>
<li>Select the <img src="addImage-icon.png" alt="Add Image Icon" /> icon on the toolbar</li>
</ul>
<p>
After that, a "Add Image" wizard dialog will show up. Then follow these following steps:</p>
<ul>
<li>Select "Image Type", then enter the "Image Path" to the image that you want to analyze (you can also use the "Browse" button to browse the location of your image). Also specify the timezone that you want. When everything is completed, press "Next" button.<br><br>
&nbsp; &nbsp; <img src="AddImageWizard1_Help.png" alt="Add Image Wizard Panel 1 Help" /> </li>
<li>Autopsy needs to analyze the image to populate its database with file system metadata. If you have configured hash databases, you will be given the option of looking up files in the hash database during the ingest. Press the "Create Database" button to create the database. When the database creation process is done, you can press the "Next" button.<br><br>
&nbsp; &nbsp; <img src="AddImageWizard2_Help.png" alt="Add Image Wizard Panel 2 Help" /> </li>
<li>After the database is created, the image can be analyzed. You will be given the option to add another image or start the analysis. <br><br>
&nbsp; &nbsp; <img src="AddImageWizard3_Help.png" alt="Add Image Wizard Panel 3 Help" /> </li>
</ul>
<p>Note that Autopsy will store the path to the image in its configuration file. If the image moves, then Autopsy will give an error because it can't find the image file.
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

View File

@ -0,0 +1,48 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Case Properties Window</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Case Properties Window</h2>
<p>
Case Properties Window is the window where you can check some information about the currently opened case (case name, case creation date, case directory, and images in this case.
<br><br>
In this window, you can also do the following things:
<ul>
<li>Change/update the case name</li>
<li>Delete the current case</li>
<li>Remove image(s) from the current case</li>
</ul>
</p>
<h2>How to Open Case Properties Window</h2>
<p>
To open the "Case Properties" window, go to "File" and then select "Case Properties..." <br><br>
</p>
<h2>Example</h2>
<p>
Here's an example of the "Case Properties" window: <br>
<img src="CasePropertiesHelp.png" alt="Case Properties Help" />
</p>
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

View File

@ -0,0 +1,50 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>About Cases</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>About Cases</h2>
<p>
In Autopsy, a "case" is a container concept for a set of <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html">images</a>. The set of images could be from multiple drives in a single computer or from multiple computers. When you make a case, it will create a directory to hold all of the information. The directory will contain a configuration file, some databases, and some other information.
</p>
<h2>Creating a Case</h2>
<p>
Refer to the <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/createNewCase.html">Creating a Case</a> page for more details.
</p>
<h2>Opening a Case</h2>
<p>
There are three ways to open a case:
<ul>
<li>Go to "File" and then select "Open Case..."</li>
<li>Select the <img src="open-icon.png" alt="Open Case Icon" /> icon on the toolbar</li>
<li>Press "Ctrl + O" on the keyboard</li>
</ul>
<p>
After that, a File Chooser dialog will show up. Then select a ".aut" file that you previously created. It will be in the case folder.
</p>
<h2>What's Next?</h2>
<p>After you create a case, you can <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/addImage.html">add an image</a> to the case. </p>
<p>If you want to view case details or edit some case information, use the <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/caseProperties.html">Case Properties</a> window.
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE helpset PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN" "http://java.sun.com/products/javahelp/helpset_2_0.dtd">
<helpset version="2.0">
<title>Case Help</title>
<maps>
<homeID>org.sleuthkit.autopsy.casemodule.about</homeID>
<mapref location="casemodule-map.xml"/>
</maps>
<view mergetype="javax.help.AppendMerge">
<name>TOC</name>
<label>Table of Contents</label>
<type>javax.help.TOCView</type>
<data>casemodule-toc.xml</data>
</view>
<view mergetype="javax.help.AppendMerge">
<name>Index</name>
<label>Index</label>
<type>javax.help.IndexView</type>
<data>casemodule-idx.xml</data>
</view>
<view>
<name>Search</name>
<label>Search</label>
<type>javax.help.SearchView</type>
<data engine="com.sun.java.help.search.DefaultSearchEngine">JavaHelpSearch</data>
</view>
</helpset>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE index PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 2.0//EN" "http://java.sun.com/products/javahelp/index_2_0.dtd">
<index version="2.0">
<indexitem text="Overview" target="org.sleuthkit.autopsy.casemodule.overview"/>
<indexitem text="About Cases" target="org.sleuthkit.autopsy.casemodule.about"/>
<indexitem text="Creating a Case" target="org.sleuthkit.autopsy.casemodule.how-to-create-case"/>
<indexitem text="About Images" target="org.sleuthkit.autopsy.casemodule.image-about"/>
<indexitem text="Adding an Image" target="org.sleuthkit.autopsy.casemodule.add-image"/>
<indexitem text="Case Properties Window" target="org.sleuthkit.autopsy.casemodule.caseproperties"/>
<indexitem text="Hash Database Management" target="org.sleuthkit.autopsy.casemodule.hashdbmgmt"/>
</index>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE map PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 2.0//EN" "http://java.sun.com/products/javahelp/map_2_0.dtd">
<map version="2.0">
<mapID target="org.sleuthkit.autopsy.casemodule.overview" url="overview.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.about" url="casemodule-about.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.how-to-create-case" url="createNewCase.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.image-about" url="aboutImage.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.add-image" url="addImage.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.caseproperties" url="caseProperties.html"/>
<mapID target="org.sleuthkit.autopsy.casemodule.hashdbmgmt" url="hashDbMgmt.html"/>
</map>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE toc PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 2.0//EN" "http://java.sun.com/products/javahelp/toc_2_0.dtd">
<toc version="2.0">
<tocitem text="Overview" target="org.sleuthkit.autopsy.casemodule.overview"/>
<tocitem text="Case Management">
<tocitem text="Case">
<tocitem text="About Cases" target="org.sleuthkit.autopsy.casemodule.about"/>
<tocitem text="Creating a Case" target="org.sleuthkit.autopsy.casemodule.how-to-create-case"/>
</tocitem>
<tocitem text="Image">
<tocitem text="About Images" target="org.sleuthkit.autopsy.casemodule.image-about"/>
<tocitem text="Adding an Image" target="org.sleuthkit.autopsy.casemodule.add-image"/>
</tocitem>
<tocitem text="Case Properties Window" target="org.sleuthkit.autopsy.casemodule.caseproperties"/>
<tocitem text="Hash Database Management Window" target="org.sleuthkit.autopsy.casemodule.hashdbmgmt"/>
</tocitem>
</toc>

View File

@ -0,0 +1,43 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Creating A Case</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Creating a Case</h2>
<p>
There are several ways to create a new case:
<ul type="circle">
<li>Go to "File" and select "New Case..." </li>
<li>Select the <img src="new-icon.png" alt="New Case Icon" /> icon on the toolbar</li>
<li>Press "Ctrl + N" on the keyboard</li>
</ul>
</p>
<p>The "New Case" wizard dialog will open and you will need to enter the case name and base directory. Each case will have its own directory and the path of the directory is created by combining the "base directory" with the "case name". If the directory already exists, you will need to either delete the existing directory or choose a different combination of names.
</p>
<h2>Example:</h2>
<p>
Here's an example of the "New Case" wizard dialog: <br>
<img src="NewCaseWizardHelp.png" alt="New Case Wizard Help" />
</p>
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

View File

@ -0,0 +1,50 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Hash Database Management</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Hash Database Management Window</h2>
<p>
The Hash Database Management window is where you can set and update your hash database information. Hash databases are used to identify files that are 'known'.
<ul>
<li>Known good files are those that can be safely ignored. This set of files frequently includes standard OS and application files. </li>
<li>Known bad files are those that should raise awareness. This set will vary depending on the type of investigation, but common examples include contraband images and malware.</li>
</ul>
</p>
<p>Autopsy allows for a single known bad hash database to be set and the <a href="http://www.nsrl.nist.gov">NIST NSRL</a>. Before they can be used, an index of them must exist.
The index can be directly copied in or it can be created within Autopsy. When you select the database from within this window, it will tell you if the index needs to be created. Autopsy
uses the hash database management system from The Sleuth Kit. You can manually create an index using the 'hfind' command line tool.</p>
<p>Note that the NSRL contains hashes of 'known files' that may be good or bad depending on your perspective and investigation type. For example, the existence of a piece of financial software
may be interesting to your investigation and that software could be in the NSRL. Therefore, Autopsy treats files that are found in the NSRL as simplyi 'known' and does not specify good or bad. </p>
<p>To use the NSRL, you must concatenate all of the NSRLFile.txt files together. You can use 'cat' on a Unix system or from within Cygwin to do this.</p>
<p>The 'known bad' hash database can be in the hashkeeper, md5sum, or NSRL format.</p>
<p>Autopsy uses hash databases when the image is added to the case. Each file is hashed and looked up in the configured databases. If the file is found in the NSRL, then it will be marked as
'known' in the case database. If it is found in the known bad hash database, it will be marked as 'known bad' in the case database. </p>
<p>You can see the lookup results in a couple of places. In the <a href="nbdocs:/org/sleuthkit/autopsy/filesearch/docs/open-filesearch.html">File Search</a> data explorer, there is an option to choose the 'known status'. From here, you can do a search to see all 'known bad' files.
From here, you can also choose to ignore all 'known' files that were found in the NSRL. You can also see the status of the file in a column when the file is listed. </p>
<p>Currently, you cannot reprocess a disk image with a new hash database after it has been added to a case.</p>
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,45 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Overview</title>
<link rel="stylesheet" href="nbdocs:/org/netbeans/modules/usersguide/ide.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Overview</h2>
<p>
Autopsy allows you to conduct a digital forensic investigation. It is a graphical interface to The Sleuth Kit and other open source tools. This page outlines the basic concepts of the program. The remainder of the help guide is organized around these concepts.
</p>
<p>All data is organized around the concept of a <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html">case</a>. A case can have one or more disk <a href="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html">images</a> loaded into it.</p>
<p>The main window has three major areas:
<ul>
<li><a href="nbdocs:/org/sleuthkit/autopsy/corecomponents/docs/dataexplorer-about.html">Data Explorers</a> (area 4 in figure below): This area is where you go find major analysis functionality. It allows you to start finding the relevant files.</li>
<li><a href="nbdocs:/org/sleuthkit/autopsy/corecomponents/docs/dataresult-about.html">Result Viewers</a> (area 5 in figure below): This area is where the files and directories that were found from the explorer window can be viewed. There are different formatting options for the files.</li>
<li><a href="nbdocs:/org/sleuthkit/autopsy/corecomponents/docs/datacontent-about.html">Content Viewers</a> (area 6 in figure below): This area is where file content can be viewed after they are selected from the Result Viewer area.</li>
</ul>
</p>
<p>The main take away from this should be that analysis techniques can be found on the left-hand side, the results are always listed in the upper right, and the file contents are displayed in the lower left.
<p>
<img src="Autopsy_overview.png" alt="Autopsy Overview Window" />
</p>
</body>
</html>
<!--
Tip: to create a link which will open in an external web browser, try:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer">
<param name="content" value="http://www.netbeans.org/">
<param name="text" value="<html><u>http://www.netbeans.org/</u></html>">
<param name="textFontSize" value="medium">
<param name="textColor" value="blue">
</object>
To create a link to a help set from another module, you need to know the code name base and path, e.g.:
<a href="nbdocs://org.netbeans.modules.usersguide/org/netbeans/modules/usersguide/configure/configure_options.html">Using the Options Window</a>
(This link will behave sanely if that module is disabled or missing.)
-->

7
Case/manifest.mf Normal file
View File

@ -0,0 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.casemodule/0
OpenIDE-Module-Implementation-Version: 1
OpenIDE-Module-Layer: org/sleuthkit/autopsy/casemodule/layer.xml
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/casemodule/Bundle.properties
OpenIDE-Module-Requires: org.openide.windows.WindowManager, org.netbeans.api.javahelp.Help

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
-->
<project name="org.sleuthkit.autopsy.casemodule-impl" basedir="..">
<fail message="Please build using Ant 1.7.1 or higher.">
<condition>
<not>
<antversion atleast="1.7.1"/>
</not>
</condition>
</fail>
<property file="nbproject/private/suite-private.properties"/>
<property file="nbproject/suite.properties"/>
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
<property file="${suite.dir}/nbproject/platform.properties"/>
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="property"/>
<attribute name="value"/>
<sequential>
<property name="@{property}" value="@{value}"/>
</sequential>
</macrodef>
<property file="${user.properties.file}"/>
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
<condition>
<not>
<contains string="${cluster.path.evaluated}" substring="platform"/>
</not>
</condition>
</fail>
<import file="${harness.dir}/build.xml"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=163956d6
build.xml.script.CRC32=601bc2ba
build.xml.stylesheet.CRC32=a56c6a5b@1.46.2
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=163956d6
nbproject/build-impl.xml.script.CRC32=65e93a36
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.2

View File

@ -0,0 +1,17 @@
cluster.path=\
${nbplatform.active.dir}/platform
disabled.modules=\
org.jdesktop.layout,\
org.netbeans.api.visual,\
org.netbeans.core.execution,\
org.netbeans.core.multiview,\
org.netbeans.libs.jsr223,\
org.netbeans.modules.autoupdate.services,\
org.netbeans.modules.autoupdate.ui,\
org.netbeans.modules.core.kit,\
org.netbeans.modules.favorites,\
org.openide.compat,\
org.openide.execution,\
org.openide.options,\
org.openide.util.enumerations
nbplatform.active=default

View File

@ -0,0 +1,4 @@
javac.source=1.6
javac.compilerargs=-Xlint -Xlint:-serial
javahelp.hs=casemodule-hs.xml
spec.version.base=0.0

141
Case/nbproject/project.xml Normal file
View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>org.sleuthkit.autopsy.casemodule</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>org.jdesktop.beansbinding</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.11.1.121</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.settings</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.26.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.23.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.dialogs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.15.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.47.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.modules</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.17.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.16.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.text</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.30.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.3.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.33.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.corecomponentinterfaces</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0</release-version>
<specification-version>0.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>0.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.logging</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>0.0</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<test-dependencies>
<test-type>
<name>unit</name>
<test-dependency>
<code-name-base>org.netbeans.libs.junit4</code-name-base>
<compile-dependency/>
</test-dependency>
</test-type>
</test-dependencies>
<public-packages>
<package>org.sleuthkit.autopsy.casemodule</package>
</public-packages>
</data>
</configuration>
</project>

View File

@ -0,0 +1 @@
suite.dir=${basedir}/..

View File

@ -0,0 +1,304 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.DialogDisplayer;
import org.openide.WizardDescriptor;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
/**
* The action to add an image to the current Case. This action should be disabled
* on creation and it will be enabled on new case creation or case opened.
*
* @author jantonius
*/
// TODO: need annotation because there's a "Lookup.getDefault().lookup(AddImageAction.class)"
// used in AddImageWizardPanel1 (among other places). It really shouldn't be done like that.
@ServiceProvider(service = AddImageAction.class)
public final class AddImageAction extends CallableSystemAction implements Presenter.Toolbar {
// Keys into the WizardDescriptor properties that pass information between stages of the wizard
// <TYPE>: <DESCRIPTION>
// String: time zone that the image is from
static final String TIMEZONE_PROP = "timeZone";
// String[]: task to clean up the database file if wizard errors/is cancelled after it is created
static final String IMGPATHS_PROP = "imgPaths";
// CleanupTask: task to clean up the database file if wizard errors/is cancelled after it is created
static final String IMAGECLEANUPTASK_PROP = "finalFileCleanup";
// int: the next availble id for a new image
static final String IMAGEID_PROP = "imageId";
// AddImageProcess: the next availble id for a new image
static final String PROCESS_PROP = "process";
private WizardDescriptor wizardDescriptor;
private WizardDescriptor.Iterator<WizardDescriptor> iterator;
private Dialog dialog;
private JButton toolbarButton = new JButton();
/**
* The constructor for AddImageAction class
*/
public AddImageAction() {
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage")); // set the action Name
// set the action for the toolbar button
toolbarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AddImageAction.this.actionPerformed(e);
}
});
this.setEnabled(false); // disable this action class
}
/**
* Pop-up the "Add Image" wizard panel.
*
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(AddImageAction.class);
iterator = new AddImageWizardIterator(this);
wizardDescriptor = new WizardDescriptor(iterator);
wizardDescriptor.setTitle("Add Image");
wizardDescriptor.putProperty(NAME, e);
if (dialog != null) {
dialog.setVisible(false); // hide the old one
}
dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
dialog.setVisible(true);
dialog.toFront();
boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
// @@@ Why don't we commit and revert in the same general area????
if (!cancelled) {
// commit anything
try {
commitImage(wizardDescriptor);
} catch (Exception ex) {
// Log error/display warning
Logger logger = Logger.getLogger(AddImageAction.class.getName());
logger.log(Level.SEVERE, "Error adding image to case.", ex);
}
}
// Do any cleanup that needs to happen (potentially: stopping the
//add-image process, reverting an image)
runCleanupTasks();
}
/**
* Commit the finished AddImageProcess, and cancel the CleanupTask that
* would have reverted it.
* @param settings property set to get AddImageProcess and CleanupTask from
* @throws Exception if commit or adding the image to the case failed
*/
private void commitImage(WizardDescriptor settings) throws Exception {
String[] imgPaths = (String[]) settings.getProperty(AddImageAction.IMGPATHS_PROP);
String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
AddImageProcess process = (AddImageProcess) settings.getProperty(PROCESS_PROP);
try {
long imageId = process.commit();
Case.getCurrentCase().addImage(imgPaths, imageId, timezone);
} finally {
// Can't bail and revert image add after commit, so disable image cleanup
// task
CleanupTask cleanupImage = (CleanupTask) settings.getProperty(IMAGECLEANUPTASK_PROP);
cleanupImage.disable();
}
}
/**
* Closes the current dialog and wizard, and opens a new one. Used in the
* "Add another image" action on the last panel
*/
public void restart() {
// Simulate clicking finish for the current dialog
wizardDescriptor.setValue(WizardDescriptor.FINISH_OPTION);
dialog.setVisible(false);
// let the previous call to AddImageAction.actionPerformed() finish up
// after the wizard, this will run when its it's done
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
actionPerformed(null);
}
});
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)" instead of this method.
*/
@Override
public void performAction() {
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override
public String getName() {
return NbBundle.getMessage(AddImageAction.class, "CTL_AddImage");
}
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
/**
* Returns the toolbar component of this action
*
* @return component the toolbar button
*/
@Override
public Component getToolbarPresenter() {
ImageIcon icon = new ImageIcon(getClass().getResource("addImage-icon.png"));
toolbarButton.setIcon(icon);
return toolbarButton;
}
/**
* Set this action to be enabled/disabled
*
* @param value whether to enable this action or not
*/
@Override
public void setEnabled(boolean value) {
super.setEnabled(value);
toolbarButton.setEnabled(value);
}
/**
* Set the focus to the button of the given name on this wizard dialog.
*
* Note: the name of the buttons that available are "Next >", "< Back",
* "Cancel", and "Finish". If you change the name of any of those buttons,
* use the latest name instead.
*
* @param buttonText the text of the button
*/
public void requestFocusButton(String buttonText) {
// get all buttons on this wizard panel
Object[] wizardButtons = wizardDescriptor.getOptions();
for (int i = 0; i < wizardButtons.length; i++) {
JButton tempButton = (JButton) wizardButtons[i];
if (tempButton.getText().equals(buttonText)) {
tempButton.setDefaultCapable(true);
tempButton.requestFocus();
}
}
}
/**
* Run and clear any cleanup tasks for wizard closing that might be
* registered. This should be run even when the wizard exits cleanly, so
* that no cleanup actions remain the next time the wizard is run.
*/
private void runCleanupTasks() {
cleanupSupport.fireChange();
}
ChangeSupport cleanupSupport = new ChangeSupport(this);
/**
* Instances of this class implement the cleanup() method to run cleanup
* code when the wizard exits.
*
* After enable() has been called on an instance it will run once after the
* wizard closes (on both a cancel and a normal finish).
*
* If disable() is called before the wizard exits, the task will not run.
*/
abstract class CleanupTask implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
// fired by AddImageAction.runCleanupTasks() after the wizard closes
try {
cleanup();
} catch (Exception ex) {
Logger logger = Logger.getLogger(this.getClass().getName());
logger.log(Level.WARNING, "Error cleaning up from wizard.", ex);
} finally {
disable(); // cleanup tasks should only run once.
}
}
/**
* Add task to the enabled list to run when the wizard closes.
*/
public void enable() {
cleanupSupport.addChangeListener(this);
}
/**
* Performs cleanup action when called
* @throws Exception
*/
abstract void cleanup() throws Exception;
/**
* Remove task from the enabled list.
*/
public void disable() {
cleanupSupport.removeChangeListener(this);
}
}
}

View File

@ -0,0 +1,205 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="imgTypeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="10" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="rawSplit" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="rawSingle" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="encase" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="multipleSelectLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="imgPathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="imgPathTextField" pref="415" max="32767" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="imgPathBrowserButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="imgInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="315" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="imgInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
<Component id="imgTypeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rawSingle" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="rawSplit" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="encase" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="imgPathLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="imgPathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="imgPathBrowserButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="multipleSelectLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="26" max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JRadioButton" name="rawSingle">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.rawSingle.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rawSingleActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="10"/>
</AuxValues>
</Component>
<Component class="javax.swing.JRadioButton" name="rawSplit">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.rawSplit.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rawSplitActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="imgTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="encase">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.encase.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="encaseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="imgPathLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgPathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="multipleSelectLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.multipleSelectLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="imgPathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgPathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="10"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="imgPathBrowserButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgPathBrowserButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="imgPathBrowserButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodePost" type="java.lang.String" value="this.imgPathBrowserButton.setDefaultCapable(true);&#xd;&#xa;this.imgPathBrowserButton.requestFocus();"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="imgInfoLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.imgInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="33" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
<Properties>
<Property name="maximumRowCount" type="int" value="30"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="timeZoneLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel1.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,493 @@
/*
* 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.casemodule;
import java.io.File;
import java.util.Calendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import javax.swing.event.DocumentEvent;
import javax.swing.filechooser.FileFilter;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.event.DocumentListener;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
/**
* The "Add Image" wizard panel 1. This class is used to design the "form" of
* the panel 1 for "Add Image" wizard panel.
*
* @author jantonius
*/
final class AddImageVisualPanel1 extends JPanel implements DocumentListener {
private JFileChooser fc = new JFileChooser();
private FileFilter filter;
private final String[] imgExt = {".img", ".dd"};
private final String imgDesc = "Raw Images (*.img, *.dd)";
private GeneralFilter imgFilter = new GeneralFilter(imgExt, imgDesc, false);
private final String[] splitExt = {".*\\.[0-9][0-9][0-9]", ".*\\.[a-z][a-z]"};
private final String splitDesc = "Split Part (*.001, *.002, etc)";
private GeneralFilter splitFilter = new GeneralFilter(splitExt, splitDesc, true);
private final String[] encasExt = {".*\\.e[0-9][0-9]", ".*\\.e[a-z][a-z]"};
private final String encaseDesc = "Encase Images (*.e01, *.eAA)";
private GeneralFilter encaseFilter = new GeneralFilter(encasExt, encaseDesc, true);
private boolean multi = false;
private AddImageWizardPanel1 wizPanel;
/**
* Creates new form AddImageVisualPanel1
* @param wizPanel corresponding WizardPanel to handle logic of wizard step
*/
AddImageVisualPanel1(AddImageWizardPanel1 wizPanel) {
initComponents();
this.wizPanel = wizPanel;
fc.setDragEnabled(multi);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(multi);
fc.addChoosableFileFilter(imgFilter);
filter = imgFilter;
buttonGroup1.add(encase);
buttonGroup1.add(rawSingle);
buttonGroup1.add(rawSplit);
imgPathTextField.getDocument().addDocumentListener(this);
imgPathTextField.setText("");
jLabel1.setText("");
rawSingle.setSelected(true);
rawSplit.setSelected(false);
encase.setSelected(false);
createTimeZoneList();
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "Add Image" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return "Enter Image Information";
}
/**
* Gets the array of image paths from the Image Path Text Field.
*
* @return imagePaths the array of image paths
*/
public String[] getImagePaths() {
String[] imgPath = Case.convertImgPath(imgPathTextField.getText());
if (Case.checkMultiplePathExist(imgPath)) {
return imgPath;
} else {
return new String[0];
}
}
/**
* Gets the type of the image that's selected.
*
* @return imgType the type of the image that selected
*/
public String getImgType() {
if (rawSingle.isSelected()) {
return "Raw Single";
}
if (rawSplit.isSelected()) {
return "Raw Split";
}
if (encase.isSelected()) {
return "EnCase";
} else {
return "Nothing Selected";
}
}
/**
* Gets the time zone that selected on the drop down list.
*
* @return timeZone the time zone that selected
*/
public String getSelectedTimezone() {
String tz = timeZoneComboBox.getSelectedItem().toString();
return tz.substring(tz.indexOf(")") + 2).trim();
}
// add the timeZone list to the timeZoneComboBox
/**
* Creates the drop down list for the time zones and then makes the local
* machine time zones to be selected.
*/
public void createTimeZoneList() {
// load and add all timezone
String[] ids = SimpleTimeZone.getAvailableIDs();
for (String id : ids) {
TimeZone zone = TimeZone.getTimeZone(id);
int offset = zone.getRawOffset() / 1000;
int hour = offset / 3600;
int minutes = (offset % 3600) / 60;
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
/*
DateFormat dfm = new SimpleDateFormat("z");
dfm.setTimeZone(zone);
boolean hasDaylight = zone.useDaylightTime();
String first = dfm.format(new Date(2010, 1, 1));
String second = dfm.format(new Date(2011, 6, 6));
int mid = hour * -1;
String result = first + Integer.toString(mid);
if(hasDaylight){
result = result + second;
}
timeZoneComboBox.addItem(item + " (" + result + ")");
*/
timeZoneComboBox.addItem(item);
}
// get the current timezone
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
int thisOffset = thisTimeZone.getRawOffset() / 1000;
int thisHour = thisOffset / 3600;
int thisMinutes = (thisOffset % 3600) / 60;
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
// set the selected timezone
timeZoneComboBox.setSelectedItem(formatted);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
rawSingle = new javax.swing.JRadioButton();
rawSplit = new javax.swing.JRadioButton();
imgTypeLabel = new javax.swing.JLabel();
encase = new javax.swing.JRadioButton();
imgPathLabel = new javax.swing.JLabel();
multipleSelectLabel = new javax.swing.JLabel();
imgPathTextField = new javax.swing.JTextField();
imgPathBrowserButton = new javax.swing.JButton();
this.imgPathBrowserButton.setDefaultCapable(true);
this.imgPathBrowserButton.requestFocus();
imgInfoLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
timeZoneComboBox = new javax.swing.JComboBox();
timeZoneLabel = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(rawSingle, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSingle.text")); // NOI18N
rawSingle.setRequestFocusEnabled(false);
rawSingle.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rawSingleActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(rawSplit, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSplit.text")); // NOI18N
rawSplit.setRequestFocusEnabled(false);
rawSplit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rawSplitActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(imgTypeLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgTypeLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(encase, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.encase.text")); // NOI18N
encase.setRequestFocusEnabled(false);
encase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
encaseActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(imgPathLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(multipleSelectLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.multipleSelectLabel.text")); // NOI18N
imgPathTextField.setText(org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(imgPathBrowserButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathBrowserButton.text")); // NOI18N
imgPathBrowserButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
imgPathBrowserButtonActionPerformed(evt);
}
});
imgInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
org.openide.awt.Mnemonics.setLocalizedText(imgInfoLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgInfoLabel.text")); // NOI18N
jLabel1.setForeground(new java.awt.Color(255, 0, 51));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.jLabel1.text")); // NOI18N
timeZoneComboBox.setMaximumRowCount(30);
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.timeZoneLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imgTypeLabel)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(rawSplit)
.addComponent(rawSingle)
.addComponent(encase)))
.addComponent(multipleSelectLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(imgPathLabel)
.addGap(18, 18, 18)
.addComponent(imgPathTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 415, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imgPathBrowserButton))
.addComponent(imgInfoLabel)
.addComponent(jLabel1)
.addGroup(layout.createSequentialGroup()
.addComponent(timeZoneLabel)
.addGap(10, 10, 10)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 315, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(imgInfoLabel)
.addGap(19, 19, 19)
.addComponent(imgTypeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rawSingle)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rawSplit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(encase)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(imgPathLabel)
.addComponent(imgPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(imgPathBrowserButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(multipleSelectLabel)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(timeZoneLabel)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 26, Short.MAX_VALUE)
.addComponent(jLabel1)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
/**
* When the "rawSingle" radio button is selected.
*
* @param evt the action event
*/
private void rawSingleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSingleActionPerformed
rawSingle.setSelected(true);
rawSplit.setSelected(false);
encase.setSelected(false);
multipleSelectLabel.setText("Single Image: Multiple Select Disabled");
filter = imgFilter;
multi = false;
this.updateUI(null);
}//GEN-LAST:event_rawSingleActionPerformed
/**
* When the "rawSplit" radio button is selected.
*
* @param evt the action event
*/
private void rawSplitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSplitActionPerformed
rawSingle.setSelected(false);
rawSplit.setSelected(true);
encase.setSelected(false);
multipleSelectLabel.setText("Split Image: Multiple Select Enabled. Use Ctrl, Shift, "
+ "or Drag to select multiple image parts");
filter = splitFilter;
multi = true;
updateUI(null);
}//GEN-LAST:event_rawSplitActionPerformed
/**
* When the "encase" radio button is selected.
*
* @param evt the action event
*/
private void encaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_encaseActionPerformed
rawSingle.setSelected(false);
rawSplit.setSelected(false);
encase.setSelected(true);
multipleSelectLabel.setText("EnCase Image: Multiple Select Enabled. Use Ctrl, Shift, "
+ "or Drag to select multiple image parts");
filter = encaseFilter;
multi = true;
updateUI(null);
}//GEN-LAST:event_encaseActionPerformed
/**
* When the "Browse" button is pressed, open the file chooser window to
* select the images.
*
* @param evt the action event
*/
private void imgPathBrowserButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_imgPathBrowserButtonActionPerformed
fc.resetChoosableFileFilters();
fc.addChoosableFileFilter(filter);
fc.setFileFilter(filter);
fc.setMultiSelectionEnabled(multi);
fc.setDragEnabled(multi);
// set the current directory of the FileChooser if the ImagePath Field is valid
File currentDir = new File(imgPathTextField.getText());
if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir);
}
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
File[] files = fc.getSelectedFiles();
String path = "";
if (multi) {
for (File file : files) {
path = path + "\"" + file.getPath() + "\" ";
}
imgPathTextField.setText(path);
} else {
path = fc.getSelectedFile().getPath();
imgPathTextField.setText(path);
}
}
}//GEN-LAST:event_imgPathBrowserButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JRadioButton encase;
private javax.swing.JLabel imgInfoLabel;
private javax.swing.JButton imgPathBrowserButton;
private javax.swing.JLabel imgPathLabel;
private static javax.swing.JTextField imgPathTextField;
private javax.swing.JLabel imgTypeLabel;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel multipleSelectLabel;
private static javax.swing.JRadioButton rawSingle;
private javax.swing.JRadioButton rawSplit;
private javax.swing.JComboBox timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel;
// End of variables declaration//GEN-END:variables
/**
* Gives notification that there was an insert into the document. The
* range given by the DocumentEvent bounds the freshly inserted region.
*
* @param e the document event
*/
@Override
public void insertUpdate(DocumentEvent e) {
updateUI(e);
}
/**
* Gives notification that a portion of the document has been
* removed. The range is given in terms of what the view last
* saw (that is, before updating sticky positions).
*
* @param e the document event
*/
@Override
public void removeUpdate(DocumentEvent e) {
updateUI(e);
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
@Override
public void changedUpdate(DocumentEvent e) {
updateUI(e);
}
/**
* The "listener" that updates the UI of this panel based on the changes of
* fields on this panel. This is also the method to check whether all the
* fields on this panel are correctly filled and decides whether to enable
* the "Next" button or not.
*
* @param e the document event
*/
public void updateUI(DocumentEvent e) {
String[] imgPath = Case.convertImgPath(imgPathTextField.getText());
boolean isExist = Case.checkMultiplePathExist(imgPath);
File imgFile = new File(imgPath[0]);
// check if the given paths exist and those are paths to image files
boolean isImagePath = true;
for (int i = 0; i < imgPath.length; i++) {
File tempImgFile = new File(imgPath[i]);
isImagePath = isImagePath && tempImgFile.exists() && !tempImgFile.isDirectory()
&& (imgFilter.accept(tempImgFile) || splitFilter.accept(tempImgFile)
|| encaseFilter.accept(tempImgFile));
}
if (isImagePath) {
Case currentCase = Case.getCurrentCase();
File dbFile = new File(currentCase.getCaseDirectory() + File.separator + imgFile.getName() + ".db");
if (dbFile.exists()) {
String dbExist = "This database already exists. Do you want to overwrite the database?";
NotifyDescriptor d = new NotifyDescriptor.Confirmation(dbExist, "Warning: Overwrite Database", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
isExist = false;
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
isExist = dbFile.delete();
if (!isExist) {
jLabel1.setText("*Database for this image is already created and it can't be deleted because it's being used.");
}
}
if (res != null && res == DialogDescriptor.NO_OPTION) {
jLabel1.setText("*Database for this image exist. Either delete it or select another image.");
}
}
} else {
isExist = false;
}
if (isExist) {
jLabel1.setText("");
}
this.wizPanel.enableNextButton(isExist);
}
}

View File

@ -0,0 +1,122 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="crDbLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="crDbButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="189" pref="189" max="189" attributes="0"/>
</Group>
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="crDbProgressBar" alignment="0" pref="292" max="32767" attributes="1"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="progressLabel" pref="272" max="32767" attributes="0"/>
</Group>
<Component id="jLabel1" alignment="0" min="-2" pref="552" max="-2" attributes="1"/>
<Component id="lookupFilesCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="crDbLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="lookupFilesCheckBox" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="80" max="-2" attributes="0"/>
<Component id="progressLabel" min="-2" pref="12" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="crDbButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="30" max="-2" attributes="0"/>
<Component id="jLabel5" min="-2" pref="14" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="crDbProgressBar" min="-2" pref="24" max="-2" attributes="1"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JProgressBar" name="crDbProgressBar">
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.jLabel5.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="crDbLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.crDbLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="progressLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.progressLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="crDbButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.crDbButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="crDbButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="lookupFilesCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel2.lookupFilesCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,181 @@
/*
* 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.casemodule;
import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
/**
* The "Add Image" wizard panel 2. Provides checkbox to enable indexing, button
* to start process, and progress bar.
*/
final class AddImageVisualPanel2 extends JPanel {
/** Creates new form AddImageVisualPanel2 */
AddImageVisualPanel2() {
initComponents();
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "Add Image" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return "Create Database";
}
public JButton getCrDbButton() {
return this.crDbButton;
}
public JProgressBar getCrDbProgressBar() {
return this.crDbProgressBar;
}
public JLabel getProgressLabel() {
return this.progressLabel;
}
public JCheckBox getLookupFilesCheckbox() {
return this.lookupFilesCheckBox;
}
/**
* Changes the progress bar text and color.
*
* @param text the text to be shown
* @param value the current value of the progress bar
* @param color the color of the progress bar text
*/
public void changeProgressBarTextAndColor(String text, int value, Color color) {
progressLabel.setText(text);
progressLabel.setForeground(color);
crDbProgressBar.setValue(value);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
crDbProgressBar = new javax.swing.JProgressBar();
jLabel5 = new javax.swing.JLabel();
crDbLabel = new javax.swing.JLabel();
progressLabel = new javax.swing.JLabel();
crDbButton = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
lookupFilesCheckBox = new javax.swing.JCheckBox();
org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.jLabel5.text")); // NOI18N
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
org.openide.awt.Mnemonics.setLocalizedText(crDbLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.crDbLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.progressLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(crDbButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.crDbButton.text")); // NOI18N
crDbButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
crDbButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.jLabel1.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lookupFilesCheckBox, org.openide.util.NbBundle.getMessage(AddImageVisualPanel2.class, "AddImageVisualPanel2.lookupFilesCheckBox.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(crDbLabel)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(crDbButton)
.addGap(189, 189, 189))
.addComponent(jLabel5)
.addComponent(crDbProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 272, Short.MAX_VALUE))
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 552, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(lookupFilesCheckBox)
.addContainerGap(407, Short.MAX_VALUE))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(crDbLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lookupFilesCheckBox)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(80, 80, 80)
.addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(crDbButton)
.addGap(30, 30, 30)
.addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(crDbProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
/**
* When the "Create Database" button is press. It starts the database
* creation process, disables the "Create Database" and "Back" button, and
* sets the progress bar text.
*
* @param evt the action event
*/
private void crDbButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_crDbButtonActionPerformed
}//GEN-LAST:event_crDbButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton crDbButton;
private javax.swing.JLabel crDbLabel;
private javax.swing.JProgressBar crDbProgressBar;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel5;
private javax.swing.JCheckBox lookupFilesCheckBox;
private javax.swing.JLabel progressLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,73 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="addImgButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="crDbLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" pref="549" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="crDbLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="addImgButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="54" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="addImgButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel3.addImgButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addImgButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="crDbLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel3.crDbLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageVisualPanel3.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,114 @@
/*
* 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.casemodule;
import javax.swing.JPanel;
import org.openide.util.Lookup;
/**
* The "Add Image" wizard panel 3. This class is used to design the "form" of
* the panel 3 for "Add Image" wizard panel.
*
* @author jantonius
*/
final class AddImageVisualPanel3 extends JPanel {
/** Creates new form AddImageVisualPanel3 */
AddImageVisualPanel3() {
initComponents();
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "Add Image" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return "Done";
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
addImgButton = new javax.swing.JButton();
crDbLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(addImgButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel3.class, "AddImageVisualPanel3.addImgButton.text")); // NOI18N
addImgButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addImgButtonActionPerformed(evt);
}
});
crDbLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(crDbLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel3.class, "AddImageVisualPanel3.crDbLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel3.class, "AddImageVisualPanel3.jLabel1.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(addImgButton)
.addComponent(crDbLabel)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 549, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(crDbLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addComponent(addImgButton)
.addContainerGap(54, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
/**
*
*
* @param evt the action event
*/
private void addImgButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addImgButtonActionPerformed
// restart the wizard
AddImageAction act = Lookup.getDefault().lookup(AddImageAction.class);
act.restart();
}//GEN-LAST:event_addImgButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addImgButton;
private javax.swing.JLabel crDbLabel;
private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,166 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import javax.swing.JComponent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
/**
* The iterator class for the "Add Image" wizard panel. This class is used to
* iterate on the sequence of panels of the "Add Image" wizard panel.
*/
class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
private int index = 0;
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
private AddImageAction action;
AddImageWizardIterator(AddImageAction action) {
this.action = action;
}
/**
* Initialize panels representing individual wizard's steps and sets
* various properties for them influencing wizard appearance.
*/
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
if (panels == null) {
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
panels.add(new AddImageWizardPanel1());
panels.add(new AddImageWizardPanel2(action));
panels.add(new AddImageWizardPanel3());
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
// Default step name to component name of panel.
steps[i] = c.getName();
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
// Sets step number of a component
// TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*:
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
// Sets steps names for a panel
jc.putClientProperty("WizardPanel_contentData", steps);
// Turn on subtitle creation on each step
jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
// Show steps on the left side with the image on the background
jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
// Turn on numbering of all steps
jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
}
}
}
return panels;
}
/**
* Returns the index of the current panel.
* Note: 0 = panel 1, 1 = panel 2, etc
*
* @return index the current panel index
*/
public int getIndex() {
return index;
}
/**
* Gets the current panel.
*
* @return panel the current panel
*/
@Override
public WizardDescriptor.Panel<WizardDescriptor> current() {
if (panels != null) {
return panels.get(index);
} else {
return getPanels().get(index);
}
}
/**
* Gets the name of the current panel.
*
* @return name the name of the current panel
*/
@Override
public String name() {
return "Step " + Integer.toString(index + 1) + " of " + getPanels().size();
}
/**
* Tests whether there is a next panel.
*
* @return boolean true if it has next panel, false if not
*/
@Override
public boolean hasNext() {
return index < getPanels().size() - 1;
}
/**
* Tests whether there is a previous panel.
*
* @return boolean true if it has previous panel, false if not
*/
@Override
// disable the previous button on all panels
public boolean hasPrevious() {
return index > 0;
}
/**
* Moves to the next panel. I.e. increment its index, need not actually
* change any GUI itself.
*/
@Override
public void nextPanel() {
if (!hasNext()) {
throw new NoSuchElementException();
}
index++;
}
/**
* Moves to the previous panel. I.e. decrement its index, need not actually
* change any GUI itself.
*/
@Override
public void previousPanel() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
index--;
}
// If nothing unusual changes in the middle of the wizard, simply:
@Override
public void addChangeListener(ChangeListener l) {
}
@Override
public void removeChangeListener(ChangeListener l) {
}
}

View File

@ -0,0 +1,189 @@
/*
* 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.casemodule;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
/**
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
* to add to Case, and pick the time zone.
*/
class AddImageWizardPanel1 implements WizardDescriptor.Panel<WizardDescriptor>, PropertyChangeListener {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private AddImageVisualPanel1 component;
private boolean isNextEnable = false;
/**
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return component the UI component of this wizard panel
*/
@Override
public AddImageVisualPanel1 getComponent() {
if (component == null) {
component = new AddImageVisualPanel1(this);
}
component.addPropertyChangeListener(this);
return component;
}
/**
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
* Tests whether the panel is finished and it is safe to proceed to the next
* one. If the panel is valid, the "Next" button will be enabled.
*
* @return boolean true if all the fields are correctly filled, false otherwise
*/
@Override
public boolean isValid() {
// set the focus to the next button of the wizard dialog if it's enabled
if(isNextEnable){
Lookup.getDefault().lookup(AddImageAction.class).requestFocusButton("Next >");
}
return isNextEnable;
}
/**
* Enable the "Next" button and fireChangeEvent to update the GUI
*
* @param isEnabled true if next button can be enabled, false otherwise
*/
public void enableNextButton(boolean isEnabled){
isNextEnable = isEnabled;
fireChangeEvent();
}
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/**
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
/**
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
/**
* This method is auto-generated. It seems that this method is used to listen
* to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
*s
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
}
/**
* Provides the wizard panel with the opportunity to update the settings
* with its current customized state. Rather than updating its settings
* with every change in the GUI, it should collect them, and then only save
* them when requested to by this method. This method can be called multiple
* times on one instance of WizardDescriptor.Panel.
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
settings.putProperty(AddImageAction.IMGPATHS_PROP, getComponent().getImagePaths());
settings.putProperty(AddImageAction.TIMEZONE_PROP, getComponent().getSelectedTimezone()); // store the timezone
}
/**
* The "listener" for any property change in this panel. Any property changes
* will invoke the "fireChangeEvent()" method.
*
* @param evt the property change event
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
fireChangeEvent();
}
}

View File

@ -0,0 +1,379 @@
/*
* 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.casemodule;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.hashdatabase.HashDbSettings;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
import org.sleuthkit.datamodel.TskException;
/**
* The "Add Image" wizard panel2. Handles processing the image in a worker
* thread, and any errors that may occur during the add process.
*/
class AddImageWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
// the paths of the image files to be added
private String[] imgPaths;
// the time zone where the image is added
private String timeZone;
// paths to any set hash lookup databases (can be null)
private String NSRLPath, knownBadPath;
// task that will clean up the created database file if the wizard is cancelled before it finishes
private AddImageAction.CleanupTask cleanupImage; // initialized to null in readSettings()
// flag to control the availiablity of next action
private boolean imgAdded; // initalized to false in readSettings()
private AddImageProcess process;
private AddImgTask addImageTask;
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private AddImageVisualPanel2 component;
private AddImageAction action;
AddImageWizardPanel2(AddImageAction action) {
this.action = action;
}
/**
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return component the UI component of this wizard panel
*/
@Override
public AddImageVisualPanel2 getComponent() {
if (component == null) {
component = new AddImageVisualPanel2();
component.getCrDbButton().addActionListener(new CrDbButtonListener());
}
return component;
}
/**
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
}
/**
* Tests whether the panel is finished and it is safe to proceed to the next
* one. If the panel is valid, the "Next" button will be enabled.
*
* @return boolean true if can proceed to the next one, false otherwise
*/
@Override
public boolean isValid() {
// set the focus to the next button of the wizard dialog if it's enabled
if (imgAdded) {
Lookup.getDefault().lookup(AddImageAction.class).requestFocusButton("Next >");
}
return imgAdded;
}
class CrDbButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
startAddImage();
}
}
/**
* Creates the database and adds the image to the XML configuration file.
*
*/
private void startAddImage() {
component.getCrDbButton().setEnabled(false);
component.getCrDbProgressBar().setIndeterminate(true);
component.changeProgressBarTextAndColor("*Adding the image may take some time for large images.", 0, Color.black);
addImageTask = new AddImgTask();
addImageTask.execute();
}
/**
* Sets the isDbCreated variable in this class and also invoke
* fireChangeEvent() method.
*
* @param created whether the database already created or not
*/
private void setDbCreated(Boolean created) {
imgAdded = created;
fireChangeEvent();
}
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/**
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
/**
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
/**
* This method is auto-generated. It seems that this method is used to listen
* to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
/**
* Load the image locations from the WizardDescriptor settings object, and
* the
*
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
cleanupImage = null;
imgAdded = false;
imgPaths = (String[]) settings.getProperty(AddImageAction.IMGPATHS_PROP);
timeZone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
// If the user went back after the image was processed, it will be replaced so its cleanup task should be executed & removed
AddImageAction.CleanupTask oldImageCleanup = (AddImageAction.CleanupTask) settings.getProperty(AddImageAction.IMAGECLEANUPTASK_PROP);
if (oldImageCleanup != null) {
try {
oldImageCleanup.cleanup();
} catch (Exception ex) {
Logger logger = Logger.getLogger(AddImageWizardPanel2.class.getName());
logger.log(Level.WARNING, "Error removing previously added image", ex);
} finally {
oldImageCleanup.disable();
}
}
component.changeProgressBarTextAndColor("", 0, Color.black);
component.getCrDbButton().setEnabled(true);
// Load hash database settings
this.NSRLPath = null;
this.knownBadPath = null;
try {
HashDbSettings hashDbs = Autopsy.getHashDbSettings();
this.NSRLPath = hashDbs.getNSRLDatabasePath();
this.knownBadPath = hashDbs.getKnownBadDatabasePath();
} catch (IOException ex) {
Log.get(AddImageWizardPanel2.class).log(Level.WARNING, "Couldn't get hash database settings.", ex);
}
JCheckBox lookupFilesCheckbox = component.getLookupFilesCheckbox();
lookupFilesCheckbox.setSelected(false);
lookupFilesCheckbox.setEnabled(this.NSRLPath != null || this.knownBadPath != null);
}
/**
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
// Store process so it can be committed if wizard finishes
settings.putProperty(AddImageAction.PROCESS_PROP, process);
// Need to make the cleanup accessible to the finished wizard so it can
// be cancelled if all goes well, and availble if we return to this
// panel so the the previously added image can be reverted
settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, cleanupImage);
}
/**
* Thread that will make the JNI call to ingest the image.
*/
private class AddImgTask extends SwingWorker<Integer, Integer> {
private JProgressBar progressBar;
private JCheckBox lookupFilesCheckbox;
private Case currentCase;
// true if the process was requested to stop
private boolean interrupted = false;
protected AddImgTask() {
this.progressBar = getComponent().getCrDbProgressBar();
this.lookupFilesCheckbox = getComponent().getLookupFilesCheckbox();
currentCase = Case.getCurrentCase();
}
/**
* Starts the addImage process, but does not commit the results.
*
* @return
* @throws Exception
*/
@Override
protected Integer doInBackground() throws Exception {
this.setProgress(0);
// Add a cleanup task to interupt the backgroud process if the
// wizard exits while the background process is running.
AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() {
@Override
void cleanup() throws Exception {
addImageTask.interrupt();
}
};
SleuthkitCase skCase = currentCase.getSleuthkitCase();
skCase.clearLookupDatabases();
if (lookupFilesCheckbox.isSelected()) {
if (NSRLPath != null) {
skCase.setNSRLDatabase(NSRLPath);
}
if (knownBadPath != null) {
skCase.setKnownBadDatabase(knownBadPath);
}
}
try {
process = currentCase.makeAddImageProcess(Case.convertTimeZone(timeZone));
cancelledWhileRunning.enable();
process.run(imgPaths);
} catch (TskException ex) {
throw ex;
} finally {
// process is over, doesn't need to be dealt with if cancel happens
cancelledWhileRunning.disable();
}
this.setProgress(100);
return 0;
}
/**
*
* (called by EventDispatch Thread after doInBackground finishes)
*/
@Override
protected void done() {
progressBar.setIndeterminate(false);
// attempt actions that might fail and force the process to stop
try {
// get() will throw any expetions that were thrown in the background task
get();
if (interrupted) {
process.revert();
return;
}
// When everything happens without an error:
// the add-image process needs to be reverted if the wizard doesn't finish
cleanupImage = action.new CleanupTask() {
@Override
void cleanup() throws Exception {
process.revert();
}
};
cleanupImage.enable();
getComponent().changeProgressBarTextAndColor("*Image added.", 100, Color.black); // complete progress bar
// Get attention for the process finish
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
SwingUtilities.getWindowAncestor(getComponent()).toFront();
setDbCreated(true);
} catch (Exception ex) {
getComponent().changeProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message
// Log error/display warning
Logger logger = Logger.getLogger(AddImgTask.class.getName());
logger.log(Level.SEVERE, "Error adding image to case", ex);
}
}
void interrupt() throws Exception {
interrupted = true;
try {
process.stop();
} catch (TskException ex) {
throw new Exception("Error stopping add-image process.", ex);
}
}
}
}

View File

@ -0,0 +1,157 @@
/*
* 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.casemodule;
import java.awt.Component;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
/**
* The "Add Image" wizard panel3. No major functionality, just presents the
* options to finish/cancel image-add or to add another image.
*/
class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private Component component;
/**
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return component the UI component of this wizard panel
*/
@Override
public Component getComponent() {
if (component == null) {
component = new AddImageVisualPanel3();
}
return component;
}
/**
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
* Tests whether the panel is finished. If the panel is valid, the "Finish"
* button will be enabled.
*
* @return true the finish button should be always enabled at this point
*/
@Override
public boolean isValid() {
// If it is always OK to press Next or Finish, then:
return true;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
}
/**
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener l) {
}
/**
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener l) {
}
/*
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
*/
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
*
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
}
/**
* Provides the wizard panel with the opportunity to update the settings
* with its current customized state. Rather than updating its settings
* with every change in the GUI, it should collect them, and then only save
* them when requested to by this method. This method can be called multiple
* times on one instance of WizardDescriptor.Panel.
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.casemodule;
import java.io.File;
import java.io.IOException;
import org.sleuthkit.autopsy.hashdatabase.HashDbSettings;
import org.sleuthkit.datamodel.SleuthkitJNI;
/**
* Class to consolidate application-wide settings.
*/
public class Autopsy {
private final static String propFilePath = System.getProperty("netbeans.user") + File.separator + "autopsy.properties";
private static boolean verboseLogging = false;
/**
* Gets the property file where the user properties such as Recent Cases
* and selected Hash Databases are stored.
* @return A new file handle
*/
public static File getPropertyFile() {
return new File(propFilePath);
}
/**
* Get the hash database settings as read from the property file.
* @return A new hash database settings object.
* @throws IOException if the property file can't be found
*/
public static HashDbSettings getHashDbSettings() throws IOException {
return new HashDbSettings(getPropertyFile());
}
/**
* Activate verbose logging for Sleuth Kit
*/
public static void startVerboseLogging() {
verboseLogging = true;
String logPath = System.getProperty("netbeans.user") + File.separator + "sleuthkit.txt";
SleuthkitJNI.startVerboseLogging(logPath);
}
/**
* Checks if verbose logging has been enabled.
* @return true if verbose logging has been enabled.
*/
public static boolean verboseLoggingIsSet() {
return verboseLogging;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -0,0 +1,115 @@
CTL_AddImage=Add Image...
CTL_CaseAction=Case
CTL_CaseCloseAct=Close Case
CTL_CaseNewAction=New Case...
CTL_CaseOpenActionOld=Open Case(old)...
CTL_CasePropertiesAction=Case Properties...
CTL_CaseTopComponent=Case Window
CTL_NewCaseAct=New Case(Old)...
CTL_OpenAction=Open Case...
CTL_RecentCases=Recent Cases
CTL_CaseDeleteAction=Delete Case
CTL_SaveCaseAction=Save Case
CTL_testAction=test
CTL_testTopComponent=test Window
HINT_CaseTopComponent=This is a Case window
HINT_testTopComponent=This is a test window
Menu/File/org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow=
Menu/File/org-sleuthkit-autopsy-casemodule-OpenAction.shadow=Open Case
OpenIDE-Module-Name=Case
CaseVisualPanel1.jLabel1.text=Name
CaseVisualPanel1.jLabel2.text=Image Path:
CaseVisualPanel1.jLabel3.text=Database Path:
CaseTopComponent.jLabel1.text=Name
CaseVisualPanel1.NameField.text=
CaseVisualPanel1.ImgPath.text=
CaseVisualPanel1.DbPath.text=
CaseTopComponent.jLabel2.text=Image Path
CaseTopComponent.jLabel3.text=DB Path
CaseVisualPanel1.ImgPathBrowserButton.text=Browse
CaseVisualPanel1.DbPathBrowserButton.text=Browse
NewCaseVisualPanel1.jLabel1.text=Name
NewCaseVisualPanel1.jTextField1.text=
NewCaseVisualPanel1.jLabel2.text=Image Type:
NewCaseVisualPanel1.jRadioButton1.text=Raw Single .img .dd
NewCaseVisualPanel1.jRadioButton2.text=Raw Split .001 .002 etc
NewCaseVisualPanel1.jRadioButton3.text=Encase .e01
NewCaseVisualPanel1.nameLabel.text_1=Name
NewCaseVisualPanel1.NameField.text_1=
NewCaseVisualPanel1.TypeLabel.text_1=Image Type:
NewCaseVisualPanel1.rawSingleRadio.text_1=Raw Single .img .dd
NewCaseVisualPanel1.rawSplitRadio.text_1=Raw Split .001 .002 etc
NewCaseVisualPanel1.encaseRadio.text_1=EnCase .e01
NewCaseVisualPanel2.jLabel1.text=Image Path:
NewCaseVisualPanel2.jLabel2.text=DataBase Path:
NewCaseVisualPanel2.descriptionText.text=variable text
NewCaseVisualPanel2.ImgBrowserButton.text=Browse
NewCaseVisualPanel2.DcBrowserButton.text=Browse
NewCaseVisualPanel2.ImagePathField.text=
NewCaseVisualPanel2.DbPathField.text=
CaseVisualPanel1.jLabel4.text=Image Type:
CaseVisualPanel1.rawSingle.text=Raw Single .img .dd
CaseVisualPanel1.rawSplit.text=Raw Split .001 .002 etc
CaseVisualPanel1.encase.text=EnCase .e01 .e02 etc
CaseVisualPanel1.multipleSelectLabel.text=Single Image: Multiple Select Disabled
CaseVisualPanel1.jLabel5.text=If a database has not already been loaded / created for the chosen image use this button: (could take a few minutes)
CaseVisualPanel1.ProgressLabel.text=
CaseVisualPanel1.createDbButton.text=Create Database
NewCaseVisualPanel1.jLabel1.text_1=Enter New Case Information:
NewCaseVisualPanel1.caseNameLabel.text_1=Case Name:
NewCaseVisualPanel1.caseDirLabel.text=Base Directory:
NewCaseVisualPanel1.caseDirBrowseButton.text=Browse
NewCaseVisualPanel1.caseNameTextField.text_1=
NewCaseVisualPanel1.jLabel2.text_1=Case data will be stored in the following directory:
NewCaseVisualPanel1.caseParentDirTextField.text=
NewCaseVisualPanel1.caseDirTextField.text_1=
CasePropertiesForm.caseDirLabel.text=Case Directory:
CasePropertiesForm.crDateLabel.text=Created Date:
CasePropertiesForm.caseNameLabel.text=Case Name:
CasePropertiesForm.crDateTextField.text=
CasePropertiesForm.caseNameTextField.text=
CasePropertiesForm.updateCaseNameButton.text=Update
CasePropertiesForm.casePropLabel.text=Case Information
CasePropertiesForm.genInfoLabel.text=General Information
CasePropertiesForm.imgInfoLabel.text=Images Information
CasePropertiesForm.OKButton.text=OK
CasePropertiesForm.deleteCaseButton.text=Delete Case
CueBannerPanel.autopsyLogo.text=
CueBannerPanel.createNewLabel.text=Create New Case
CueBannerPanel.autopsyLabel.text=Autopsy
CueBannerPanel.welcomeLabel.text=Welcome to
CueBannerPanel.openLabel.text=Open Existing Case
CueBannerPanel.startupCheckBox.text=Don't show on startup again
CueBannerPanel.closeButton.text=Close
CueBannerPanel.openRecentLabel.text=Open Recent Case
CueBannerPanel.newCaseButton.text=
CueBannerPanel.openCaseButton.text=
CueBannerPanel.openRecentButton.text=
OpenRecentCasePanel.cancelButton.text=Cancel
OpenRecentCasePanel.jLabel1.text=Recent Cases
AddImageVisualPanel1.imgInfoLabel.text=Enter Disk Image Information:
AddImageVisualPanel2.crDbLabel.text=Adding Image
AddImageVisualPanel2.jLabel5.text=Processing Image and Adding to Database :
AddImageVisualPanel2.crDbButton.text=Process Image
AddImageVisualPanel2.progressLabel.text=
AddImageVisualPanel2.jLabel1.text=<html> We will now analyze the disk image to extract volume and file system data and populate a local database. This may <br>take a while on large images. </html>
AddImageVisualPanel3.addImgButton.text=Add Another Image
AddImageVisualPanel3.crDbLabel.text=Finish or Add More Images
AddImageVisualPanel3.jLabel1.text=Image successfully processed and added to the case. You can add another image or return to the case.
AddImageVisualPanel1.jLabel1.text=
AddImageVisualPanel1.timeZoneLabel.text=Please select your timezone:
AddImageVisualPanel1.rawSingle.text=Raw Single (*.img, *.dd, etc)
AddImageVisualPanel1.rawSplit.text=Raw Split (*.001, *.002, *.aa, *.ab, etc)
AddImageVisualPanel1.imgTypeLabel.text=Image Type:
AddImageVisualPanel1.multipleSelectLabel.text=Single Image: Multiple Select Disabled
AddImageVisualPanel1.imgPathTextField.text=
AddImageVisualPanel1.encase.text=EnCase (*.e01, *.e02, etc)
AddImageVisualPanel1.imgPathLabel.text=Image Path:
AddImageVisualPanel1.imgPathBrowserButton.text=Browse
NewJPanel.jLabel1.text=
NewJPanel.jLabel2.text=NSRL Index
NewJPanel.jLabel5.text=The NSRL index is used to idenify "known" files.
NewJPanel.jFormattedTextField1.text=jFormattedTextField1
NewJPanel.jButton1.text=Rename
NewJPanel.jLabel4.text=Database:
AddImageVisualPanel2.lookupFilesCheckBox.text=Lookup files in hash databases

View File

@ -0,0 +1,232 @@
/*
* 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.casemodule;
/**
* @author jantonius
*
* Taken from: http://tips4java.wordpress.com/2009/07/12/table-button-column/
* Note: everything is the same, except I edited the buttonName
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
/**
* The ButtonColumn class provides a renderer and an editor that looks like a
* JButton. The renderer and editor will then be used for a specified column
* in the table. The TableModel will contain the String to be displayed on
* the button.
*
* The button can be invoked by a mouse click or by pressing the space bar
* when the cell has focus. Optionally a mnemonic can be set to invoke the
* button. When the button is invoked the provided Action is invoked. The
* source of the Action will be the table. The action command will contain
* the model row number of the button that was clicked.
*
*/
class ButtonColumn extends AbstractCellEditor
implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener
{
private JTable table;
private Action action;
private int mnemonic;
private Border originalBorder;
private Border focusBorder;
private JButton renderButton;
private JButton editButton;
private String text;
private boolean isButtonColumnEditor;
String buttonName;
/**
* Create the ButtonColumn to be used as a renderer and editor. The
* renderer and editor will automatically be installed on the TableColumn
* of the specified column.
*
* @param table the table containing the button renderer/editor
* @param action the Action to be invoked when the button is invoked
* @param column the column to which the button renderer/editor is added
* @param buttonName text displayed on the button
*/
ButtonColumn(JTable table, Action action, int column, String buttonName)
{
this.table = table;
this.action = action;
this.buttonName = buttonName;
renderButton = new JButton();
editButton = new JButton();
editButton.setFocusPainted( false );
editButton.addActionListener( this );
originalBorder = editButton.getBorder();
setFocusBorder( new LineBorder(Color.BLUE) );
TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(column).setCellRenderer( this );
columnModel.getColumn(column).setCellEditor( this );
table.addMouseListener( this );
}
/**
* Get foreground color of the button when the cell has focus
*
* @return the foreground color
*/
public Border getFocusBorder()
{
return focusBorder;
}
/**
* The foreground color of the button when the cell has focus
*
* @param focusBorder the foreground color
*/
public void setFocusBorder(Border focusBorder)
{
this.focusBorder = focusBorder;
editButton.setBorder( focusBorder );
}
public int getMnemonic()
{
return mnemonic;
}
/**
* The mnemonic to activate the button when the cell has focus
*
* @param mnemonic the mnemonic
*/
public void setMnemonic(int mnemonic)
{
this.mnemonic = mnemonic;
renderButton.setMnemonic(mnemonic);
editButton.setMnemonic(mnemonic);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
text = (value == null) ? "" : value.toString();
editButton.setText( text );
return editButton;
}
@Override
public Object getCellEditorValue()
{
return text;
}
//
// Implement TableCellRenderer interface
//
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (isSelected)
{
renderButton.setForeground(table.getSelectionForeground());
renderButton.setBackground(table.getSelectionBackground());
}
else
{
renderButton.setForeground(table.getForeground());
renderButton.setBackground(UIManager.getColor("Button.background"));
}
if (hasFocus)
{
renderButton.setBorder( focusBorder );
}
else
{
renderButton.setBorder( originalBorder );
}
//renderButton.setText( (value == null) ? "" : value.toString() );
renderButton.setText(buttonName);
return renderButton;
}
//
// Implement ActionListener interface
//
/*
* The button has been pressed. Stop editing and invoke the custom Action
*/
@Override
public void actionPerformed(ActionEvent e)
{
int row = table.convertRowIndexToModel( table.getEditingRow() );
fireEditingStopped();
// Invoke the Action
ActionEvent event = new ActionEvent(
table,
ActionEvent.ACTION_PERFORMED,
"" + row);
action.actionPerformed(event);
}
//
// Implement MouseListener interface
//
/*
* When the mouse is pressed the editor is invoked. If you then then drag
* the mouse to another cell before releasing it, the editor is still
* active. Make sure editing is stopped when the mouse is released.
*/
@Override
public void mousePressed(MouseEvent e)
{
if (table.isEditing()
&& table.getCellEditor() == this)
isButtonColumnEditor = true;
}
@Override
public void mouseReleased(MouseEvent e)
{
if (isButtonColumnEditor
&& table.isEditing())
table.getCellEditor().stopCellEditing();
isButtonColumnEditor = false;
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}

View File

@ -0,0 +1,852 @@
/*
* 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.casemodule;
import java.awt.Frame;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.Lookup;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.*;
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
/**
* Class to store the case information
*/
public class Case {
// change the CTL_MainWindow_Title in Bundle.properties as well if you change this value
private static final String autopsyVer = "3.0.0b1"; // current version of autopsy. Changed it when the version is changed
private static final String appName = "Autopsy " + autopsyVer;
/**
* Property name that indicates the name of the current case has changed.
* Fired with the case is renamed, and when the current case is
* opened/closed/changed. The value is a String: the name of the case.
* The empty string ("") is used for no open case.
*/
public static final String CASE_NAME = "caseName";
/**
* Property name that indicates a new image has been added to the current
* case. The new value is the newly-added instance of Image, and the old
* value is always null.
*/
public static final String CASE_ADD_IMAGE = "addImages";
/**
* Property name that indicates an image has been removed from the current
* case. The "old value" is the (int) image ID of the image that was
* removed, the new value is the instance of the Image.
*/
public static final String CASE_DEL_IMAGE = "removeImages";
/**
* Property name that indicates the currently open case has changed.
* The new value is the instance of the opened Case, or null if there is no
* open case.
* The old value is the instance of the closed Case, or null if there was no
* open case.
*/
public static final String CASE_CURRENT_CASE = "currentCase";
/**
* Name for the property that determines whether to show the dialog at
* startup
*/
static final String propStartup = "LBL_StartupDialog";
private static Properties properties = new Properties();
// pcs is initialized in CaseListener constructor
private static PropertyChangeSupport pcs;
private static PropertyChangeListener caseListener = new CaseListener();
private String name;
private String configFilePath;
private XMLCaseManagement xmlcm;
private SleuthkitCase db;
// Track the current case (only set with changeCase() method)
private static Case currentCase = null;
/**
* Constructor for the Case class
*/
private Case(String name, String configFilePath, XMLCaseManagement xmlcm, SleuthkitCase db) {
this.name = name;
this.configFilePath = configFilePath;
this.xmlcm = xmlcm;
this.db = db;
}
/**
* Gets the currently opened case, if there is one.
*
* @return the current open case
* @throws IllegalStateException if there is no case open.
*/
public static Case getCurrentCase() {
if (currentCase != null) {
return currentCase;
} else {
throw new IllegalStateException("Can't get the current case; there is no case open!");
}
}
/**
* Updates the current case to the given case and fires off
* the appropriate property-change
* @param newCase the new current case
*/
private static void changeCase(Case newCase) {
Case oldCase = Case.currentCase;
Case.currentCase = null;
String oldCaseName = oldCase != null ? oldCase.name : "";
pcs.firePropertyChange(CASE_CURRENT_CASE, oldCase, null);
pcs.firePropertyChange(CASE_NAME, oldCaseName, "");
if (newCase != null) {
currentCase = newCase;
pcs.firePropertyChange(CASE_CURRENT_CASE, null, currentCase);
//TODO: This will fire off a bunch of stuff in CaseListener.propertyChange()
// that should probably be migrated into here
pcs.firePropertyChange(CASE_NAME, "", currentCase.name);
RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases
}
}
AddImageProcess makeAddImageProcess(String timezone) {
return this.db.makeAddImageProcess(timezone);
}
/**
* Creates a new case (create the XML config file and the directory)
*
* @param caseDir the base directory where the configuration file is saved
* @param caseName the name of case
*/
static void create(String caseDir, String caseName) throws Exception {
Log.get(Case.class).log(Level.INFO, "Creating new case.\ncaseDir: {0}\ncaseName: {1}", new Object[] {caseDir, caseName});
String configFilePath = caseDir + File.separator + caseName + ".aut";
XMLCaseManagement xmlcm = new XMLCaseManagement();
xmlcm.create(caseDir, caseName); // create a new XML config file
xmlcm.writeFile();
String dbPath = caseDir + File.separator + "autopsy.db";
SleuthkitCase db = SleuthkitCase.newCase(dbPath);
Case newCase = new Case(caseName, configFilePath, xmlcm, db);
changeCase(newCase);
}
/**
* Opens the existing case (open the XML config file)
*
* @param configFilePath the path of the configuration file that's opened
* @throws Exception
*/
static void open(String configFilePath) throws Exception {
Log.get(Case.class).log(Level.INFO, "Opening case.\nconfigFilePath: {0}", configFilePath);
try {
XMLCaseManagement xmlcm = new XMLCaseManagement();
xmlcm.open(configFilePath); // open and load the config file to the document handler in the XML class
xmlcm.writeFile(); // write any changes to the config file
String caseName = xmlcm.getCaseName();
// if the caseName is "", case / config file can't be opened
if (caseName.equals("")) {
throw new Exception("Case name is blank.");
}
String caseDir = xmlcm.getCaseDirectory();
String dbPath = caseDir + File.separator + "autopsy.db";
SleuthkitCase db = SleuthkitCase.openCase(dbPath);
Case openedCase = new Case(caseName, configFilePath, xmlcm, db);
changeCase(openedCase);
} catch (Exception ex) {
// close the previous case if there's any
CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class);
closeCase.actionPerformed(null);
throw ex;
}
}
/**
* Adds the image to the current case after it has been added to the DB
*
* @param imgPaths the paths of the image that being added
* @param imgId the ID of the image that being added
* @param timeZone the timeZone of the image where it's added
*/
void addImage(String[] imgPaths, long imgId, String timeZone) throws Exception {
Log.get(this.getClass()).log(Level.INFO, "Adding image to Case. imgPaths: {0} ID: {1} TimeZone: {2}", new Object[]{Arrays.toString(imgPaths), imgId, timeZone});
try {
xmlcm.addImage(imgPaths, imgId, timeZone); // add the image to the document handler in the XML class and to the config file
xmlcm.writeFile(); // write any changes to the config file
Image newImage = db.getImageById(imgId);
pcs.firePropertyChange(CASE_ADD_IMAGE, null, newImage); // the new value is the instance of the image
} catch (Exception ex) {
// throw an error here
throw ex;
}
}
/**
* Get the underlying SleuthkitCase instance from the Sleuth Kit bindings
* library.
* @return
*/
public SleuthkitCase getSleuthkitCase() {
return this.db;
}
/**
* Closes this case. This methods close the xml and clear all the fields.
*/
void closeCase() throws Exception {
changeCase(null);
try {
this.xmlcm.close(); // close the xmlcm
this.db.close();
} catch (Exception e) {
throw new Exception("Error while trying to close the current case.", e);
}
}
/**
* Delete this case. This methods delete all folders and files of this case.
*/
boolean deleteCase(File caseDir) {
Log.get(this.getClass()).log(Level.FINE, "Deleting case.\ncaseDir: {0}", caseDir);
try {
xmlcm.close(); // close the xmlcm
boolean result = deleteCaseDirectory(caseDir); // delete the directory
RecentCases.getInstance().removeRecentCase(this.name, this.configFilePath); // remove it from the recent case
Case.changeCase(null);
return result;
} catch (Exception ex) {
// TODO: change to using exceptions instead of return value.
// throw an error here
Logger logger = Logger.getLogger(Case.class.getName());
logger.log(Level.SEVERE, "Error deleting the current case.", ex);
return false;
}
}
/**
* Updates the case name.
*
* @param oldCaseName the old case name that wants to be updated
* @param oldPath the old path that wants to be updated
* @param newCaseName the new case name
* @param newPath the new path
*/
void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath) throws Exception {
try {
xmlcm.setCaseName(newCaseName); // set the case
name = newCaseName; // change the local value
RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case
pcs.firePropertyChange(CASE_NAME, oldCaseName, newCaseName);
} catch (Exception e) {
throw new Exception("Error while trying to update the case name.", e);
}
}
// Not dealing with removing images for now.
// /**
// * Removes the image from this case
// *
// * @param givenID the ID of the image to be removed
// * @param givenPath the path of the image to be removed
// */
// void removeImage(int givenID, String givenPath) throws Exception {
// Log.get(this.getClass()).log(Level.FINE, "Removing image.\ngivenID: {0}\ngivenPath: {1}", new Object[] {givenID, givenPath});
//
// String[] tempPaths = xmlcm.getImageSet(givenID);
// String tempDb = xmlcm.getImageSetDbPath(givenID);
//
// if (tempPaths[0].equals(givenPath)) {
// xmlcm.removeImageSet(givenID); // make the changes in the config file
// try {
// xmlcm.writeFile();
// } catch (Exception ex) {
// throw new Exception("Error while trying to remove the image from this case.", ex);
// }
//
// Image img = imageIdToData.get(givenID).image; // save the image that we want to delete temporarily
//
// imageIdToData.remove(givenID);
//
// pcs.firePropertyChange(CASE_DEL_IMAGE, givenID, img); // the old value is the image ID that removed, the new value is the instance of the image
//
// img.getSleuthkit().closeConnection(); // to make sure that we close the connection
//
// // need to remove the database as well??
// File database = new File(tempDb);
// boolean test = database.delete(); // delete the database of the image that we remove
// if (!test) {
// database.deleteOnExit(); // delete on exit if the delete is not successful
// }
// } else {
// // throw an error here
// Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Couldn't remove image.", new Exception("Couldn't find the image in this case."));
// }
// }
/**
* Checks whether there is a current case open.
*
* @return True if a case is open.
*/
public static boolean existsCurrentCase() {
return currentCase != null;
}
/**
* Uses the given path to store it as the configuration file path
*
* @param givenPath the given config file path
*/
private void setConfigFilePath(String givenPath) {
configFilePath = givenPath;
}
/**
* Get the config file path in the given path
*
* @return configFilePath the path of the configuration file
*/
String getConfigFilePath() {
return configFilePath;
}
/**
* Returns the current version of Autopsy
* @return autopsyVer
*/
public static String getAutopsyVersion() {
return autopsyVer;
}
/**
* Gets the application name
* @return appName
*/
public static String getAppName() {
return appName;
}
/**
* Gets the case name
* @return name
*/
public String getName() {
return name;
}
/**
* Gets the case directory path
* @return caseDirectoryPath
*/
public String getCaseDirectory() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getCaseDirectory();
}
}
/**
* Gets the full path to the temp directory of this case
* @return tempDirectoryPath
*/
public String getTempDirectory() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getTempDir();
}
}
/**
* get the created date of this case
* @return case creation date
*/
public String getCreatedDate() {
if (xmlcm == null) {
return "";
} else {
return xmlcm.getCreatedDate();
}
}
/**
* get the PropertyChangeSupport of this class
* @return PropertyChangeSupport
*/
public static PropertyChangeSupport getPropertyChangeSupport() {
return pcs;
}
String[] getImagePaths(int imgID) {
return xmlcm.getImageSet(imgID);
}
/**
* get all the image id in this case
* @return imageIDs
*/
public int[] getImageIDs() {
if (xmlcm == null) {
return new int[0];
} else {
return xmlcm.getImageIDs();
}
}
/**
* Count the root objects.
* @return The number of total root objects in this case.
*/
public int getRootObjectsCount() {
return getRootObjects().size();
}
/**
* Get the data model Content objects in the root of this case's hierarchy.
* @return a list of the root objects
*/
public List<Content> getRootObjects() {
try {
return db.getRootObjects();
} catch (TskException ex) {
throw new RuntimeException("Error getting root objects.", ex);
}
}
/**
* Gets the time zone(s) of the image(s) in this case.
*
* @return time zones the set of time zones
*/
public Set<TimeZone> getTimeZone() {
if (xmlcm == null) {
return new HashSet<TimeZone>();
} else {
return xmlcm.getTimeZone();
}
}
public static synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public static synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
/**
* convert the image Path to array string
* @param imgPath the image path
* @return imgPath the converted image path
*/
public static String[] convertImgPath(String imgPath) {
String[] result;
String unsplitPaths = imgPath;
int count = 0;
for (int i = 0; i < unsplitPaths.length(); i++) {
if (unsplitPaths.charAt(i) == '\"') {
count++;
}
}
if (count != 0) {
result = new String[count / 2];
int start = 0;
int current = 0;
for (int i = 0; i < count / 2; i++) {
while (unsplitPaths.charAt(current) != '\"') {
current++;
}
start = current;
current++;
while (unsplitPaths.charAt(current) != '\"') {
current++;
}
result[i] = unsplitPaths.substring(start + 1, current);
current++;
}
} else {
result = new String[1];
result[0] = unsplitPaths;
}
return result;
}
/**
* Check if all the images from the given image path exist.
* @param imgPaths the image paths
* @return isExist whether the multiple paths exist
*/
public static boolean checkMultiplePathExist(String[] imgPaths) {
boolean result = false;
int totalLength = imgPaths.length;
if (totalLength > 0) {
result = true;
for (int i = 0; i < totalLength; i++) {
if (new File(imgPaths[i]).exists()) {
result = result && true;
} else {
result = result && false;
}
}
}
return result;
}
/**
* Convert the Java timezone ID to the "formatted" string that can be
* accepted by the C/C++ code.
* Example: "America/New_York" converted to "EST5EDT", etc
*
* @param timezoneID
* @return
*/
public static String convertTimeZone(String timezoneID) {
String result = "";
TimeZone zone = TimeZone.getTimeZone(timezoneID);
int offset = zone.getRawOffset() / 1000;
int hour = offset / 3600;
DateFormat dfm = new SimpleDateFormat("z");
dfm.setTimeZone(zone);
boolean hasDaylight = zone.useDaylightTime();
String first = dfm.format(new Date(2010, 1, 1)).substring(0, 3); // make it only 3 letters code
String second = dfm.format(new Date(2011, 6, 6)).substring(0, 3); // make it only 3 letters code
int mid = hour * -1;
result = first + Integer.toString(mid);
if (hasDaylight) {
result = result + second;
}
return result;
}
/* The methods below are used to manage the case directories (creating, checking, deleting, etc) */
/**
* to create the case directory
* @param caseDir the case directory path
* @param caseName the case name
* @return boolean whether the case directory is successfully created or not
*/
static boolean createCaseDirectory(String caseDir, String caseName) {
boolean result = false;
try {
result = (new File(caseDir)).mkdirs(); // create root case Directory
// create the folders inside the case directory
result = result && (new File(caseDir + File.separator + XMLCaseManagement.EXPORT_FOLDER_RELPATH)).mkdir()
&& (new File(caseDir + File.separator + XMLCaseManagement.LOG_FOLDER_RELPATH)).mkdir()
&& (new File(caseDir + File.separator + XMLCaseManagement.TEMP_FOLDER_RELPATH)).mkdir();
return result;
} catch (Exception e) {
// TODO: change to use execptions instead of return values for error handling
return false;
}
}
/**
* delete the given case directory
* @param casePath the case path
* @return boolean whether the case directory is successfully deleted or not
*/
static boolean deleteCaseDirectory(File casePath) {
if (casePath.exists()) {
File[] files = casePath.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteCaseDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return (casePath.delete());
}
/**
* Invoke the creation of startup dialog window.
*/
static public void invokeStartupDialog() {
boolean showDialog = true;
String propFilePath = RecentCases.getPropertiesFilePath();
// before showing the startup dialog, check if it has been disabled or not by the user
try {
// try to load the property from the properties file in the home directory
InputStream inputStream = new FileInputStream(propFilePath);
//InputStream inputStream = getClass().getResourceAsStream("Case.properties"); // old variable (can be deleted if no longer needed)
properties.load(inputStream);
String temp = properties.getProperty(propStartup);
if (temp != null) {
showDialog = !temp.equals("false");
} else {
// if it's null, we have to write the properties
// update the properties
properties.setProperty(propStartup, "true");
// write the properties file
try {
properties.store(new FileOutputStream(new File(RecentCases.getPropertiesFilePath())), "");
} catch (Exception ex) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex);
}
}
} catch (Exception ex) {
// if cannot load it, we create a new properties file without any data inside it
properties.setProperty(propStartup, "true");
try {
// create the directory and property file to store it
File output = new File(propFilePath);
// if the properties file doesn't exist, we create a new one.
if (!output.exists()) {
File parent = new File(output.getParent());
if (!parent.exists()) {
parent.mkdirs(); // create the parent directory if it doesn't exist
}
output.createNewFile(); // create the properties file
FileOutputStream fos = new FileOutputStream(output);
properties.store(fos, "");
} // if the output exist, we just add the properties
else {
properties.setProperty(propStartup, "true");
// write the properties file
try {
properties.store(new FileOutputStream(new File(RecentCases.getPropertiesFilePath())), "");
} catch (Exception ex3) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex3);
}
}
} catch (Exception ex2) {
Logger.getLogger(Case.class.getName()).log(Level.WARNING, "Error: Could not create the property file.", ex2);
}
}
if (showDialog) {
StartupWindow.getInstance().display();
}
}
/**
* Call if there are no images in the case. Displays
* a dialog offering to add one.
*/
private void noRootObjectsNotification() throws TskException {
NotifyDescriptor nd = new NotifyDescriptor(
"This case contains no images. Would you like to add one?",
"No images in case", NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.INFORMATION_MESSAGE,
null,
NotifyDescriptor.YES_OPTION);
if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION) {
Lookup.getDefault().lookup(AddImageAction.class).actionPerformed(null);
}
}
/**
* Get the properties.
*
* @return properties
*/
public Properties getProperties() {
return properties;
}
/**
* Checks if a String is a valid case name
* @param caseName the candidate String
* @return true if the candidate String is a valid case name
*/
static public boolean isValidName(String caseName) {
return !(caseName.contains("\\") || caseName.contains("/") || caseName.contains(":")
|| caseName.contains("*") || caseName.contains("?") || caseName.contains("\"")
|| caseName.contains("<") || caseName.contains(">") || caseName.contains("|"));
}
static private void clearTempFolder() {
File tempFolder = new File(currentCase.getTempDirectory());
if (tempFolder.isDirectory()) {
File[] files = tempFolder.listFiles();
if (files.length > 0) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteCaseDirectory(files[i]);
} else {
files[i].delete();
}
}
}
}
}
private static class CaseListener implements PropertyChangeListener {
CaseListener() {
pcs = new PropertyChangeSupport(this);
pcs.addPropertyChangeListener(this);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName();
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if (changed.equals(Case.CASE_CURRENT_CASE)) {
try {
if (newValue != null) { // new case is open
Case newCase = (Case) newValue;
// clear the temp folder when the case is created / opened
Case.clearTempFolder();
// enable these menus
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
if (newCase.getRootObjectsCount() > 0) {
// open all top components
CoreComponentControl.openCoreWindows();
} else {
// close all top components
CoreComponentControl.closeCoreWindows();
// notify user
newCase.noRootObjectsNotification();
}
} else { // case is closed
// disable these menus
CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
// close all top components
CoreComponentControl.closeCoreWindows();
Frame f = WindowManager.getDefault().getMainWindow();
f.setTitle(Case.getAppName()); // set the window name to just application name
}
} catch (TskException ex) {
Log.get(CaseListener.class).log(Level.WARNING, "Error handling change in current case.", ex);
}
}
// changed in the case name
if (changed.equals(Case.CASE_NAME)) {
String oldCaseName = oldValue.toString();
String newCaseName = newValue.toString();
// update case name
if (!newCaseName.equals("")) {
Frame f = WindowManager.getDefault().getMainWindow();
f.setTitle(newCaseName + " - " + Case.getAppName()); // set the window name to the new value
}
}
// if the image is added to the case
if (changed.equals(Case.CASE_ADD_IMAGE)) {
// open all top components
CoreComponentControl.openCoreWindows();
}
// if the image is removed from the case
if (changed.equals(Case.CASE_DEL_IMAGE)) {
// no more image left in this case
if (currentCase.getRootObjectsCount() == 0) {
// close all top components
CoreComponentControl.closeCoreWindows();
}
}
}
}
}

View File

@ -0,0 +1,132 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.logging.Log;
/**
* The action to close the current Case. This class should be disabled on
* creation and it will be enabled on new case creation or case opened.
*/
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar{
JButton toolbarButton = new JButton();
/**
* The constructor for this class
*/
public CaseCloseAction() {
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); // put the icon
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); // put the action Name
// set action of the toolbar button
toolbarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CaseCloseAction.this.actionPerformed(e);
}
});
this.setEnabled(false);
}
/**
* Closes the current opened case.
*
* @param e the action event for this method
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
if (Case.existsCurrentCase() == false)
return;
Case result = Case.getCurrentCase();
try {
result.closeCase();
} catch (Exception ex) {
Logger.getLogger(CaseCloseAction.class.getName()).log(Level.SEVERE, "Error closing case.", ex);
}
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)" instead of this method.
*/
@Override
public void performAction() {
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override
public String getName() {
return NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct");
}
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
/**
* Returns the toolbar component of this action
*
* @return component the toolbar button
*/
@Override
public Component getToolbarPresenter() {
ImageIcon icon = new ImageIcon(getClass().getResource("close-icon.png"));
toolbarButton.setIcon(icon);
return toolbarButton;
}
/**
* Set this action to be enabled/disabled
*
* @param value whether to enable this action or not
*/
@Override
public void setEnabled(boolean value){
super.setEnabled(value);
toolbarButton.setEnabled(value);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.casemodule;
/**
* NOTE: NOTHING ACTUALLY USES THIS
*
* The interface for the classes that edit the case configuration file
*/
//TODO: check that this can just be deleted.
interface CaseConfigFileInterface {
public void open(String conFilePath) throws Exception; // opens the confiuation store (XML, DB...)
public void writeFile() throws Exception; // writes out the configuration to store
public void close() throws Exception; // close and clear the document handler
public int[] getImageIDs() throws Exception; // returns a list of image IDs and names
public int getNextImageID() throws Exception; // returns the next free ID to be assigned to new image, and increments the internal counter
// all the get and set methods
public String getCaseName() throws Exception; // get the case name
public void setCaseName(String caseName) throws Exception; // set the case name
// public void getXXX(); // methods to get the case attributes
// public void setXXX(); // methods to set the case attributes
}

View File

@ -0,0 +1,117 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.logging.Log;
/**
* The action to delete the current Case. This class should be disabled on
* creation and it will be enabled on new case creation or case opened.
*/
public final class CaseDeleteAction extends CallableSystemAction {
private JPanel caller; // for error handling
/**
* The constructor for this class
*/
public CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction")); // put the action Name
this.setEnabled(false);
}
/**
* Deletes the current opened case.
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
Case currentCase = Case.getCurrentCase();
File configFile = new File(currentCase.getConfigFilePath());
File caseFolder = new File(configFile.getParent());
String caseName = currentCase.getName();
if(!caseFolder.exists()){
// throw an error
Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
logger.log(Level.WARNING, "Couldn't delete case.", new Exception("The case directory doesn't exist."));
}
else{
// show the confirmation first to close the current case and open the "New Case" wizard panel
String closeCurrentCase = "Are you sure want to close and delete this case? \n Case Name: " + caseName + "\n Case Directory: "+ caseFolder.getPath();
NotifyDescriptor d = new NotifyDescriptor.Confirmation(closeCurrentCase, "Warning: Closing the Current Case", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if(res != null && res == DialogDescriptor.YES_OPTION){
boolean success = Case.getCurrentCase().deleteCase(caseFolder); // delete the current case
// show notification whether the case has been deleted or it failed to delete...
if(!success){
JOptionPane.showMessageDialog(caller, "The delete action can't be fully completed because the folder or file in it is open by another program.\n \nClose the folder and file and try again or you can delete the case manually.", "Error: Folder In Use", JOptionPane.ERROR_MESSAGE); // throw an error
}
else{
CasePropertiesAction.closeCasePropertiesWindow(); // because the "Delete Case" button is in the "CaseProperties" window, we have to close that window when we delete the case.
JOptionPane.showMessageDialog(caller, "Case " + caseName + " has been deleted.");
}
}
}
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)" instead of this method.
*/
@Override
public void performAction() {
// Note: I use the actionPerformed above instead of this method
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
* @return actionName
*/
@Override
public String getName() {
return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction");
}
/**
* Gets the HelpCtx associated with implementing object
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.util.actions.SystemAction;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.logging.Log;
/**
* The action to create a new case. This action class is always enabled.
*
* @author jantonius
*/
@ServiceProvider(service = CaseNewAction.class)
public final class CaseNewAction implements ActionListener {
private NewCaseWizardAction wizard = SystemAction.get(NewCaseWizardAction.class);
/**
* Calls the "New Case" wizard panel action.
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
wizard.performAction();
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.logging.Log;
/**
* The action to open a existing case. This class is always enabled.
*
* @author jantonius
*/
@ServiceProvider(service = CaseOpenAction.class)
public final class CaseOpenAction implements ActionListener {
JFileChooser fc = new JFileChooser();
GeneralFilter autFilter = new GeneralFilter(new String[]{".aut"}, "AUTOPSY File (*.aut)", false);
/** The constructor */
public CaseOpenAction() {
fc.setDragEnabled(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
fc.addChoosableFileFilter(autFilter);
}
/**
* Pop-up the File Chooser to open the existing case (.aut file)
*
* @param e the action event
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
int retval = fc.showOpenDialog((Component) e.getSource());
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
// check if the file exists
if (!new File(path).exists()) {
JOptionPane.showMessageDialog(null, "Error: File doesn't exist.", "Error", JOptionPane.ERROR_MESSAGE);
this.actionPerformed(e); // show the dialog box again
} else {
// try to close Startup window if there's one
try {
StartupWindow.getInstance().close();
} catch (Exception ex) {
// no need to show the error message to the user.
// TODO: But maybe put the error message in the log in the future.
}
try {
Case.open(path); // open the case
} catch (Exception ex) {
Logger.getLogger(CaseOpenAction.class.getName()).log(Level.SEVERE, "Error opening case.", ex);
}
}
}
}
}

View File

@ -0,0 +1,139 @@
/*
* 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.casemodule;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.JDialog;
import javax.swing.JFrame;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.logging.Log;
/**
* The action to pop up the Case Properties Form window. By using this form,
* user can update the case properties (for example: updates the case name and
* removes the image from the current case)
*
* @author jantonius
*/
public final class CasePropertiesAction extends CallableSystemAction {
private static JDialog popUpWindow;
/**
* The CasePropertiesAction constructor
*/
CasePropertiesAction() {
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction")); // put the action Name
this.setEnabled(false);
}
/**
* Pop-up the Case Properties Form window where user can change the case
* properties (example: update case name and remove the image from the case)
*/
@Override
public void performAction() {
Log.noteAction(this.getClass());
try {
// create the popUp window for it
String title = "Case Properties";
final JFrame frame = new JFrame(title);
popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
// get the information that needed
Case currentCase = Case.getCurrentCase();
String caseName = currentCase.getName();
String crDate = currentCase.getCreatedDate();
String caseDir = currentCase.getCaseDirectory();
int totalImage = currentCase.getRootObjectsCount();
// put the image paths information into hashmap
HashMap<Integer, String[]> imgPaths = new HashMap<Integer, String[]>();
int[] imgIDs = currentCase.getImageIDs();
for (int i = 0; i < totalImage; i++) {
int imgID = imgIDs[i];
String[] imagePaths = currentCase.getImagePaths(imgID);
if (imagePaths != null) {
imgPaths.put(imgID, imagePaths);
}
}
// create the case properties form
CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);
// add the command to close the window to the button on the Case Properties form / panel
cpf.setOKButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popUpWindow.dispose();
}
});
// add the case properties form / panel to the popup window
popUpWindow.add(cpf);
popUpWindow.pack();
popUpWindow.setResizable(false);
// set the location of the popUp Window on the center of the screen
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
double w = popUpWindow.getSize().getWidth();
double h = popUpWindow.getSize().getHeight();
popUpWindow.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
popUpWindow.setVisible(true);
} catch (Exception ex) {
Log.get(CasePropertiesAction.class).log(Level.WARNING, "Error displaying Case Properties window.", ex);
}
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
* @return actionName
*/
@Override
public String getName() {
return NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction");
}
/**
* Gets the HelpCtx associated with implementing object
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
static void closeCasePropertiesWindow() {
popUpWindow.dispose();
}
}

View File

@ -0,0 +1,254 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextArea1">
<Properties>
<Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="5"/>
</Properties>
</Component>
</SubComponents>
</Container>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="casePropLabel" pref="440" max="32767" attributes="0"/>
<Component id="genInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="caseDirLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="crDateLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="caseNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" pref="246" max="32767" attributes="0"/>
<Component id="caseNameTextField" alignment="0" pref="246" max="32767" attributes="1"/>
<Component id="crDateTextField" alignment="0" pref="246" max="32767" attributes="1"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="updateCaseNameButton" max="32767" attributes="1"/>
<Component id="deleteCaseButton" alignment="0" max="32767" attributes="1"/>
</Group>
</Group>
<Component id="imgInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="imagesTableScrollPane" alignment="0" pref="440" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="191" max="-2" attributes="0"/>
<Component id="OKButton" min="-2" pref="78" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="casePropLabel" min="-2" pref="33" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="genInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="updateCaseNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="crDateLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="crDateTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="caseDirLabel" min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" min="-2" pref="40" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
<Component id="imgInfoLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="deleteCaseButton" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="imagesTableScrollPane" min="-2" pref="170" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="OKButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="17" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="casePropLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.casePropLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="crDateLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseDirLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="crDateTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseNameTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="updateCaseNameButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.updateCaseNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="updateCaseNameButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="genInfoLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.genInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="imgInfoLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.imgInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="OKButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.OKButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="imagesTableScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="imagesTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="2" rowCount="0">
<Column editable="false" title="Path" type="java.lang.Object"/>
<Column editable="true" title="Remove" type="java.lang.Object"/>
</Table>
</Property>
<Property name="showHorizontalLines" type="boolean" value="false"/>
<Property name="showVerticalLines" type="boolean" value="false"/>
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
</Property>
<Property name="updateSelectionOnSort" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="caseDirTextArea">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="rows" type="int" value="1"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="deleteCaseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.deleteCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteCaseButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,399 @@
/*
* 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.
*/
/*
* CasePropertiesForm.java
*
* Created on Mar 14, 2011, 1:48:20 PM
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.actions.CallableSystemAction;
/**
* The form where user can change / update the properties of the current case.
*
* @author jantonius
*/
class CasePropertiesForm extends javax.swing.JPanel{
Case current = null;
private static JPanel caller; // panel for error
// Shrink a path to fit in targetLength (if necessary), by replaceing part
// of the path with "...". Ex: "C:\Users\bob\...\folder\other\Image.img"
private String shrinkPath(String path, int targetLength) {
if(path.length() > targetLength){
String fill = "...";
int partsLength = targetLength - fill.length();
String front = path.substring(0, partsLength/4);
int frontSep = front.lastIndexOf(File.separatorChar);
if (frontSep != -1) {
front = front.substring(0, frontSep+1);
}
String back = path.substring(partsLength*3/4);
int backSep = back.indexOf(File.separatorChar);
if (backSep != -1) {
back = back.substring(backSep);
}
return back + fill + front;
} else {
return path;
}
}
/** Creates new form CasePropertiesForm */
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Integer,String[]> imgPaths) {
initComponents();
caseNameTextField.setText(currentCase.getName());
crDateTextField.setText(crDate);
caseDirTextArea.setText(caseDir);
current = currentCase;
int totalImages = imgPaths.size();
// create the headers and add all the rows
String[] headers = {"Path"};
String[][] rows = new String[totalImages][];
int i = 0;
for(int key : imgPaths.keySet()){
String path = imgPaths.get(key)[0];
String shortenPath = shrinkPath(path, 70);
rows[i++] = new String[]{shortenPath};
}
// create the table inside with the imgPaths information
DefaultTableModel model = new DefaultTableModel(rows, headers)
{
@Override
// make the cells in the FileContentTable "read only"
public boolean isCellEditable(int row, int column){
return false;
//return column == lastColumn; // make the last column (Remove button), only the editable
}
};
imagesTable.setModel(model);
// // set the size of the remove column
// TableColumn removeCol = imagesTable.getColumnModel().getColumn(lastColumn);
// removeCol.setPreferredWidth(75);
// removeCol.setMaxWidth(75);
// removeCol.setMinWidth(75);
// removeCol.setResizable(false);
// // create the delete action to remove the image from the current case
// Action delete = new AbstractAction()
// {
// @Override
// public void actionPerformed(ActionEvent e)
// {
// // get the image path
// JTable table = (JTable)e.getSource();
// int modelRow = Integer.valueOf(e.getActionCommand());
// String removeColumn = table.getValueAt(modelRow, lastColumn).toString();
// // get the image ID
// int selectedID = Integer.parseInt(removeColumn.substring(0, removeColumn.indexOf('|')));
// String imagePath = removeColumn.substring(removeColumn.indexOf('|') + 1);
//
// // throw the confirmation first
// String confMsg = "Are you sure want to remove image \"" + imagePath + "\" from this case?";
// NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg, "Create directory", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
// d.setValue(NotifyDescriptor.NO_OPTION);
//
// Object res = DialogDisplayer.getDefault().notify(d);
// // if user select "Yes"
// if(res != null && res == DialogDescriptor.YES_OPTION){
// // remove the image in the case class and in the xml config file
// try {
// current.removeImage(selectedID, imagePath);
// } catch (Exception ex) {
// Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: couldn't remove image.", ex);
// }
// // remove the row of the image path
// ((DefaultTableModel)table.getModel()).removeRow(modelRow);
// }
// }
// };
//
// ButtonColumn buttonColumn = new ButtonColumn(imagesTable, delete, 1, "Remove");
// buttonColumn.setMnemonic(KeyEvent.VK_D);
}
/** This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
casePropLabel = new javax.swing.JLabel();
caseNameLabel = new javax.swing.JLabel();
crDateLabel = new javax.swing.JLabel();
caseDirLabel = new javax.swing.JLabel();
crDateTextField = new javax.swing.JTextField();
caseNameTextField = new javax.swing.JTextField();
updateCaseNameButton = new javax.swing.JButton();
genInfoLabel = new javax.swing.JLabel();
imgInfoLabel = new javax.swing.JLabel();
OKButton = new javax.swing.JButton();
imagesTableScrollPane = new javax.swing.JScrollPane();
imagesTable = new javax.swing.JTable();
jScrollPane2 = new javax.swing.JScrollPane();
caseDirTextArea = new javax.swing.JTextArea();
deleteCaseButton = new javax.swing.JButton();
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);
casePropLabel.setFont(new java.awt.Font("Tahoma", 1, 24));
casePropLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
casePropLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.casePropLabel.text")); // NOI18N
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameLabel.text")); // NOI18N
crDateLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateLabel.text")); // NOI18N
caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirLabel.text")); // NOI18N
crDateTextField.setEditable(false);
crDateTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateTextField.text")); // NOI18N
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameTextField.text")); // NOI18N
updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.updateCaseNameButton.text")); // NOI18N
updateCaseNameButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
updateCaseNameButtonActionPerformed(evt);
}
});
genInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
genInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.genInfoLabel.text")); // NOI18N
imgInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
imgInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imgInfoLabel.text")); // NOI18N
OKButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.OKButton.text")); // NOI18N
imagesTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Path", "Remove"
}
) {
boolean[] canEdit = new boolean [] {
false, true
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
imagesTable.setShowHorizontalLines(false);
imagesTable.setShowVerticalLines(false);
imagesTable.getTableHeader().setReorderingAllowed(false);
imagesTable.setUpdateSelectionOnSort(false);
imagesTableScrollPane.setViewportView(imagesTable);
caseDirTextArea.setBackground(new java.awt.Color(240, 240, 240));
caseDirTextArea.setColumns(20);
caseDirTextArea.setEditable(false);
caseDirTextArea.setRows(1);
caseDirTextArea.setRequestFocusEnabled(false);
jScrollPane2.setViewportView(caseDirTextArea);
deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.deleteCaseButton.text")); // NOI18N
deleteCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteCaseButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(casePropLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)
.addComponent(genInfoLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseDirLabel)
.addComponent(crDateLabel)
.addComponent(caseNameLabel))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
.addComponent(caseNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
.addComponent(crDateTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(updateCaseNameButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(deleteCaseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(imgInfoLabel)
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGap(191, 191, 191)
.addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(casePropLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(genInfoLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNameLabel)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(updateCaseNameButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(crDateLabel)
.addComponent(crDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseDirLabel)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(39, 39, 39)
.addComponent(imgInfoLabel))
.addComponent(deleteCaseButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(OKButton)
.addContainerGap(17, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
/**
* Updates the case name.
*
* @param evt The action event
*/
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
String oldCaseName = Case.getCurrentCase().getName();
String newCaseName = caseNameTextField.getText();
//String oldPath = caseDirTextArea.getText() + File.separator + oldCaseName + ".aut";
//String newPath = caseDirTextArea.getText() + File.separator + newCaseName + ".aut";
// check if the old and new case name is not equal
if(!oldCaseName.equals(newCaseName)){
// check if the case name is empty
if(newCaseName.trim().equals("")){
JOptionPane.showMessageDialog(caller, "The caseName cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
}
else{
// check if case Name contain one of this following symbol:
// \ / : * ? " < > |
if(newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":") ||
newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"") ||
newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")){
String errorMsg = "The Case Name cannot contain any of this following symbol: \\ / : * ? \" < > |";
JOptionPane.showMessageDialog(caller, errorMsg, "Error", JOptionPane.ERROR_MESSAGE);
}
else{
// ask for the confirmation first
String confMsg = "Are you sure want to update the case name from \"" + oldCaseName + "\" to \"" + newCaseName + "\"?";
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg, "Create directory", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if(res != null && res == DialogDescriptor.YES_OPTION){
// if user select "Yes"
String oldPath = current.getConfigFilePath();
try {
current.updateCaseName(oldCaseName, oldPath , newCaseName, oldPath);
} catch (Exception ex) {
Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex);
}
}
}
}
}
}//GEN-LAST:event_updateCaseNameButtonActionPerformed
private void deleteCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteCaseButtonActionPerformed
CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt);
}//GEN-LAST:event_deleteCaseButtonActionPerformed
/**
* Sets the listener for the OK button
*
* @param e The action listener
*/
public void setOKButtonActionListener(ActionListener e){
OKButton.addActionListener(e);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton OKButton;
private javax.swing.JLabel caseDirLabel;
private javax.swing.JTextArea caseDirTextArea;
private javax.swing.JLabel caseNameLabel;
private javax.swing.JTextField caseNameTextField;
private javax.swing.JLabel casePropLabel;
private javax.swing.JLabel crDateLabel;
private javax.swing.JTextField crDateTextField;
private javax.swing.JButton deleteCaseButton;
private javax.swing.JLabel genInfoLabel;
private javax.swing.JTable imagesTable;
private javax.swing.JScrollPane imagesTableScrollPane;
private javax.swing.JLabel imgInfoLabel;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JButton updateCaseNameButton;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,299 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="startupCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="345" max="32767" attributes="0"/>
<Component id="closeButton" min="-2" pref="73" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="logoPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editorPanel" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="editorPanel" max="32767" attributes="0"/>
<Component id="logoPanel" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="closeButton" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="startupCheckBox" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="startupCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.startupCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="closeButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JPanel" name="logoPanel">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="ff" red="ff" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace pref="13" max="32767" attributes="0"/>
<Component id="autopsyLogo" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="55" max="-2" attributes="0"/>
<Component id="autopsyLogo" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="131" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="autopsyLogo">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/Autopsy_logo.gif"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.autopsyLogo.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodePost" type="java.lang.String" value="this.autopsyLogo.setText(&quot;&quot;);"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="editorPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="welcomeLabel" min="-2" max="-2" attributes="0"/>
<Component id="autopsyLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="openCaseButton" alignment="1" min="-2" max="-2" attributes="1"/>
<Component id="newCaseButton" alignment="1" min="-2" max="-2" attributes="1"/>
<Component id="openRecentButton" alignment="1" min="-2" pref="70" max="-2" attributes="1"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="openLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="createNewLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="openRecentLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace pref="124" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="welcomeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="autopsyLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="newCaseButton" min="-2" pref="68" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="openCaseButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="openRecentButton" min="-2" pref="67" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="1">
<EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
<Component id="createNewLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="72" max="-2" attributes="0"/>
<Component id="openLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="70" max="32767" attributes="0"/>
<Component id="openRecentLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="45" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="welcomeLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="18" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.welcomeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="autopsyLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="32" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.autopsyLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodePost" type="java.lang.String" value="this.autopsyLabel.setText(Case.getAppName());"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="newCaseButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/new-icon.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.newCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[70, 70]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="openCaseButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/open-icon.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[1, 1, 1, 1]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[70, 70]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="openRecentButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/casemodule/open-recent-icon.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openRecentButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/>
</Property>
<Property name="borderPainted" type="boolean" value="false"/>
<Property name="contentAreaFilled" type="boolean" value="false"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[70, 70]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openRecentButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="createNewLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.createNewLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="openLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="openRecentLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="13" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CueBannerPanel.openRecentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,333 @@
/*
* 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.casemodule;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.openide.util.Lookup;
/**
*
* @author jantonius
*/
public class CueBannerPanel extends javax.swing.JPanel {
final private static String title = "Open Recent Case";
final private static JFrame frame = new JFrame(title);
final static JDialog recentCasesWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
// for error handling
private static JPanel caller = new JPanel();
private String className = this.getClass().toString();
/** Creates new form CueBannerPanel */
public CueBannerPanel() {
initComponents();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
startupCheckBox = new javax.swing.JCheckBox();
closeButton = new javax.swing.JButton();
logoPanel = new javax.swing.JPanel();
autopsyLogo = new javax.swing.JLabel();
this.autopsyLogo.setText("");
editorPanel = new javax.swing.JPanel();
welcomeLabel = new javax.swing.JLabel();
autopsyLabel = new javax.swing.JLabel();
this.autopsyLabel.setText(Case.getAppName());
newCaseButton = new javax.swing.JButton();
openCaseButton = new javax.swing.JButton();
openRecentButton = new javax.swing.JButton();
createNewLabel = new javax.swing.JLabel();
openLabel = new javax.swing.JLabel();
openRecentLabel = new javax.swing.JLabel();
startupCheckBox.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.startupCheckBox.text")); // NOI18N
closeButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.closeButton.text")); // NOI18N
closeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
logoPanel.setBackground(new java.awt.Color(255, 255, 255));
autopsyLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/Autopsy_logo.gif"))); // NOI18N
autopsyLogo.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.autopsyLogo.text")); // NOI18N
javax.swing.GroupLayout logoPanelLayout = new javax.swing.GroupLayout(logoPanel);
logoPanel.setLayout(logoPanelLayout);
logoPanelLayout.setHorizontalGroup(
logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(logoPanelLayout.createSequentialGroup()
.addContainerGap(13, Short.MAX_VALUE)
.addComponent(autopsyLogo)
.addContainerGap())
);
logoPanelLayout.setVerticalGroup(
logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(logoPanelLayout.createSequentialGroup()
.addGap(55, 55, 55)
.addComponent(autopsyLogo)
.addContainerGap(131, Short.MAX_VALUE))
);
welcomeLabel.setFont(new java.awt.Font("Tahoma", 1, 18));
welcomeLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.welcomeLabel.text")); // NOI18N
autopsyLabel.setFont(new java.awt.Font("Tahoma", 1, 32)); // NOI18N
autopsyLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.autopsyLabel.text")); // NOI18N
newCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/new-icon.png"))); // NOI18N
newCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.newCaseButton.text")); // NOI18N
newCaseButton.setBorder(null);
newCaseButton.setBorderPainted(false);
newCaseButton.setContentAreaFilled(false);
newCaseButton.setPreferredSize(new java.awt.Dimension(70, 70));
newCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newCaseButtonActionPerformed(evt);
}
});
openCaseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/open-icon.png"))); // NOI18N
openCaseButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openCaseButton.text")); // NOI18N
openCaseButton.setBorder(null);
openCaseButton.setBorderPainted(false);
openCaseButton.setContentAreaFilled(false);
openCaseButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
openCaseButton.setPreferredSize(new java.awt.Dimension(70, 70));
openCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openCaseButtonActionPerformed(evt);
}
});
openRecentButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/casemodule/open-recent-icon.png"))); // NOI18N
openRecentButton.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openRecentButton.text")); // NOI18N
openRecentButton.setBorder(null);
openRecentButton.setBorderPainted(false);
openRecentButton.setContentAreaFilled(false);
openRecentButton.setPreferredSize(new java.awt.Dimension(70, 70));
openRecentButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openRecentButtonActionPerformed(evt);
}
});
createNewLabel.setFont(new java.awt.Font("Tahoma", 0, 13));
createNewLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.createNewLabel.text")); // NOI18N
openLabel.setFont(new java.awt.Font("Tahoma", 0, 13));
openLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openLabel.text")); // NOI18N
openRecentLabel.setFont(new java.awt.Font("Tahoma", 0, 13));
openRecentLabel.setText(org.openide.util.NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.openRecentLabel.text")); // NOI18N
javax.swing.GroupLayout editorPanelLayout = new javax.swing.GroupLayout(editorPanel);
editorPanel.setLayout(editorPanelLayout);
editorPanelLayout.setHorizontalGroup(
editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(editorPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(welcomeLabel)
.addComponent(autopsyLabel)
.addGroup(editorPanelLayout.createSequentialGroup()
.addGap(19, 19, 19)
.addGroup(editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(openCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(newCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(openRecentButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(openLabel)
.addComponent(createNewLabel)
.addComponent(openRecentLabel))))
.addContainerGap(124, Short.MAX_VALUE))
);
editorPanelLayout.setVerticalGroup(
editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(editorPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(welcomeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(autopsyLabel)
.addGroup(editorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(editorPanelLayout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(newCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(openCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(openRecentButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(17, 17, 17))
.addGroup(editorPanelLayout.createSequentialGroup()
.addGap(41, 41, 41)
.addComponent(createNewLabel)
.addGap(72, 72, 72)
.addComponent(openLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 70, Short.MAX_VALUE)
.addComponent(openRecentLabel)
.addGap(45, 45, 45))))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(startupCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 345, Short.MAX_VALUE)
.addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(logoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(editorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(20, 20, 20)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(closeButton)
.addComponent(startupCheckBox))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void newCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCaseButtonActionPerformed
Lookup.getDefault().lookup(CaseNewAction.class).actionPerformed(evt);
}//GEN-LAST:event_newCaseButtonActionPerformed
private void openCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openCaseButtonActionPerformed
Lookup.getDefault().lookup(CaseOpenAction.class).actionPerformed(evt);
}//GEN-LAST:event_openCaseButtonActionPerformed
private void openRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openRecentButtonActionPerformed
// open the recent cases dialog
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
recentCasesWindow.setSize(750, 400);
int w = recentCasesWindow.getSize().width;
int h = recentCasesWindow.getSize().height;
// set the location of the popUp Window on the center of the screen
recentCasesWindow.setLocation((screenDimension.width - w)/2, (screenDimension.height - h)/2);
OpenRecentCasePanel welcomeWindow = new OpenRecentCasePanel();
// add the command to close the window to the button on the Volume Detail Panel
welcomeWindow.setCloseButtonActionListener( new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
recentCasesWindow.dispose();
}
});
recentCasesWindow.add(welcomeWindow);
recentCasesWindow.pack();
recentCasesWindow.setResizable(false);
recentCasesWindow.setVisible(true);
}//GEN-LAST:event_openRecentButtonActionPerformed
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
if(this.startupCheckBox.isSelected()){
Case current = Case.getCurrentCase();
Properties properties = current.getProperties();
// update the properties
properties.setProperty(current.propStartup, "false");
// write the properties file
try{
properties.store(new FileOutputStream(new File(RecentCases.getPropertiesFilePath())), "");
}
catch(Exception ex){
Logger.getLogger(this.className).log(Level.WARNING, "Error: Could not update the properties file.", ex);
}
}
}//GEN-LAST:event_closeButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel autopsyLabel;
private javax.swing.JLabel autopsyLogo;
private javax.swing.JButton closeButton;
private javax.swing.JLabel createNewLabel;
private javax.swing.JPanel editorPanel;
private javax.swing.JPanel logoPanel;
private javax.swing.JButton newCaseButton;
private javax.swing.JButton openCaseButton;
private javax.swing.JLabel openLabel;
private javax.swing.JButton openRecentButton;
private javax.swing.JLabel openRecentLabel;
private javax.swing.JCheckBox startupCheckBox;
private javax.swing.JLabel welcomeLabel;
// End of variables declaration//GEN-END:variables
/**
* Sets the Close button action listener.
*
* @param e the action listener
*/
public void setCloseButtonActionListener(ActionListener e){
closeButton.addActionListener(e);
}
/**
* Close the open recent cases window.
*/
public static void closeOpenRecentCasesWindow(){
//startupWindow.setVisible(false);
recentCasesWindow.dispose();
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.casemodule;
import java.io.File;
import java.util.regex.Pattern;
import javax.swing.filechooser.FileFilter;
/**
* FileFilter helper class. Matches files based on extension
*/
public class GeneralFilter extends FileFilter{
String[] ext;
String desc;
boolean isMultiple; // whether the filter can accept multiple files.
public GeneralFilter(String[] ext, String desc, boolean isMultiple){
this.ext = ext;
this.desc = desc;
this.isMultiple = isMultiple;
}
/**
* Checks whether the given file is accepted by this filter.
*
* @param f the given file
* @return boolean return true if accepted, false otherwise
*/
@Override
public boolean accept(File f) {
if(f.isDirectory()){
return true;
}
else{
Boolean result = false;
String name = f.getName().toLowerCase();
if(isMultiple){
for(int i = 0; i < ext.length; i++){
String regex = ext[i];
if (Pattern.matches(regex, name)){
result = result || true;
}
}
}
else{
for(int i = 0; i < ext.length; i++){
if (name.endsWith(ext[i]))
result = result || true;
}
}
return result;
}
}
/**
* Returns the description of this file filter
*
* @return desc return the description
*/
@Override
public String getDescription() {
return desc;
}
}

View File

@ -0,0 +1,136 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="caseDirLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="caseParentDirTextField" min="-2" pref="296" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="caseNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
<Component id="caseNameTextField" min="-2" pref="296" max="-2" attributes="0"/>
</Group>
<Component id="caseDirTextField" alignment="0" min="-2" pref="380" max="-2" attributes="1"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="caseDirBrowseButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseNameTextField" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseDirLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseParentDirTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseDirBrowseButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="caseDirTextField" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="32" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.jLabel1.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseNameLabel.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseDirLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseNameTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseNameTextField.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseParentDirTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseParentDirTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="caseDirBrowseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseDirBrowseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="caseDirBrowseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.jLabel2.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseDirTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseDirTextField.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,251 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* The wizard panel for the new case creation.
*
* @author jantonius
*/
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener{
private JFileChooser fc = new JFileChooser();
private NewCaseWizardPanel1 wizPanel;
NewCaseVisualPanel1(NewCaseWizardPanel1 wizPanel) {
initComponents();
this.wizPanel = wizPanel;
caseNameTextField.getDocument().addDocumentListener(this);
caseParentDirTextField.getDocument().addDocumentListener(this);
}
/**
* Returns the name of the this panel. This name will be shown on the left
* panel of the "New Case" wizard panel.
*
* @return name the name of this panel
*/
@Override
public String getName() {
return "Case Info";
}
/**
* Gets the case name that the user types on the case name text field.
*
* @return caseName the case name from the case name text field
*/
public String getCaseName(){
return this.caseNameTextField.getText();
}
/**
* Gets the base directory that the user typed on the base directory text field.
*
* @return baseDirectory the base directory from the case dir text field
*/
public String getCaseParentDir(){
return this.caseParentDirTextField.getText();
}
/** This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
caseNameLabel = new javax.swing.JLabel();
caseDirLabel = new javax.swing.JLabel();
caseNameTextField = new javax.swing.JTextField();
caseParentDirTextField = new javax.swing.JTextField();
caseDirBrowseButton = new javax.swing.JButton();
jLabel2 = new javax.swing.JLabel();
caseDirTextField = new javax.swing.JTextField();
jLabel1.setFont(new java.awt.Font("Tahoma", 1, 14));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel1.text_1")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(caseNameLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseNameLabel.text_1")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(caseDirLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirLabel.text")); // NOI18N
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseNameTextField.text_1")); // NOI18N
caseParentDirTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseParentDirTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(caseDirBrowseButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirBrowseButton.text")); // NOI18N
caseDirBrowseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
caseDirBrowseButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel2.text_1")); // NOI18N
caseDirTextField.setEditable(false);
caseDirTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirTextField.text_1")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(caseDirLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(caseParentDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(caseNameLabel)
.addGap(26, 26, 26)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(caseDirTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 380, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(caseDirBrowseButton)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(31, 31, 31)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNameLabel)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseDirLabel)
.addComponent(caseParentDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(caseDirBrowseButton))
.addGap(18, 18, 18)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(caseDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(32, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
/**
* The action when the Browse button is pressed. The browse button will pop
* up the file chooser window to choose where the user wants to save the
* case directory.
*
* @param evt the action event
*/
private void caseDirBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseDirBrowseButtonActionPerformed
// show the directory chooser where the case directory will be created
fc.setDragEnabled(false);
if(!caseParentDirTextField.getText().trim().equals("")){
fc.setSelectedFile(new File(caseParentDirTextField.getText()));
}
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
//fc.setSelectedFile(new File("C:\\Program Files\\"));
//disableTextField(fc); // disable all the text field on the file chooser
int returnValue = fc.showSaveDialog((Component)evt.getSource());
if(returnValue == JFileChooser.APPROVE_OPTION){
String path = fc.getSelectedFile().getPath();
caseParentDirTextField.setText(path); // put the path to the textfield
}
}//GEN-LAST:event_caseDirBrowseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton caseDirBrowseButton;
private javax.swing.JLabel caseDirLabel;
private javax.swing.JTextField caseDirTextField;
private javax.swing.JLabel caseNameLabel;
private javax.swing.JTextField caseNameTextField;
private javax.swing.JTextField caseParentDirTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration//GEN-END:variables
/**
* Gives notification that there was an insert into the document. The
* range given by the DocumentEvent bounds the freshly inserted region.
*
* @param e the document event
*/
@Override
public void insertUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* Gives notification that a portion of the document has been
* removed. The range is given in terms of what the view last
* saw (that is, before updating sticky positions).
*
* @param e the document event
*/
@Override
public void removeUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
@Override
public void changedUpdate(DocumentEvent e) {
this.wizPanel.fireChangeEvent();
updateUI(e);
}
/**
* The "listener" that listens when the fields in this form are updated.
* This method is used to determine when to enable / disable the "Finish" button.
*
* @param e the document event
*/
public void updateUI(DocumentEvent e) {
String caseName = this.caseNameTextField.getText();
String caseDir = this.caseParentDirTextField.getText();
if(!caseName.equals("") && !caseDir.equals("")){
caseDirTextField.setText( caseDir + File.separator + caseName);
wizPanel.setIsFinish(true);
}
else{
caseDirTextField.setText("");
wizPanel.setIsFinish(false);
}
}
}

View File

@ -0,0 +1,157 @@
/*
* 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.casemodule;
import java.awt.Component;
import java.awt.Dialog;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.sleuthkit.autopsy.logging.Log;
/**
* Action to open the New Case wizard.
*/
public final class NewCaseWizardAction extends CallableSystemAction {
private WizardDescriptor.Panel[] panels;
@Override
public void performAction() {
Log.noteAction(this.getClass());
// there's a case open
if (Case.existsCurrentCase()) {
// show the confirmation first to close the current case and open the "New Case" wizard panel
String closeCurrentCase = "Do you want to save and close this case and proceed with the new case creation?";
NotifyDescriptor d = new NotifyDescriptor.Confirmation(closeCurrentCase, "Warning: Closing the Current Case", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
try {
Case.getCurrentCase().closeCase(); // close the current case
newCaseAction(); // start the new case creation process
} catch (Exception ex) {
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.SEVERE, "Error closing case.", ex);
}
}
} else {
newCaseAction();
}
}
/**
* The method to perform new case creation
*/
private void newCaseAction() {
WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
// {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
wizardDescriptor.setTitle("New Case Information");
Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
dialog.setVisible(true);
dialog.toFront();
boolean finished = wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION; // check if it finishes (it's not cancelled)
boolean isCancelled = wizardDescriptor.getValue() == WizardDescriptor.CANCEL_OPTION; // check if the "Cancel" button is pressed
// if the finish button is pressed (not cancelled)
if (finished) {
// nothing to do, the Add Image dialog will pop up on its own because we've just opened a case with no images
}
// if Cancel button is pressed
if (isCancelled) {
// if there's case opened, close the case
if (Case.existsCurrentCase()) {
// close the previous case if there's any
CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class);
closeCase.actionPerformed(null);
}
}
panels = null; // reset the panel
}
/**
* Initialize panels representing individual wizard's steps and sets
* various properties for them influencing wizard appearance.
*/
private WizardDescriptor.Panel[] getPanels() {
if (panels == null) {
panels = new WizardDescriptor.Panel[]{
new NewCaseWizardPanel1()
};
String[] steps = new String[panels.length];
for (int i = 0; i < panels.length; i++) {
Component c = panels[i].getComponent();
// Default step name to component name of panel. Mainly useful
// for getting the name of the target chooser to appear in the
// list of steps.
steps[i] = c.getName();
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
// Sets step number of a component
// TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*:
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
// Sets steps names for a panel
jc.putClientProperty("WizardPanel_contentData", steps);
// Turn on subtitle creation on each step
jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
// Show steps on the left side with the image on the background
jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
// Turn on numbering of all steps
jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
}
}
}
return panels;
}
@Override
public String getName() {
return "New Case Wizard";
}
@Override
public String iconResource() {
return null;
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;
}
}

View File

@ -0,0 +1,278 @@
/*
* 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.casemodule;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.WizardValidationException;
import org.openide.util.HelpCtx;
/**
* The "New Case" wizard panel with a component on it. This class represents
* data of wizard step. It defers creation and initialization of UI component
* of wizard panel into getComponent() method.
*
* @author jantonius
*/
class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private NewCaseVisualPanel1 component;
private Boolean isFinish = false;
/**
* Get the visual component for the panel. In this template, the component
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
*
* @return component the UI component of this wizard panel
*/
@Override
public NewCaseVisualPanel1 getComponent() {
if (component == null) {
component = new NewCaseVisualPanel1(this);
}
return component;
}
/**
* Help for this panel. When the panel is active, this is used as the help
* for the wizard dialog.
*
* @return HelpCtx.DEFAULT_HELP the help for this panel
*/
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
}
/**
* Tests whether the panel is finished. If the panel is valid, the "Finish"
* button will be enabled.
*
* @return boolean true if all the fields are correctly filled, false otherwise
*/
@Override
public boolean isValid() {
// If it is always OK to press Next or Finish, then:
return isFinish;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
}
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/**
* Adds a listener to changes of the panel's validity.
*
* @param l the change listener to add
*/
@Override
public final void addChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.add(l);
}
}
/**
* Removes a listener to changes of the panel's validity.
*
* @param l the change listener to move
*/
@Override
public final void removeChangeListener(ChangeListener l) {
synchronized (listeners) {
listeners.remove(l);
}
}
/**
* This method is auto-generated. It seems that this method is used to listen
* to any change in this wizard panel.
*/
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
/**
* Sets the isFinish variable in this class. isFinish variable is used to
* determine whether the Finish button should be disabled or not.
*
* @param isFinish the given parameter (boolean)
*/
public void setIsFinish(Boolean isFinish) {
this.isFinish = isFinish;
fireChangeEvent();
}
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/**
* Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel.
*
* @param settings the setting to be read from
*/
@Override
public void readSettings(WizardDescriptor settings) {
}
/**
* Provides the wizard panel with the opportunity to update the settings
* with its current customized state. Rather than updating its settings
* with every change in the GUI, it should collect them, and then only save
* them when requested to by this method. This method can be called multiple
* times on one instance of WizardDescriptor.Panel.
*
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
settings.putProperty("caseName", getComponent().getCaseName());
settings.putProperty("caseParentDir", getComponent().getCaseParentDir());
}
@Override
public void validate() throws WizardValidationException {
String caseName = getComponent().getCaseName();
String caseParentDir = getComponent().getCaseParentDir();
String caseDirPath = caseParentDir + File.separator + caseName;
// check if case Name contain one of this following symbol:
// \ / : * ? " < > |
if (!Case.isValidName(caseName)) {
String errorMsg = "The Case Name cannot contain any of this following symbol: \\ / : * ? \" < > |";
validationError(errorMsg);
} else {
// check if the directory exist
if (new File(caseDirPath).exists()) {
// throw a warning to enter new data or delete the existing directory
String errorMsg = "Case directory '" + caseDirPath + "' already exists.";
validationError(errorMsg);
} else {
// check if the "base" directory path is absolute
File baseDir = new File(caseParentDir);
if (baseDir.isAbsolute()) {
// when the base directory doesn't exist
if (!baseDir.exists()) {
// get confirmation to create directory
String confMsg = "The base directory \'" + caseParentDir + "\' doesn't exist. \n \n Do you want to make that directory?";
NotifyDescriptor d2 = new NotifyDescriptor.Confirmation(confMsg, "Create directory", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d2.setValue(NotifyDescriptor.NO_OPTION);
Object res2 = DialogDisplayer.getDefault().notify(d2);
if (res2 != null && res2 == DialogDescriptor.YES_OPTION) {
// if user say yes
try {
createDirectory(caseDirPath, caseName);
} catch (Exception ex) {
String errorMsg = "Error: Couldn't create directory.";
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.WARNING, errorMsg, ex);
validationError(errorMsg);
}
}
if (res2 != null && res2 == DialogDescriptor.NO_OPTION) {
// if user say no
validationError("Prevented from creating base directory.");
}
} else {
try {
createDirectory(caseDirPath, caseName);
} catch (Exception ex) {
String errorMsg = "Error: Couldn't create directory.";
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.WARNING, errorMsg, ex);
validationError(errorMsg);
}
}
} else {
// throw a notification
String errorMsg = "ERROR: The Base Directory that you entered is not valid.\nPlease enter a valid Base Directory.";
validationError(errorMsg);
}
}
}
}
private void validationError(String errorMsg) throws WizardValidationException {
throw new WizardValidationException(this.getComponent(), errorMsg, null);
}
/*
* create the directory and create a new case
*/
private void createDirectory(final String caseDirPath, final String caseName) throws Exception {
// try to create the directory with the case name in the choosen parent directory
boolean success = Case.createCaseDirectory(caseDirPath, caseName);
// check if the directory is successfully created
if (!success) {
// delete the folder if we already created the folder and the error shows up
if (new File(caseDirPath).exists()) {
Case.deleteCaseDirectory(new File(caseDirPath));
}
String errorMsg = "ERROR: Could not create the case directory. \nPlease enter a valid Case Name and Directory.";
validationError(errorMsg);
} // the new case directory is successfully created
else {
// try to close Startup window if there's one
try {
StartupWindow.getInstance().close();
} catch (Exception ex) {
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.INFO, "Startup window didn't close as expected.", ex);
}
Case.create(caseDirPath, caseName); // create a new Case
}
}
}

View File

@ -0,0 +1,99 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="292" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="imagesTableScrollPane" pref="470" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="imagesTableScrollPane" min="-2" pref="170" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="OpenRecentCasePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="cancelButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="OpenRecentCasePanel.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="imagesTableScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="imagesTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="3" rowCount="0">
<Column editable="false" title="Case Name" type="java.lang.Object"/>
<Column editable="false" title="Path" type="java.lang.Object"/>
<Column editable="true" title="Open" type="java.lang.Object"/>
</Table>
</Property>
<Property name="showHorizontalLines" type="boolean" value="false"/>
<Property name="showVerticalLines" type="boolean" value="false"/>
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
</Property>
<Property name="updateSelectionOnSort" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,213 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
/**
* Panel show from the splash dialog that shows recent cases and allows them
* to be opened.
*/
class OpenRecentCasePanel extends javax.swing.JPanel {
static String[] caseName;
static String[] casePaths;
OpenRecentCasePanel() {
initComponents();
caseName = RecentCases.getInstance().getRecentCaseNames();
casePaths = RecentCases.getInstance().getRecentCasePaths();
int totalRecentCases = RecentCases.getInstance().getTotalRecentCases();
// create the headers and add all the rows
String[] headers = {"Case Name", "Path", "Open"};
String[][] rows = new String[totalRecentCases][];
final int lastColumn = headers.length - 1;
for(int i = 0; i < totalRecentCases; i++){
String path = casePaths[i];
String shortenPath = path;
if(path.length() > 50){
shortenPath = shortenPath.substring(0, 10 + shortenPath.substring(10).indexOf(File.separator) + 1) + "..." +
shortenPath.substring((shortenPath.length() - 20) + shortenPath.substring(shortenPath.length() - 20).indexOf(File.separator));
}
String[] thisRow = {caseName[i], shortenPath, path};
rows[i] = thisRow;
//model.insertRow(i, row);
}
// create the table inside with the imgPaths information
DefaultTableModel model = new DefaultTableModel(rows, headers)
{
@Override
// make the cells in the FileContentTable "read only"
public boolean isCellEditable(int row, int column){
return column == lastColumn; // make the last column (Remove button), only the editable
}
};
imagesTable.setModel(model);
// set the size of the remove column
TableColumn removeCol = imagesTable.getColumnModel().getColumn(lastColumn);
removeCol.setPreferredWidth(75);
removeCol.setMaxWidth(75);
removeCol.setMinWidth(75);
removeCol.setResizable(false);
// create the delete action to remove the image from the current case
Action open = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
// get the image path
JTable table = (JTable)e.getSource();
int modelRow = Integer.valueOf(e.getActionCommand());
String removeColumn = table.getValueAt(modelRow, lastColumn).toString();
// try to close Startup and openRecentCase window if they exist
try{
StartupWindow.getInstance().close();
CueBannerPanel.closeOpenRecentCasesWindow();
}
catch(Exception ex){
// no need to show the error message to the user.
//TODO: But maybe put the error message in the log in the future.
}
// Open the recent cases
try {
Case.open(removeColumn); // open the case
} catch (Exception ex) {
Logger.getLogger(OpenRecentCasePanel.class.getName()).log(Level.WARNING, "Error: couldn't open case.", ex);
}
}
};
ButtonColumn buttonColumn = new ButtonColumn(imagesTable, open, lastColumn, "Open");
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
cancelButton = new javax.swing.JButton();
imagesTableScrollPane = new javax.swing.JScrollPane();
imagesTable = new javax.swing.JTable();
jLabel1.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.jLabel1.text")); // NOI18N
cancelButton.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.cancelButton.text")); // NOI18N
cancelButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancelButtonActionPerformed(evt);
}
});
imagesTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Case Name", "Path", "Open"
}
) {
boolean[] canEdit = new boolean [] {
false, false, true
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
imagesTable.setShowHorizontalLines(false);
imagesTable.setShowVerticalLines(false);
imagesTable.getTableHeader().setReorderingAllowed(false);
imagesTable.setUpdateSelectionOnSort(false);
imagesTableScrollPane.setViewportView(imagesTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(292, 292, 292))
.addGroup(layout.createSequentialGroup()
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE)
.addContainerGap()))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(cancelButton)
.addContainerGap())))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cancelButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton;
private javax.swing.JTable imagesTable;
private javax.swing.JScrollPane imagesTableScrollPane;
private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables
/**
* Sets the Close button action listener.
*
* @param e the action listener
*/
public void setCloseButtonActionListener(ActionListener e){
this.cancelButton.addActionListener(e);
}
}

View File

@ -0,0 +1,442 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JMenuItem;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.logging.Log;
import org.openide.filesystems.FileUtil;
/**
* The action in this class is to clear the list of "Recent Cases".
* The constructor is called when the autopsy is running.
* All the method to create and modify the properties file are within this class
*/
public final class RecentCases extends CallableSystemAction implements Presenter.Menu {
static final int LENGTH = 5;
static final String NAME_PROP_KEY = "LBL_RecentCase_Name";
static final String PATH_PROP_KEY = "LBL_RecentCase_Path";
static final RecentCase BLANK_RECENTCASE = new RecentCase("", "");
// get the path of the case.properties file in the user directory
private final static String propFilePath = System.getProperty("netbeans.user") + File.separator + "autopsy.properties";
private final static RecentCases INSTANCE = new RecentCases();
private Properties properties;
private Deque<RecentCase> recentCases; // newest case is last case
/**
* Gets the instance of the RecentCases singleton.
*
*
* @return INSTANCE the RecentCases singleton
*/
static public RecentCases getInstance() {
return INSTANCE;
}
static private Properties makeDefaults() {
Properties temp = new Properties();
for (int i = 0; i < LENGTH; i++) {
temp.setProperty(nameKey(i), "");
temp.setProperty(pathKey(i), "");
}
return temp;
}
/** the constructor */
private RecentCases() {
properties = new Properties(makeDefaults());
try {
// try to load all the recent cases from the properties file in the home directory
InputStream inputStream = new FileInputStream(propFilePath);
properties.load(inputStream);
} catch (Exception ignore) {
// if cannot load it, we create a new properties file without any data inside it
try {
// create the directory and property file to store it
File output = new File(propFilePath);
if (!output.exists()) {
File parent = new File(output.getParent());
if (!parent.exists()) {
parent.mkdirs();
}
output.createNewFile();
FileOutputStream fos = new FileOutputStream(output);
properties.store(fos, "");
} else {
// if the property file already exist, throw an error that says cannot load that file
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not load the property file.", new Exception("The properties file already exist and can't load that file."));
}
} catch (IOException ex2) {
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not create the property file.", ex2);
}
}
// Load recentCases from properties
recentCases = new LinkedList<RecentCase>();
for (int i = 0; i < LENGTH; i++) {
final RecentCase rc = new RecentCase(getName(i), getPath(i));
if (!rc.equals(BLANK_RECENTCASE)) {
recentCases.add(rc);
}
}
}
private static void validateCaseIndex(int i) {
if (i < 0 || i >= LENGTH) {
throw new IllegalArgumentException("Recent case index " + i + " is out of range.");
}
}
private static String nameKey(int i) {
validateCaseIndex(i);
return NAME_PROP_KEY + Integer.toString(i + 1);
}
private static String pathKey(int i) {
validateCaseIndex(i);
return PATH_PROP_KEY + Integer.toString(i + 1);
}
private String getName(int i) {
return properties.getProperty(nameKey(i));
}
private String getPath(int i) {
return properties.getProperty(pathKey(i));
}
private void setName(int i, String name) {
properties.setProperty(nameKey(i), name);
}
private void setPath(int i, String path) {
properties.setProperty(pathKey(i), path);
}
private void setRecentCase(int i, RecentCase rc) {
setName(i, rc.name);
setPath(i, rc.path);
}
private static final class RecentCase {
String name, path;
/**
* @param name The case name or "" if a blank placeholder case
* @param path A normalized path (via FileUtil.normalizePath(path)) or "" if a blank placeholder case
*/
private RecentCase(String name, String path) {
this.name = name;
this.path = path;
}
/**
* Used when creating RecentCases with external data. The path must be
* normalized so that duplicate cases always have the same path.
* @param name The case name.
* @param unsafePath The (potentially un-normalized) case path.
* @return The created RecentCase.s
*/
static RecentCase createSafe(String name, String unsafePath) {
return new RecentCase(name, FileUtil.normalizePath(unsafePath));
}
// netbeans autogenerated hashCode
@Override
public int hashCode() {
int hash = 7;
hash = 13 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 13 * hash + (this.path != null ? this.path.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final RecentCase other = (RecentCase) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if ((this.path == null) ? (other.path != null) : !this.path.equals(other.path)) {
return false;
}
return true;
}
}
private void storeProperties() throws IOException {
properties.store(new FileOutputStream(new File(propFilePath)), "");
}
private void storeRecentCases() throws IOException {
int i = 0;
// store however many recent cases exist
for (RecentCase rc : recentCases) {
setRecentCase(i, rc);
i++;
}
// set the rest to blanks
while (i < LENGTH) {
setRecentCase(i, BLANK_RECENTCASE);
i++;
}
storeProperties();
}
/**
* Gets a menu item that can present this action in a JMenu.
*
* @return menuItem the representation menu item for this action
*/
@Override
public JMenuItem getMenuPresenter() {
return new UpdateRecentCases();
}
/**
* This action is used to clear all the recent cases menu options.
*
* @param e the action event
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
UpdateRecentCases.hasRecentCase = false;
recentCases.clear();
try {
// clear the properties file
storeRecentCases();
} catch (Exception ex) {
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not clear the properties file.", ex);
}
}
private void addRecentCase(RecentCase rc) {
// remove the case if it's already in the list
recentCases.remove(rc);
// make space if it's needed
if (recentCases.size() == LENGTH) recentCases.remove();
recentCases.add(rc);
}
/**
* Adds a recent case to the top of the list. If the case is already in the
* list, it will be removed before the new entry is added.
*
* @param name the name of the recent case to be added
* @param unsafePath the (potentially un-normalized) path of the case
* config file
*/
public void addRecentCase(String name, String unsafePath) {
RecentCase rc = RecentCase.createSafe(name, unsafePath);
addRecentCase(rc);
this.getMenuPresenter().setVisible(true); // invoke the contructor again
try {
storeRecentCases();
} catch (Exception ex) {
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex);
}
}
/**
* This method is used to update the name and path of a RecentCase.
*
* @param oldName the old recent case name
* @param oldPath the old recent case config file path
* @param newName the new recent case name
* @param newPath the new recent case config file path
* @throws Exception
*/
public void updateRecentCase(String oldName, String oldPath, String newName, String newPath) throws Exception {
RecentCase oldRc = RecentCase.createSafe(oldName, oldPath);
RecentCase newRc = RecentCase.createSafe(newName, newPath);
// remove all instances of the old recent case
recentCases.removeAll(Arrays.asList(oldRc));
addRecentCase(newRc);
this.getMenuPresenter().setVisible(true); // invoke the contructor again
try {
storeRecentCases();
} catch (Exception ex) {
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex);
}
}
/**
* Gets the total number of recent cases
*
* @return total total number of recent cases
*/
public int getTotalRecentCases() {
return recentCases.size();
}
/**
* This method is used to remove the selected name and path of the RecentCase
*
* @param name the case name to be removed from the recent case
* @param path the config file path to be removed from the recent case
*/
public void removeRecentCase(String name, String path) {
RecentCase rc = RecentCase.createSafe(name, path);
// remove all instances of the old recent case
recentCases.removeAll(Arrays.asList(rc));
this.getMenuPresenter().setVisible(true); // invoke the contructor again
// write the properties file
try {
storeRecentCases();
} catch (Exception ex) {
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex);
}
}
/**
* Gets the recent case names.
*
* @return caseNames An array String[LENGTH], newest case first, with any
* extra spots filled with ""
*/
public String[] getRecentCaseNames() {
String[] caseNames = new String[LENGTH];
Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator();
int i = 0;
while (mostRecentFirst.hasNext()) {
caseNames[i] = mostRecentFirst.next().name;
i++;
}
while (i < caseNames.length) {
caseNames[i] = "";
i++;
}
return caseNames;
}
/**
* Gets the recent case paths.
*
* @return casePaths An array String[LENGTH], newest case first, with any
* extra spots filled with ""
*/
public String[] getRecentCasePaths() {
String[] casePaths = new String[LENGTH];
Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator();
int i = 0;
while (mostRecentFirst.hasNext()) {
casePaths[i] = mostRecentFirst.next().path;
i++;
}
while (i < casePaths.length) {
casePaths[i] = "";
i++;
}
return casePaths;
}
// TODO: really shouldn't be done like this; need one common properties tracker
/**
* Gets the properties file paths.
*
* @return propertyPath
*/
public static String getPropertiesFilePath() {
return propFilePath;
}
/**
* This method does nothing. Use the actionPerformed instead of this method.
*/
@Override
public void performAction() {
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override
public String getName() {
//return NbBundle.getMessage(RecentCases.class, "CTL_RecentCases");
return "Clear Recent Cases";
}
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.sleuthkit.autopsy.logging.Log;
/**
* This class is used to add the action to the recent case menu item. When the
* the recent case menu is pressed, it should open that selected case.
*/
class RecentItems implements ActionListener {
String caseName;
String casePath;
private JPanel caller; // for error handling
/** the constructor */
public RecentItems(String caseName, String casePath){
this.caseName = caseName;
this.casePath = casePath;
}
/**
* Opens the recent case.
*
* @param e the action event
*/
@Override
public void actionPerformed(ActionEvent e) {
Log.noteAction(this.getClass());
// check if the file exists
if(caseName.equals("") || casePath.equals("") || (!new File(casePath).exists())){
// throw an error here
JOptionPane.showMessageDialog(caller, "Error: Case doesn't exist.", "Error", JOptionPane.ERROR_MESSAGE);
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore
}
else {
try {
Case.open(casePath); // open the case
} catch (Exception ex) {
Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case.", ex);
}
}
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.casemodule;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JFrame;
/**
* Displays
*/
public final class StartupWindow extends JDialog {
private static StartupWindow instance;
private static final String TITLE = "Welcome";
private static Dimension DIMENSIONS = new Dimension(750, 400);
private StartupWindow(JFrame frame, String title, boolean isModal) {
super(frame, title, isModal);
}
/**
* Get the startup window
* @return the startup window singleton
*/
public static synchronized StartupWindow getInstance() {
if (StartupWindow.instance == null) {
JFrame frame = new JFrame(TITLE);
boolean isModal = true;
StartupWindow.instance = new StartupWindow(frame, TITLE, isModal);
}
return instance;
}
/**
* Shows the startup window.
*/
public void display() {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
setSize(DIMENSIONS);
int w = this.getSize().width;
int h = this.getSize().height;
// set the location of the popUp Window on the center of the screen
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
CueBannerPanel welcomeWindow = new CueBannerPanel();
// add the command to close the window to the button on the Volume Detail Panel
welcomeWindow.setCloseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close();
}
});
add(welcomeWindow);
pack();
setResizable(false);
setVisible(true);
}
/**
* Closes the startup window.
*/
public void close() {
this.dispose();
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.casemodule;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import org.openide.awt.DynamicMenuContent;
import org.openide.util.actions.SystemAction;
/**
* This class is used to change / update the list of recent cases dynamically.
*/
public class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
int length;
static boolean hasRecentCase = false;
/** the constructor */
UpdateRecentCases(){
length = RecentCases.LENGTH;
}
/**
* Creates main menu/popup menu items. Null values will be later replaced by
* JSeparators. This method is called for popups and for menus. It's called
* each time a popup menu is constructed and just once for the main menu.
* Main menu updates happen through the synchMenuPresenters() method.
*
* @return
*/
@Override
public JComponent[] getMenuPresenters() {
String[] caseName = RecentCases.getInstance().getRecentCaseNames();
String[] casePath = RecentCases.getInstance().getRecentCasePaths();
JComponent[] comps = new JComponent[length + 2]; // + 2 for separator and clear menu
// if it has the recent menus, add them to the component list
for (int i = 0; i < length; i++) {
if((!caseName[i].equals(""))){
JMenuItem menuItem = new JMenuItem(caseName[i]);
menuItem.setActionCommand(caseName[i].toUpperCase());
menuItem.addActionListener(new RecentItems(caseName[i], casePath[i]));
comps[i] = menuItem;
hasRecentCase = hasRecentCase || true;
}
}
// if it has recent case, create clear menu
if(hasRecentCase){
comps[length] = new JSeparator();
JMenuItem clearMenu = new JMenuItem("Clear Recent Cases");
clearMenu.addActionListener(SystemAction.get(RecentCases.class));
comps[length+1] = clearMenu;
}
// otherwise, just create a disabled empty menu
else{
comps = new JComponent[1];
JMenuItem emptyMenu = new JMenuItem("-Empty-");
emptyMenu.addActionListener(new RecentItems("", ""));
comps[0] = emptyMenu;
comps[0].setEnabled(false);
}
return comps;
}
/**
* Updates main menu presenters. This method is called only by the main menu processing.
*
* @param jcs the previously used menu items returned by previous call to getMenuPresenters() or synchMenuPresenters()
* @return menu a new set of items to show in menu. Can be either an updated old set of instances or a completely new one.
*/
@Override
public JComponent[] synchMenuPresenters(JComponent[] jcs) {
return getMenuPresenters();
}
}

View File

@ -0,0 +1,802 @@
/*
* 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.casemodule;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
/**
*
* This class is used to create, access, and modify the XML configuration file,
* where we store the information about the case and image(s). This class uses
* the document handler to store the information about the case. The document
* handler will be created / opened when the case configuration file is created/
* opened.
*
* @author jantonius
*/
public class XMLCaseManagement implements CaseConfigFileInterface{
final static String TOP_ROOT_NAME = "AutopsyCase";
final static String CASE_ROOT_NAME = "Case";
// general metadata about the case file
final static String NAME = "Name";
final static String CREATED_DATE_NAME = "CreatedDate";
final static String MODIFIED_DATE_NAME = "ModifiedDate";
final static String SCHEMA_VERSION_NAME = "SchemaVersion";
final static String AUTOPSY_CRVERSION_NAME = "AutopsyCreatedVersion";
final static String AUTOPSY_MVERSION_NAME = "AutopsySavedVersion";
// disk image paths
final static String IMAGES_NAME = "Images";
final static String IMG_SET_NAME = "ImgSet";
final static String IMG_PATH_NAME = "ImgPath";
final static String IMG_DB_NAME = "ImgDb";
final static String NEXT_ID_NAME = "NextID";
// image attribute
final static String IMG_SET_COUNT = "count";
final static String IMG_SET_ID = "id";
final static String IMG_PATH_ID = "idx";
final static String TIMEZONE = "timezone";
// folders inside case directory
final static String LOG_FOLDER_NAME = "LogFolder";
final static String LOG_FOLDER_RELPATH = "Log";
final static String TEMP_FOLDER_NAME = "TempFolder";
final static String TEMP_FOLDER_RELPATH = "Temp";
final static String EXPORT_FOLDER_NAME = "ExportFolder";
final static String EXPORT_FOLDER_RELPATH = "Export";
// folders attribute
final static String RELATIVE_NAME = "Relative"; // relevant path info
// folder attr values
final static String RELATIVE_TRUE = "true"; // if it's a relative path
final static String RELATIVE_FALSE = "false"; // if it's not a relative path
// the document
private Document doc;
// general info
private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
private String caseDirPath; // case directory path
private String caseName; // case name
private String schemaVersion = "1.0";
private String autopsySavedVersion;
// for error handling
private JPanel caller;
private String className = this.getClass().toString();
/** The constructor */
XMLCaseManagement() throws Exception {
String autopsyVer = Case.getAutopsyVersion();
// System.setProperty("netbeans.buildnumber", autopsyVer); // set the current autopsy version // moved to CoreComponents installer
autopsySavedVersion = System.getProperty("netbeans.buildnumber");
}
/**
* Sets the case directory path of the case directory on the local variable
*
* @param givenPath the new path to be stored as case directory path
*/
private void setCaseDirPath(String givenPath){
caseDirPath = givenPath; // change this to change the xml file if needed
}
/**
* Sets the case Name on the XML configuration file
*
* @param givenCaseName the new case name to be set
*/
@Override
public void setCaseName(String givenCaseName) throws Exception {
// change this to change the xml file if needed
Element nameElement = (Element) getCaseElement().getElementsByTagName(NAME).item(0);
nameElement.setTextContent(givenCaseName);
doc.normalize();
// edit the modified data
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
try {
writeFile();
} catch (Exception ex) {
throw new Exception("Cannot update the case name in the XML config file.", ex);
}
}
/**
* Sets the case name internally (on local variable in this class)
*
* @param givenCaseName the new case name
*/
private void setName(String givenCaseName){
caseName = givenCaseName; // change this to change the xml file if needed
}
/**
* Gets the case Name from the document handler
*
* @return caseName the case name from the document handler
*/
@Override
public String getCaseName(){
if(doc == null){
return "";
}
else{
Element nameElement = (Element) getCaseElement().getElementsByTagName(NAME).item(0);
String result = nameElement.getTextContent();
return result;
}
}
/**
* Gets the case directory path that's stored in this class
*
* @return caseDirPath the case directory path
*/
public String getCaseDirectory(){
if(doc == null){
return "";
}
else{
return caseDirPath;
}
// Note: change this to get the case name from the xml file if needed
}
/**
* Gets the Root Element from the document handler
*
* @return rootElement the root element on the document handler
*/
private Element getRootElement(){
if(doc != null){
return doc.getDocumentElement();
}
else{
return null; // should throw error or exception
}
}
/**
* Gets the created Date from the document handler
*
* @return createdDate the creation date of this case
*/
protected String getCreatedDate(){
if(doc != null){
Element crDateElement = (Element) getRootElement().getElementsByTagName(CREATED_DATE_NAME).item(0);
return crDateElement.getTextContent();
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the Modified Date from the document handler
*
* @return modifiedDate the modification date of this case
*/
protected String getModifiedDate(){
if(doc != null){
Element mDateElement = (Element) getRootElement().getElementsByTagName(MODIFIED_DATE_NAME).item(0);
return mDateElement.getTextContent();
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the Autopsy Created Version from the document handler
*
* @return createdVersion the version of autopsy when this case was created
*/
protected String getCreatedVersion(){
if(doc != null){
Element crVerElement = (Element) getRootElement().getElementsByTagName(AUTOPSY_CRVERSION_NAME).item(0);
return crVerElement.getTextContent();
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the Autopsy Saved Version from the document handler
*
* @return savedVersion the latest version of autopsy when this case is saved
*/
protected String getSavedVersion(){
if(doc != null){
Element mVerElement = (Element) getRootElement().getElementsByTagName(AUTOPSY_MVERSION_NAME).item(0);
return mVerElement.getTextContent();
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the Schema Version from the document handler
*
* @return schemaVersion the schema version of this XML configuration file
*/
protected String getSchemaVersion(){
if(doc != null){
Element schemaVerElement = (Element) getRootElement().getElementsByTagName(SCHEMA_VERSION_NAME).item(0);
return schemaVerElement.getTextContent();
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the Case Element from the document handler
*
* @return caseElement the "Case" element
*/
private Element getCaseElement(){
if(doc != null){
return (Element) doc.getElementsByTagName(CASE_ROOT_NAME).item(0);
}
else{
return null; // should throw error or exception
}
}
/**
* Gets the full path to the log directory
*
* @return logDir the full path of the "Log" directory
*/
protected String getLogDir(){
if(doc != null){
Element logElement = (Element)getCaseElement().getElementsByTagName(LOG_FOLDER_NAME).item(0);
if(logElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
return caseDirPath + File.separator + logElement.getTextContent();
}
else{
return logElement.getTextContent();
}
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the full path to the temp directory
*
* @return tempDir the full path of the "Temp" directory
*/
protected String getTempDir(){
if(doc != null){
Element tempElement = (Element)getCaseElement().getElementsByTagName(TEMP_FOLDER_NAME).item(0);
if(tempElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
return caseDirPath + File.separator + tempElement.getTextContent();
}
else{
return tempElement.getTextContent();
}
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets the full path to the Export directory
*
* @return exportDir the full path of the "Export" directory
*/
protected String getExportDir(){
if(doc != null){
Element exportElement = (Element)getCaseElement().getElementsByTagName(EXPORT_FOLDER_NAME).item(0);
if(exportElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
return caseDirPath + File.separator + exportElement.getTextContent();
}
else{
return exportElement.getTextContent();
}
}
else{
return ""; // should throw error or exception
}
}
/**
* Gets image Element from the document handler
*
* @return imageElement the "Image" element
*/
private Element getImagesElement(){
if(doc != null){
return (Element) doc.getElementsByTagName(IMAGES_NAME).item(0);
}
else{
return null; // should throw error or exception
}
}
/**
* Looks up for the Image Set Element in the document handler with the given
* image ID.
*
* @param id the image ID
* @return element the "ImageSet" element
*/
protected Element getImageSetElement(int id){
if(doc != null){
Element result = null;
int totalImageSet = getImageSetCount();
for(int i = 0; i < totalImageSet; i++){
Element imageSetElement = (Element)getImagesElement().getElementsByTagName(IMG_SET_NAME).item(i);
int imgSetID = Integer.parseInt(imageSetElement.getAttribute(IMG_SET_ID));
if(id == imgSetID){
result = imageSetElement;
}
}
return result;
}
else{
return null; //TODO: should throw error or exception
}
}
/**
* Sets the ImgDb entry for corresponding image set in the document handler
*
* @param id the image ID
* @param path the image path
*/
protected void setImageSetDbPath(int id, String path){
Element imgDbElement = (Element) getImageSetElement(id).getElementsByTagName(IMG_DB_NAME).item(0);
imgDbElement.setTextContent(path);
imgDbElement.setAttribute(RELATIVE_NAME, RELATIVE_TRUE); // depends on the path (relative or not)
// if need to write the XML file immidiately, uncomment the code below
// writeFile();
}
/**
* Returns number of image sets in this case
*
* @return imageSetCount total number of imageSet in this case
*/
protected int getImageSetCount(){
return getImagesElement().getElementsByTagName(IMG_SET_NAME).getLength();
}
/**
* Returns a set of image paths of the given image ID in this case
*
* @param id the image ID
* @return imagePaths the image paths of the given imageID
*/
protected String[] getImageSet(int id){
Element imgSetElement = getImageSetElement(id);
int totalImagePaths = imgSetElement.getElementsByTagName(IMG_PATH_NAME).getLength(); // or use the attribute count
String[] result = new String[totalImagePaths];
for(int i = 0; i < totalImagePaths; i++){
Element imgPathElement = (Element) imgSetElement.getElementsByTagName(IMG_PATH_NAME).item(i);
if(imgPathElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
result[i] = caseDirPath + File.separator + imgPathElement.getTextContent();
}
else{
result[i] = imgPathElement.getTextContent();
}
}
return result;
}
/**
* Returns absolute path of image database of the given image ID.
*
* @param id the image ID
* @return dbPath the database path of the given image
*/
protected String getImageSetDbPath(int id){
Element imgDbElement = (Element) getImageSetElement(id).getElementsByTagName(IMG_DB_NAME).item(0);
if(imgDbElement.getAttribute(RELATIVE_NAME).equals(RELATIVE_TRUE)){
return caseDirPath + File.separator + imgDbElement.getTextContent();
}
else{
return imgDbElement.getTextContent();
}
}
/**
* Gets the next free image ID and and increments the internal counter
*
* @return imageID the next free image ID
*/
@Override
public int getNextImageID(){
Element imgElement = getImagesElement();
if(imgElement == null){
return -1; // which indicates the error
}
else{
String nextID = imgElement.getAttribute(NEXT_ID_NAME);
int result = Integer.parseInt(nextID);
// increment the nextID
int incNextID = result + 1;
getImagesElement().setAttribute(NEXT_ID_NAME, Integer.toString(incNextID));
// write the change to the config file immediately
try{
writeFile();
}
catch(Exception ex){
// TODO: throw exception further up
Logger logger = Logger.getLogger(this.className);
logger.log(Level.WARNING, "Error while trying to write the new NextID to the config file.", ex);
}
return result;
}
}
/**
* Returns an array of all image ID values in this case.
*
* @return imageIDs array of all image IDs in this case
*/
@Override
public int[] getImageIDs() {
int totalImageSet = getImageSetCount();
int[] result = new int[totalImageSet];
Element imgElement = getImagesElement();
for(int i = 0; i < totalImageSet; i++){
Element imgSetElement = (Element)imgElement.getElementsByTagName(IMG_SET_NAME).item(i);
result[i] = Integer.parseInt(imgSetElement.getAttribute(IMG_SET_ID));
}
return result;
}
/**
* Returns the HashSet of all timezone values of all images in this case.
*
* @return imageIDs the HashSet of all timezone values
*/
public HashSet<TimeZone> getTimeZone() {
HashSet<TimeZone> result = new HashSet<TimeZone>();
int totalImageSet = getImageSetCount();
Element imgElement = getImagesElement();
for(int i = 0; i < totalImageSet; i++){
Element imgSetElement = (Element)imgElement.getElementsByTagName(IMG_SET_NAME).item(i);
result.add(TimeZone.getTimeZone(imgSetElement.getAttribute(TIMEZONE)));
}
return result;
}
/**
* Removes the imageSet of the given image ID.
*
* @param imgID the image ID of the image that going to be removed
*/
public void removeImageSet(int imgID) {
Element imgElement = getImagesElement();
Element selectedElement = getImageSetElement(imgID);
imgElement.removeChild(selectedElement); // remove the imagesetElement
doc.normalize();
// edit the modified data
String newDate = dateFormat.format(new Date());
Element rootEl = getRootElement();
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
}
/**
* Initialize the basic values for a new case management file.
* Note: this is the schema version 1.0
*
* @param parentPath the name of the parent of the case directory.
* @param caseName the name of the config file to be located in the case directory
*/
protected void create(String dirPath, String caseName) throws Exception {
clear(); // clear the previous data
// set the case Name and Directory and the parent directory
setCaseDirPath(dirPath);
setName(caseName);
DocumentBuilder docBuilder;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
// throw an error here
try {
docBuilder = docFactory.newDocumentBuilder();
} catch (Exception ex) {
clear();
throw ex;
}
doc = docBuilder.newDocument();
Element rootElement = doc.createElement(TOP_ROOT_NAME); // <AutopsyCase> ... </AutopsyCase>
doc.appendChild(rootElement);
Element crDateElement = doc.createElement(CREATED_DATE_NAME); // <CreatedDate> ... </CreatedDate>
crDateElement.appendChild(doc.createTextNode(dateFormat.format(new Date())));
rootElement.appendChild(crDateElement);
Element mDateElement = doc.createElement(MODIFIED_DATE_NAME); // <ModifedDate> ... </ModifedDate>
mDateElement.appendChild(doc.createTextNode(dateFormat.format(new Date())));
rootElement.appendChild(mDateElement);
Element autVerElement = doc.createElement(AUTOPSY_CRVERSION_NAME); // <AutopsyVersion> ... </AutopsyVersion>
autVerElement.appendChild(doc.createTextNode(autopsySavedVersion));
rootElement.appendChild(autVerElement);
Element autSavedVerElement = doc.createElement(AUTOPSY_MVERSION_NAME); // <AutopsySavedVersion> ... </AutopsySavedVersion>
autSavedVerElement.appendChild(doc.createTextNode(autopsySavedVersion));
rootElement.appendChild(autSavedVerElement);
Element schVerElement = doc.createElement(SCHEMA_VERSION_NAME); // <SchemaVersion> ... </SchemaVersion>
schVerElement.appendChild(doc.createTextNode(schemaVersion));
rootElement.appendChild(schVerElement);
Element caseElement = doc.createElement(CASE_ROOT_NAME); // <Case> ... </Case>
rootElement.appendChild(caseElement);
Element nameElement = doc.createElement(NAME); // <Name> ... </Name>
nameElement.appendChild(doc.createTextNode(caseName));
caseElement.appendChild(nameElement);
Element exportElement = doc.createElement(EXPORT_FOLDER_NAME); // <ExportFolder> ... </ExportFolder>
exportElement.appendChild(doc.createTextNode(EXPORT_FOLDER_RELPATH));
exportElement.setAttribute(RELATIVE_NAME, "true");
caseElement.appendChild(exportElement);
Element logElement = doc.createElement(LOG_FOLDER_NAME); // <LogFolder> ... </LogFolder>
logElement.appendChild(doc.createTextNode(LOG_FOLDER_RELPATH));
logElement.setAttribute(RELATIVE_NAME, "true");
caseElement.appendChild(logElement);
Element tempElement = doc.createElement(TEMP_FOLDER_NAME); // <TempFolder> ... </TempFolder>
tempElement.appendChild(doc.createTextNode(TEMP_FOLDER_RELPATH));
tempElement.setAttribute(RELATIVE_NAME, "true");
caseElement.appendChild(tempElement);
// create the new images
Element imagesElement = doc.createElement(IMAGES_NAME); // <Images> ... </Images>
imagesElement.setAttribute(NEXT_ID_NAME, Integer.toString(0)); // add nextID to 0
rootElement.appendChild(imagesElement);
// write more code if needed ...
}
/**
* Writes the case management file to disk (from document handler to .aut file)
*
*/
@Override
public void writeFile() throws Exception {
if (doc == null || caseName.equals("")) {
throw new Exception("No set case to write management file for.");
}
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the data for the output file
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
// Write the DOM document to the file
Transformer xformer;// = TransformerFactory.newInstance().newTransformer();
TransformerFactory tfactory = TransformerFactory.newInstance();
try {
xformer = tfactory.newTransformer();
} catch (Exception ex) {
throw ex;
}
//Setup indenting to "pretty print"
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
try {
xformer.transform(source, result);
} catch (TransformerException ex) {
throw ex;
}
// preparing the output file
String xmlString = sw.toString();
File file = new File(caseDirPath + File.separator + caseName + ".aut");
// write the file
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
bw.write(xmlString);
bw.flush();
bw.close();
} catch (Exception ex) {
throw ex;
}
}
/**
* Opens the configuration file and load the document handler
* Note: this is for the schema version 1.0
*
* @param conFilePath the path of the XML case configuration file path
*/
@Override
public void open(String conFilePath) throws Exception{
clear();
File file = new File(conFilePath);
try{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(file);
doc.getDocumentElement().normalize();
Element rootEl = doc.getDocumentElement();
String rootName = rootEl.getNodeName();
// check if it's the autopsy case, if not, throws an error
if(!rootName.equals(TOP_ROOT_NAME)){
// throw an error ...
clear();
JOptionPane.showMessageDialog(caller, "Error: This is not an Autopsy config file (\"" + file.getName() + "\").\n \nDetail: \nCannot open a non-Autopsy config file (at " + className + ").", "Error", JOptionPane.ERROR_MESSAGE);
}
else{
/* Autopsy Created Version */
String createdVersion = getCreatedVersion(); // get the created version
// check if it has the same autopsy version as the current one
if(!createdVersion.equals(autopsySavedVersion)){
// if not the same version, update the saved version in the xml to the current version
getRootElement().getElementsByTagName(AUTOPSY_MVERSION_NAME).item(0).setTextContent(autopsySavedVersion);
}
/* Schema Version */
String schemaVer = getSchemaVersion();
// check if it has the same schema version as the current one
if(!schemaVer.equals(schemaVersion)){
// do something here if not the same version
// ... @Override
}
// set the case Directory and Name
setCaseDirPath(file.getParent());
String fullFileName = file.getName();
String fileName = fullFileName.substring(0, fullFileName.indexOf(".")); // remove the extension
setName(fileName);
}
}
catch(Exception e){
throw e;
// throw an error here
//JOptionPane.showMessageDialog(caller, "Error: This file is not supported (\"" + file.getName() + "\").\n \nDetail: \n" + e.getMessage() + " (at " + className + ")." , "Error", JOptionPane.ERROR_MESSAGE);
}
}
/**
* When user wants to close the case. This method writes any changes to the
* XML case configuration file, closes it and the document handler, and
* clears all the local variables / fields.
*
*/
@Override
public void close() throws Exception {
try {
writeFile(); // write any changes to xml
} catch (Exception ex) {
throw new Exception("Error: error while trying to close XML config file.", ex);
}
clear();
}
/**
* Clear the internal structures / variables
*/
private void clear() {
doc = null;
caseDirPath = "";
caseName = "";
}
/**
* Adds the image to the current document handler.
*
* @param images the paths of the images that want to be added
* @param currentID the ID of the image that want to be added
* @param timeZone the timeZone where the image is added
*/
protected void addImage(String[] images, long currentID, String timeZone) throws Exception {
String dbName = "image-" + currentID + ".db";
if (doc == null) {
throw new Exception("No case open.");
} else {
Element rootEl = getRootElement();
int imgCount = images.length; // how many given images to add to the config file
Element imagesElement = getImagesElement();
//int currentID = Integer.parseInt(imagesElement.getAttribute(NEXT_ID_NAME));
// add the latest image set
Element imgSetElement = doc.createElement(IMG_SET_NAME); // <ImgSet> ... </ImgSet>
imgSetElement.setAttribute(IMG_SET_COUNT, Integer.toString(imgCount));
imgSetElement.setAttribute(IMG_SET_ID, Long.toString(currentID));
imgSetElement.setAttribute(TIMEZONE, timeZone);
imagesElement.appendChild(imgSetElement);
// add all the image Path
for (int i = 0; i < imgCount; i++) {
Element imgPathElement = doc.createElement(IMG_PATH_NAME); // <ImgPath> ... </ImgPath>
imgPathElement.setAttribute(IMG_PATH_ID, Integer.toString(i));
imgPathElement.setAttribute(RELATIVE_NAME, "false");
imgPathElement.appendChild(doc.createTextNode(images[i]));
imgSetElement.appendChild(imgPathElement);
}
// add the database
Element imgDbElement = doc.createElement(IMG_DB_NAME); // <ImgDb> ... </ImgDb>
imgDbElement.setAttribute(RELATIVE_NAME, "true");
imgDbElement.appendChild(doc.createTextNode(dbName));
//imgDbElement.appendChild(doc.createTextNode("image-" + currentID + ".db"));
imgSetElement.appendChild(imgDbElement);
// edit the modified data
String newDate = dateFormat.format(new Date());
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
}
// JOptionPane.showMessageDialog(caller, "Error while trying to add the image to XML config file.\n \nDetail: \n" + e.getMessage() + " (at " + className + ").", "Error", JOptionPane.ERROR_MESSAGE);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE helpsetref PUBLIC "-//NetBeans//DTD JavaHelp Help Set Reference 1.0//EN" "http://www.netbeans.org/dtds/helpsetref-1_0.dtd">
<helpsetref url="nbdocs:/org/sleuthkit/autopsy/casemodule/docs/casemodule-hs.xml"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,258 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
<attr name="Menu\File\Separator2.instance_hidden\position" intvalue="100"/>
<attr name="Menu\File\Separator3.instance_hidden\position" intvalue="200"/>
<attr name="Menu\File\Separator4.instance_hidden\position" intvalue="400"/>
<attr name="Menu\File\org-netbeans-modules-print-action-PageSetupAction.shadow_hidden\position" intvalue="300"/>
<attr name="Menu\File\org-netbeans-modules-print-action-PrintAction.shadow_hidden\position" intvalue="500"/>
<attr name="Toolbars\File\org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance\iconBase" stringvalue="org/sleuthkit/autopsy/images/close-icon.gif"/>
<folder name="Actions">
<folder name="File">
<file name="org-sleuthkit-autopsy-casemodule-AddImageAction.instance">
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance">
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseNewAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseNewAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenActionOld.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseOpenActionOld"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseOpenActionOld"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction.instance">
</file>
<file name="org-sleuthkit-autopsy-casemodule-NewCaseAct.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.NewCaseAct"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_NewCaseAct"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-NewCaseAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.NewCaseAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_NewCaseAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseOpenAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_OpenAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseSaveAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseSaveAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_SaveCaseAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-RecentCases.instance">
</file>
</folder>
<folder name="Tools">
<file name="org-sleuthkit-autopsy-filebrowser-FileBrowserAction.instance"></file>
<file name="org-sleuthkit-autopsy-hashdatabase-HashDbMgmtAction.instance">
</file>
</folder>
<folder name="View">
<file name="org-netbeans-core-windows-actions-ToolbarsListAction.instance">
</file>
</folder>
<folder name="Window">
<file name="org-sleuthkit-autopsy-casemodule-testAction.instance">
<attr name="component" methodvalue="org.sleuthkit.autopsy.casemodule.testTopComponent.findInstance"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_testAction"/>
<attr name="instanceCreate" methodvalue="org.openide.windows.TopComponent.openAction"/>
</file>
<file name="org-sleuthkit-autopsy-filebrowser-FileBrowserAction.instance">
<attr name="component" methodvalue="org.sleuthkit.autopsy.filebrowser.FileBrowserTopComponent.findInstance"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.filebrowser.Bundle#CTL_FileBrowserAction"/>
<attr name="instanceCreate" methodvalue="org.openide.windows.TopComponent.openAction"/>
</file>
<file name="org-netbeans-core-windows-actions-GlobalPropertiesAction.instance_hidden"/>
<file name="org-sleuthkit-autopsy-filebrowser-ChangeViewAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.filebrowser.ChangeViewAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.filebrowser.Bundle#CTL_ChangeViewAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-filebrowser-DetailWindowAction.instance">
<attr name="component" methodvalue="org.sleuthkit.autopsy.filebrowser.DetailWindowTopComponent.findInstance"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.filebrowser.Bundle#CTL_DetailWindowAction"/>
<attr name="instanceCreate" methodvalue="org.openide.windows.TopComponent.openAction"/>
</file>
</folder>
</folder>
<folder name="Menu">
<folder name="File">
<file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/>
<attr name="position" intvalue="1212"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/>
<attr name="position" intvalue="1225"/>
</file>
<folder name="Open Recent Case">
<attr name="position" intvalue="1262"/>
<file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/>
</file>
</folder>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/>
<attr name="position" intvalue="1300"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="1318"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-AddImageAction.instance"/>
<attr name="position" intvalue="1336"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorAfter.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="1354"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction-separatorBefore.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="1340"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CasePropertiesAction.instance"/>
<attr name="position" intvalue="1345"/>
</file>
<file name="Separator2.instance_hidden"/>
<file name="Separator3.instance_hidden"/>
<file name="Separator4.instance_hidden"/>
<file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden">
<attr name="position" intvalue="200"/>
</file>
<file name="org-netbeans-modules-print-action-PrintAction.shadow_hidden">
<attr name="position" intvalue="300"/>
</file>
<file name="org-openide-actions-SaveAction.shadow_hidden"/>
<file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
<file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
</folder>
<file name="GoTo_hidden"/>
<folder name="Help">
<file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/>
</folder>
<folder name="Tools">
<file name="org-sleuthkit-autopsy-hashdatabase-HashDatabaseSettingsAction.shadow">
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-hashdatabase-HashDbMgmtAction.instance"/>
<attr name="position" intvalue="1000"/>
</file>
<file name="SeparatorAfterHashDatabaseSettings.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
<attr name="position" intvalue="1001"/>
</file>
<file name="Separator1.instance_hidden"/>
<file name="Separator3.instance_hidden"/>
<file name="org-netbeans-modules-autoupdate-ui-actions-PluginManagerAction.shadow_hidden"/>
<file name="org-netbeans-modules-favorites-templates-TemplatesAction.shadow_hidden"/>
<file name="org-netbeans-modules-options-OptionsWindowAction.shadow_hidden"/>
<file name="org-openide-actions-ToolsAction.shadow_hidden"/>
</folder>
<folder name="View">
<file name="org-netbeans-core-actions-HTMLViewAction.shadow_hidden"/>
<file name="org-netbeans-core-actions-LogAction.shadow_hidden"/>
<file name="org-netbeans-core-windows-actions-ToolbarsListAction.instance_hidden"/>
</folder>
<folder name="Window">
<file name="CloneDocumentAction.shadow_hidden"/>
<file name="CloseAllButThisAction.shadow_hidden"/>
<file name="CloseAllDocumentsAction.shadow_hidden"/>
<file name="DocumentsAction.shadow_hidden"/>
<file name="FileBrowserAction.shadow"/>
<file name="FileBrowserAction.shadow_hidden"/>
<file name="Output_hidden"/>
<file name="ProgressListAction.shadow_hidden"/>
<file name="SwitchToRecentDocumentAction.shadow_hidden"/>
<file name="ViewFavoritesTabAction.shadow_hidden"/>
<file name="org-netbeans-core-windows-actions-ResetWindowsAction.shadow_hidden"/>
<file name="testAction.shadow_hidden"/>
</folder>
</folder>
<folder name="Services">
<folder name="JavaHelp">
<file name="casemodule-helpset.xml" url="casemodule-helpset.xml">
<attr name="position" intvalue="3075"/>
</file>
</folder>
</folder>
<folder name="Shortcuts">
<file name="D-N.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/>
</file>
<file name="D-O.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/>
</file>
</folder>
<folder name="Toolbars">
<folder name="File">
<file name="org-sleuthkit-autopsy-casemodule-NewCaseAct.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseNewAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseNewAction"/>
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/images/new-icon.png"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
<attr name="position" intvalue="150"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseSaveAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseSaveAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_SaveCaseAction"/>
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/images/save-icon.png"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
<attr name="position" intvalue="300"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseOpenAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_OpenAction"/>
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/images/open-icon.png"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
<attr name="position" intvalue="200"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseCloseAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseCloseAct"/>
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/images/close-icon.png"/>
<attr name="noIconInMenu" boolvalue="false"/>
<attr name="position" intvalue="400"/>
</file>
<file name="sep1.instance">
<attr name="instanceClass" stringvalue="javax.swing.JToolBar$Separator"/>
<attr name="position" intvalue="500"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-AddImageAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.AddImageAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_AddImage"/>
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/images/addImage-icon.png"/>
<attr name="noIconInMenu" boolvalue="false"/>
<attr name="position" intvalue="550"/>
</file>
<file name="org-openide-actions-SaveAllAction.shadow_hidden">
<attr name="position" intvalue="100"/>
</file>
<file name="org-sleuthkit-autopsy-casemodule-CaseSaveAction.instance_hidden"/>
</folder>
<file name="UndoRedo_hidden"/>
</folder>
<folder name="Windows2">
<folder name="Components"/>
<folder name="Modes">
<folder name="editor"/>
<folder name="output"/>
</folder>
</folder>
</filesystem>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,10 @@
<body>
<p>A case contains one or more disk images and is the highest-level unit of an investigation. All data in a case will be stored in a single database and configuration file. A case must be open before analysis can occur. You will use a {@link org.sleuthkit.autopsy.casemodule.Case#Case Case} object to get access to the data being analyzed.</p>
<p>Case settings are stored in an XML file. See the {@link org.sleuthkit.autopsy.casemodule.XMLCaseManagement#XMLCaseManagement() XMLCaseManagement} class for more details.</p>
<p>Currently, only one case can be opened at a time. To determine the open case, use the static {@link org.sleuthkit.autopsy.casemodule.Case#getCurrentCase() Case.getCurrentCase()} method. Once you have the object for the currently open case, {@link org.sleuthkit.autopsy.casemodule.Case#getRootObjects() Case.getRootObjects()} will return the top-level Sleuth Kit Content modules. You can then get their children to go down the tree of data types. </p>
<p>To receive an event when cases are opened, closed, or changed, use the {@link org.sleuthkit.autopsy.casemodule.Case#addPropertyChangeListener(PropertyChangeListener) addPropertyChangeListener} method to register your class as a PropertyChangeListener. THis is most commonly required when developing a new {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer#DataExplorer() DataExplorer} module that needs to get data about the currently opened case. </p>
</body>

View File

@ -0,0 +1,2 @@
HashDatabaseManagementPanel.okayButton.text=Okay
HashDbPanel.fileSelectButton.text=Select...\n

View File

@ -0,0 +1,179 @@
/*
* 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.hashdatabase;
import java.io.File;
import java.util.logging.Level;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.SleuthkitJNI;
import org.sleuthkit.datamodel.TskException;
/**
* HashDb is based on the path to a database, and has methods to check the
* status of database and index files, and create indexes. One of these
* is created for every open hash database.
*/
class HashDb {
// Suffix added to the end of a database name to get its index file
private static final String INDEX_SUFFIX = "-md5.idx";
/**
* Path to database (database and/or index may not actually exist)
*/
String databasePath;
/**
* New {@link HashDb} for database at given path
* @param databasePath Path of database this instance represents (database
* and/or index may not actually exist)
*/
HashDb(String databasePath) {
this.databasePath = databasePath;
}
/**
* Checks if the database exists.
* @return true if a file exists at the database path, else false
*/
boolean databaseExists() {
return databaseFile().exists();
}
/**
* Checks if Sleuth Kit can open the index for the database path.
* @return true if the index was found and opened successfully, else false
*/
boolean indexExists() {
try {
return hasIndex(databasePath);
} catch (TskException ex) {
Log.get(this.getClass()).log(Level.WARNING, "Error checking if index exists.", ex);
return false;
}
}
/**
* Gets the database file.
* @return a File initialized with the database path
*/
File databaseFile() {
return new File(databasePath);
}
/**
* Gets the index file
* @return a File initialized with an index path derived from the database
* path
*/
File indexFile() {
return new File(toIndexPath(databasePath));
}
/**
* Checks if the index file is older than the database file
* @return true if there is are files at the index path and the database
* path, and the index file has an older modified-time than the database
* file, else false
*/
boolean isOutdated() {
File i = indexFile();
File db = databaseFile();
return i.exists() && db.exists() && isOlderThan(i, db);
}
/**
* Returns the status of the HashDb as determined from indexExists(),
* databaseExists(), and isOutdated()
* @return IndexStatus enum according to their definitions
*/
IndexStatus status() {
boolean i = this.indexExists();
boolean db = this.databaseExists();
if (i) {
if (db) {
return this.isOutdated() ? IndexStatus.INDEX_OUTDATED : IndexStatus.INDEX_CURRENT;
} else {
return IndexStatus.NO_DB;
}
} else {
return db ? IndexStatus.NO_INDEX : IndexStatus.NONE;
}
}
/**
* Tries to index the database (overwrites any existing index)
* @throws TskException if an error occurs in the SleuthKit bindings
*/
void createIndex() throws TskException {
SleuthkitJNI.createLookupIndex(databasePath);
//TODO: error checking
}
/**
* Checks if one file is older than an other
* @param a first file
* @param b second file
* @return true if the first file's last modified data is before the second
* file's last modified date
*/
private static boolean isOlderThan(File a, File b) {
return a.lastModified() < b.lastModified();
}
/**
* Determines if a path points to an index by checking the suffix
* @param path
* @return true if index
*/
static boolean isIndexPath(String path) {
return path.endsWith(INDEX_SUFFIX);
}
/**
* Derives database path from an image path by removing the suffix.
* @param indexPath
* @return
*/
static String toDatabasePath(String indexPath) {
return indexPath.substring(0, indexPath.lastIndexOf(INDEX_SUFFIX));
}
/**
* Derives image path from an database path by appending the suffix.
* @param databasePath
* @return
*/
static String toIndexPath(String databasePath) {
return databasePath.concat(INDEX_SUFFIX);
}
/**
* Calls Sleuth Kit method via JNI to determine whether there is an
* index for the given path
* @param databasePath path Path for the database the index is of
* (database doesn't have to actually exist)'
* @return true if index exists
* @throws TskException if there is an error in the JNI call
*/
static boolean hasIndex(String databasePath) throws TskException {
return SleuthkitJNI.lookupIndexExists(databasePath);
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.hashdatabase;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.logging.Level;
import javax.swing.JDialog;
import javax.swing.JFrame;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.Autopsy;
import org.sleuthkit.autopsy.logging.Log;
/**
* The HashDbMgmtAction opens the HashDbMgmtPanel in a dialog, and saves the
* settings of the panel if the Apply button is clicked.
* @author pmartel
*/
class HashDbMgmtAction extends CallableSystemAction {
private static final String ACTION_NAME = "Hash Database Management";
@Override
public void performAction() {
Log.noteAction(this.getClass());
try {
// Load settings from the property file
HashDbSettings hashDatabaseSettings = new HashDbSettings(Autopsy.getPropertyFile());
// create the popUp window for it
final JFrame frame = new JFrame(ACTION_NAME);
final JDialog popUpWindow = new JDialog(frame, ACTION_NAME, true); // to make the popUp Window to be modal
// initialize panel with loaded settings
final HashDbMgmtPanel panel = new HashDbMgmtPanel(hashDatabaseSettings);
// set action for the "Apply" button
panel.setApplyButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (panel.indexesExist()) {
try {
panel.saveSettings();
} catch (IOException ex) {
Log.get(HashDbMgmtAction.class).log(Level.WARNING, "Couldn't save hash database settings.", ex);
}
popUpWindow.dispose();
} else {
NotifyDescriptor d = new NotifyDescriptor.Message("All selected databases must have indexes.", NotifyDescriptor.INFORMATION_MESSAGE);
DialogDisplayer.getDefault().notify(d);
}
}
});
// add the panel to the popup window
popUpWindow.add(panel);
popUpWindow.pack();
popUpWindow.setResizable(false);
// set the location of the popUp Window on the center of the screen
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
double w = popUpWindow.getSize().getWidth();
double h = popUpWindow.getSize().getHeight();
popUpWindow.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
// display the window
popUpWindow.setVisible(true);
} catch (Exception ex) {
Log.get(HashDbMgmtAction.class).log(Level.WARNING, "Error displaying " + ACTION_NAME + " window.", ex);
}
}
@Override
public String getName() {
return ACTION_NAME;
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.hashdatabase;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.border.EmptyBorder;
/**
* Panel for displaying and editing the Hash Database settings.
* @author pmartel
*/
class HashDbMgmtPanel extends javax.swing.JPanel {
private HashDbSettings settings;
// text of panel for each database
private static final String INTRO_TEXT1 = "Hash lookups are conducted when an image is added to a case.";
private static final String INTRO_TEXT2 = "Lookup results can be found using the File Search feature.";
private static final String NSRL_NAME = "NIST NSRL Database";
private static final String NSRL_DESC = "Hashes that are known good and bad.";
private static final String KNOWN_BAD_NAME = "Known Bad Database";
private static final String KNOWN_BAD_DESC = "Hashes that are known bad.";
private JLabel introText1;
private JLabel introText2;
private HashDbPanel NSRLPanel;
private HashDbPanel knownBadPanel;
private JButton applyButton;
/**
*
* @param settings Settings to initialize the panel state from.
*/
HashDbMgmtPanel(HashDbSettings settings) {
this.settings = settings;
initComponents();
}
/**
* Sets a listener for the Apply button
* @param e The action listener
*/
void setApplyButtonActionListener(ActionListener e) {
this.applyButton.addActionListener(e);
}
/**
* Checks if indexes exist for all defined databases
* @return true if Sleuth Kit can open the indexes of all databases
* than have been selected
*/
boolean indexesExist() {
HashDb nsrl = this.NSRLPanel.db;
HashDb knownBad = this.knownBadPanel.db;
if (nsrl != null && !nsrl.indexExists()) {
return false;
}
if (knownBad != null && !knownBad.indexExists()) {
return false;
}
return true;
}
/**
* Modifies the given settings object to match the current panel state, and
* then persists it to its backing file.
* @throws IOException if there is an error saving the settings to a file
*/
void saveSettings() throws IOException {
this.settings.setNSRLDatabase(this.NSRLPanel.db);
this.settings.setKnownBadDatabase(this.knownBadPanel.db);
this.settings.save();
}
/**
* Initializes all the panel components
*/
private void initComponents() {
NSRLPanel = new HashDbPanel(this.settings.getNSRLDatabase(), HashDbMgmtPanel.NSRL_NAME, HashDbMgmtPanel.NSRL_DESC);
knownBadPanel = new HashDbPanel(this.settings.getKnownBadDatabase(), HashDbMgmtPanel.KNOWN_BAD_NAME, HashDbMgmtPanel.KNOWN_BAD_DESC);
applyButton = new JButton();
applyButton.setText("OK");
applyButton.setAlignmentX(Component.CENTER_ALIGNMENT);
introText1 = new JLabel();
introText1.setText(INTRO_TEXT1);
introText1.setBorder(new EmptyBorder(10, 10, 5, 10));
introText1.setAlignmentX(Component.CENTER_ALIGNMENT);
introText1.setMaximumSize(NSRLPanel.getMaximumSize());
introText2 = new JLabel();
introText2.setText(INTRO_TEXT2);
introText2.setBorder(new EmptyBorder(0, 10, 0, 10));
introText2.setAlignmentX(Component.CENTER_ALIGNMENT);
introText2.setMaximumSize(NSRLPanel.getMaximumSize());
BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS);
this.setLayout(layout);
this.add(introText1);
this.add(introText2);
this.add(NSRLPanel);
this.add(knownBadPanel);
this.add(applyButton);
this.add(Box.createRigidArea(new Dimension(0, 10)));
}
}

View File

@ -0,0 +1,129 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="databaseNameLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" max="-2" attributes="0">
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="indexButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="indexStatusLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="databasePathField" min="-2" pref="329" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="fileSelectButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="databaseDetailsLabel" alignment="0" max="32767" attributes="1"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="databaseNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="databaseDetailsLabel" min="-2" pref="14" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="databasePathField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileSelectButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="indexButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="indexStatusLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="1"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="databaseNameLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="databaseNameLabel" property="font" relativeSize="true" size="2"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="databaseName()" type="code"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="databasePathField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="path()" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="databasePathFieldActionPerformed"/>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="databasePathFieldFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="indexButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="indexOrReindex()" type="code"/>
</Property>
<Property name="enabled" type="boolean" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="indexable()" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="indexButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="indexStatusLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="indexStatus()" type="code"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="databaseDetailsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="databaseDetails()" type="code"/>
</Property>
<Property name="verticalAlignment" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="fileSelectButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbPanel.fileSelectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fileSelectButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,300 @@
/*
* 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.
*/
/*
* HashDbPanel.java
*
* Created on Oct 11, 2011, 2:44:56 PM
*/
package org.sleuthkit.autopsy.hashdatabase;
import java.awt.Cursor;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.TskException;
/**
* Panel for selecting a hash database.
* @author pmartel
*/
class HashDbPanel extends javax.swing.JPanel {
/**
* Current hash database backing the panel (can be null).
*/
HashDb db;
/**
* Name to title this database panel.
*/
String databaseName;
/**
* Details of this database slot.
*/
String databaseDetails;
private JFileChooser fc = new JFileChooser();
/**
* Create a panel from a current setting and description strings.
* @param db current hash database (can be null)
* @param databaseName name to title this database panel
* @param databaseDetails details of this database
*/
HashDbPanel(HashDb db, String databaseName, String databaseDetails) {
this.db = db; // nullable
this.databaseDetails = databaseDetails;
this.databaseName = databaseName;
fc.setDragEnabled(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
this.initComponents();
this.refresh();
}
/**
* Gets the string for the (re)index button.
* @return "Reindex" if the database and index exist, otherwise "Index"
*/
private String indexOrReindex() {
return (this.db != null) && this.db.databaseExists() && this.db.indexExists() ? "Reindex" : "Index";
}
private String databaseName() {
return this.databaseName;
}
private String databaseDetails() {
return this.databaseDetails;
}
/**
* @return Path to database to display in panel
*/
private String path() {
return (this.db != null) ? this.db.databasePath : "";
}
/**
* Short description of the index/db state (if there is one)
* @return
*/
private String indexStatus() {
return (this.db != null) ? db.status().message() : "";
}
/**
* Check if an index can be created.
* @return true if the database exists
*/
private boolean indexable() {
return (this.db != null) && db.databaseExists();
}
private boolean invalid() {
return (this.db != null) && this.db.status().equals(IndexStatus.NONE);
}
/**
* Updates the state of all panel elements.
*/
private void refresh() {
this.databasePathField.setText(this.path());
this.indexButton.setEnabled(this.indexable());
this.indexButton.setText(this.indexOrReindex());
this.indexStatusLabel.setText(this.indexStatus());
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
databaseNameLabel = new javax.swing.JLabel();
databasePathField = new javax.swing.JFormattedTextField();
indexButton = new javax.swing.JButton();
indexStatusLabel = new javax.swing.JLabel();
databaseDetailsLabel = new javax.swing.JLabel();
fileSelectButton = new javax.swing.JButton();
databaseNameLabel.setFont(databaseNameLabel.getFont().deriveFont(databaseNameLabel.getFont().getStyle() | java.awt.Font.BOLD, databaseNameLabel.getFont().getSize()+2));
databaseNameLabel.setText(databaseName());
databasePathField.setText(path());
databasePathField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
databasePathFieldActionPerformed(evt);
}
});
databasePathField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
databasePathFieldFocusLost(evt);
}
});
indexButton.setText(indexOrReindex());
indexButton.setEnabled(indexable());
indexButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
indexButtonActionPerformed(evt);
}
});
indexStatusLabel.setText(indexStatus());
databaseDetailsLabel.setText(databaseDetails());
databaseDetailsLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
fileSelectButton.setText(org.openide.util.NbBundle.getMessage(HashDbPanel.class, "HashDbPanel.fileSelectButton.text")); // NOI18N
fileSelectButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fileSelectButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(databaseNameLabel)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(indexButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(indexStatusLabel))
.addGroup(layout.createSequentialGroup()
.addComponent(databasePathField, javax.swing.GroupLayout.PREFERRED_SIZE, 329, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSelectButton))
.addComponent(databaseDetailsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(databaseNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(databaseDetailsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(databasePathField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSelectButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(indexButton)
.addComponent(indexStatusLabel))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void indexButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_indexButtonActionPerformed
if (this.db != null) {
try {
// change the cursor to "waiting cursor"
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
this.db.createIndex();
} finally {
this.setCursor(null);
}
} catch (TskException ex) {
Log.get(this.getClass()).log(Level.WARNING, "Couldn't create index.", ex);
}
}
this.refresh();
}//GEN-LAST:event_indexButtonActionPerformed
private void databasePathFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_databasePathFieldActionPerformed
// if field becomes editable: add handler
}//GEN-LAST:event_databasePathFieldActionPerformed
private void fileSelectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileSelectButtonActionPerformed
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
File f = fc.getSelectedFile();
try {
String filePath = f.getCanonicalPath();
if (HashDb.isIndexPath(filePath)) {
filePath = HashDb.toDatabasePath(filePath);
}
this.db = new HashDb(filePath);
} catch (IOException ex) {
Logger.getLogger(HashDbPanel.class.getName()).log(Level.WARNING, "Couldn't get selected file path.", ex);
return;
}
}
this.refresh();
}//GEN-LAST:event_fileSelectButtonActionPerformed
private void databasePathFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_databasePathFieldFocusLost
String path = databasePathField.getText().trim();
if (path.isEmpty()) {
this.db = null;
} else {
File f = new File(path);
try {
String filePath = f.getCanonicalPath();
if (HashDb.isIndexPath(filePath)) {
filePath = HashDb.toDatabasePath(filePath);
}
this.db = new HashDb(filePath);
} catch (IOException ex) {
Logger.getLogger(HashDbPanel.class.getName()).log(Level.WARNING, "Couldn't get selected file path.", ex);
return;
}
}
this.refresh();
}//GEN-LAST:event_databasePathFieldFocusLost
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel databaseDetailsLabel;
private javax.swing.JLabel databaseNameLabel;
private javax.swing.JFormattedTextField databasePathField;
private javax.swing.JButton fileSelectButton;
private javax.swing.JButton indexButton;
private javax.swing.JLabel indexStatusLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,166 @@
/*
* 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.hashdatabase;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
/**
* Loads and stores Hash Database settings from/to a property file
* @author pmartel
*/
public class HashDbSettings {
private static final String PROP_PREFIX = "HASHDB";
private static final String NSRL_PROP = "NSRL";
private static final String KNOWN_BAD_PROP = "KNOWN_BAD";
private File propertyFile;
private HashDb NSRLDatabase, knownBadDatabase;
/**
* @param propertyFile file to load settings from
* @throws IOException if there's an error loading the property file
* @throws FileNotFoundException if the property file can't be found
*/
public HashDbSettings(File propertyFile) throws IOException, FileNotFoundException {
this.propertyFile = propertyFile;
Properties temp = new Properties();
InputStream loadStream = new FileInputStream(propertyFile);
temp.load(loadStream);
loadStream.close();
String NSRL = getNSRL(temp);
String knownBad = getKnownBad(temp);
if (!NSRL.equals("")) {
this.NSRLDatabase = new HashDb(NSRL);
}
if (!knownBad.equals("")) {
this.knownBadDatabase = new HashDb(knownBad);
}
}
/**
* Writes settings to the property file
* @throws IOException if there's an error loading or writing to the
* property file
* @throws FileNotFoundException if the property file can't be found
*/
void save() throws IOException, FileNotFoundException {
Properties temp = new Properties();
InputStream loadStream = new FileInputStream(propertyFile);
temp.load(loadStream);
loadStream.close();
setNSRL(temp, this.NSRLDatabase != null ? this.NSRLDatabase.databasePath : "");
setKnownBad(temp, this.knownBadDatabase != null ? this.knownBadDatabase.databasePath : "");
String comments = "";
OutputStream storeStream = new FileOutputStream(propertyFile);
temp.store(storeStream, comments);
storeStream.close();
}
/**
* Returns the path the the selected NSRL hash database, or null if there is
* none selected.
* @return path or null
*/
public String getNSRLDatabasePath() {
return this.NSRLDatabase != null ? this.NSRLDatabase.databasePath : null;
}
/**
* Returns the path the the selected Known Bad hash database, or null if
* there is none selected.
* @return path or null
*/
public String getKnownBadDatabasePath() {
return this.knownBadDatabase != null ? this.knownBadDatabase.databasePath : null;
}
/**
* Gets NSRL database if there is one
* @return database (can be null)
*/
HashDb getNSRLDatabase() {
return this.NSRLDatabase;
}
/**
* Gets known bad database if there is one
* @return database (can be null)
*/
HashDb getKnownBadDatabase() {
return this.knownBadDatabase;
}
/**
* Set NSRL database
* @param nsrl database, or null to clear
*/
void setNSRLDatabase(HashDb nsrl) {
this.NSRLDatabase = nsrl;
}
/**
* Set known bad database
* @param knownBad known bad database, or null to clear
*/
void setKnownBadDatabase(HashDb knownBad) {
this.knownBadDatabase = knownBad;
}
// helper functions:
private static void setNSRL(Properties props, String databasePath) {
setProp(props, NSRL_PROP, databasePath);
}
private static void setKnownBad(Properties props, String databasePath) {
setProp(props, KNOWN_BAD_PROP, databasePath);
}
private static String getNSRL(Properties props) {
return getProp(props, NSRL_PROP);
}
private static String getKnownBad(Properties props) {
return getProp(props, KNOWN_BAD_PROP);
}
private static void setProp(Properties props, String propName, String propValue) {
props.setProperty(fullProp(propName), propValue);
}
private static String getProp(Properties props, String propName) {
return props.getProperty(fullProp(propName), "");
}
private static String fullProp(String propName) {
return PROP_PREFIX + "_" + propName;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.hashdatabase;
/**
* The status of a HashDb as determined from its indexExists(),
* databaseExists(), and isOutdated() methods
* @author pmartel
*/
enum IndexStatus {
/**
* The index and database both exist, and the index is older.
*/
INDEX_OUTDATED("Index is older than database."),
/**
* The index and database both exist, and the index is not older.
*/
INDEX_CURRENT("Database has index."),
/**
* The index exists but the database does not.
*/
NO_DB("Index does not have database."),
/**
* The database exists but the index does not.
*/
NO_INDEX("Database does not have index."),
/**
* Neither the index nor the database exists.
*/
NONE("No index or database.");
private String message;
/**
* @param message Short description of the state represented
*/
private IndexStatus(String message) {
this.message = message;
}
/**
* Get status message
* @return a short description of the state represented
*/
String message() {
return this.message;
}
}

View File

@ -0,0 +1,280 @@
/*
* 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.casemodule;
import java.awt.event.ActionEvent;
import javax.swing.JMenuItem;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class RecentCasesTest {
RecentCases instance;
public RecentCasesTest() {
instance = RecentCases.getInstance();
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
instance.actionPerformed(null);
}
@After
public void tearDown() {
}
/**
* Test of getInstance method, of class RecentCases.
*/
@Test
public void testGetInstance() {
System.out.println("getInstance");
RecentCases expResult = RecentCases.getInstance();
RecentCases result = RecentCases.getInstance();
assertEquals(expResult, result);
assertNotNull(result);
}
/**
* Test of getMenuPresenter method, of class RecentCases.
*/
@Test
public void testGetMenuPresenter() {
System.out.println("getMenuPresenter");
JMenuItem result = instance.getMenuPresenter();
assertNotNull(result);
}
/**
* Test of actionPerformed method, of class RecentCases.
*/
@Test
public void testActionPerformed() {
System.out.println("actionPerformed");
ActionEvent e = null;
instance.addRecentCase("test", "test");
instance.actionPerformed(e);
assertEquals(instance.getTotalRecentCases(), 0);
}
/**
* Test of addRecentCase method, of class RecentCases.
*/
@Test
public void testAddRecentCase() {
System.out.println("addRecentCase");
String name = "name";
String path = "C:\\path";
instance.addRecentCase(name, path);
instance.addRecentCase(name, path);
assertEquals(name, instance.getRecentCaseNames()[0]);
assertEquals(path, instance.getRecentCasePaths()[0]);
assertEquals(1, instance.getTotalRecentCases());
}
/**
* Test of updateRecentCase method, of class RecentCases.
*/
@Test
public void testUpdateRecentCase() throws Exception {
System.out.println("updateRecentCase");
String oldName = "oldName";
String oldPath = "C:\\oldPath";
String newName = "newName";
String newPath = "C:\\newPath";
instance.addRecentCase(oldName, oldPath);
instance.updateRecentCase(oldName, oldPath, newName, newPath);
assertEquals(newName, instance.getRecentCaseNames()[0]);
assertEquals(newPath, instance.getRecentCasePaths()[0]);
assertEquals(1, instance.getTotalRecentCases());
}
/**
* Test of getTotalRecentCases method, of class RecentCases.
*/
@Test
public void testGetTotalRecentCases() {
System.out.println("getTotalRecentCases");
int expResult = 0;
int result = instance.getTotalRecentCases();
assertEquals(expResult, result);
instance.addRecentCase("name", "path");
result = instance.getTotalRecentCases();
expResult = 1;
assertEquals(expResult, result);
}
/**
* Test of removeRecentCase method, of class RecentCases.
*/
@Test
public void testRemoveRecentCase() {
System.out.println("removeRecentCase");
String name = "name";
String path = "path";
String name1 = "name1";
String path1 = "path1";
instance.addRecentCase(name, path);
instance.addRecentCase(name1, path1);
instance.removeRecentCase(name, path);
assertEquals(1, instance.getTotalRecentCases());
instance.removeRecentCase(name, path);
assertEquals(1, instance.getTotalRecentCases());
instance.removeRecentCase(name1, path1);
assertEquals(0, instance.getTotalRecentCases());
}
/**
* Test of getRecentCaseNames method, of class RecentCases.
*/
@Test
public void testGetRecentCaseNames() {
System.out.println("getRecentCaseNames");
String[] expResult = {"","","","",""};
String[] result = instance.getRecentCaseNames();
assertArrayEquals(expResult, result);
String name = "name";
String path = "C:\\path";
String name1 = "name1";
String path1 = "C:\\path1";
instance.addRecentCase(name, path);
instance.addRecentCase(name1, path1);
String[] expResult1 = {name1,name,"","",""};
String[] result1 = instance.getRecentCaseNames();
assertArrayEquals(expResult1, result1);
}
/**
* Test of getRecentCasePaths method, of class RecentCases.
*/
@Test
public void testGetRecentCasePaths() {
System.out.println("getRecentCasePaths");
String[] expResult = {"","","","",""};
String[] result = instance.getRecentCasePaths();
assertArrayEquals(expResult, result);
String name = "name";
String path = "C:\\path";
String name1 = "name1";
String path1 = "C:\\path1";
instance.addRecentCase(name, path);
instance.addRecentCase(name1, path1);
String[] expResult1 = {path1, path,"","",""};
String[] result1 = instance.getRecentCasePaths();
assertArrayEquals(expResult1, result1);
}
/**
* Test of getName method, of class RecentCases.
*/
@Test
public void testGetName() {
System.out.println("getName");
String result = instance.getName();
assertNotNull(result);
}
/**
* Regression tests for TSK-227
* Make sure that paths are normalized, so that different representations of
* the same path don't result in duplicates.
*/
@Test
public void testNormalizePathAddRecentCase1() {
System.out.println("normalizePathAddRecentCase1");
String name = "name";
String path = "C:\\biig-case\\biig-case.aut";
String oddPath = "c:\\\\biig-case\\biig-case.aut";
instance.addRecentCase(name, path);
instance.addRecentCase(name, oddPath);
assertEquals(1, instance.getTotalRecentCases());
}
@Test
public void testNormalizePathAddRecentCase2() {
System.out.println("normalizePathAddRecentCase2");
String name = "name";
String path = "C:\\biig-case\\biig-case.aut";
String oddPath = "c:\\\\biig-case\\biig-case.aut";
instance.addRecentCase(name, oddPath);
instance.addRecentCase(name, path);
assertEquals(1, instance.getTotalRecentCases());
}
@Test
public void testNormalizePathUpdateRecentCase1() throws Exception {
System.out.println("normalizePathUpdateRecentCase1");
String oldName = "oldName";
String oldPath = "C:\\biig-case\\biig-case.aut";
String oddOldPath = "c:\\\\biig-case\\biig-case.aut";
String newName = "newName";
String newPath = "newPath";
instance.addRecentCase(oldName, oldPath);
instance.updateRecentCase(oldName, oddOldPath, newName, newPath);
assertEquals(1, instance.getTotalRecentCases());
}
@Test
public void testNormalizePathUpdateRecentCase2() throws Exception {
System.out.println("normalizePathUpdateRecentCase2");
String oldName = "oldName";
String oldPath = "C:\\biig-case\\biig-case.aut";
String oddOldPath = "c:\\\\biig-case\\biig-case.aut";
String newName = "newName";
String newPath = "newPath";
instance.addRecentCase(oldName, oddOldPath);
instance.updateRecentCase(oldName, oldPath, newName, newPath);
assertEquals(1, instance.getTotalRecentCases());
}
@Test
public void testNormalizePathRemoveRecentCase1() {
System.out.println("normalizePathRemoveRecentCase1");
String name = "name";
String path = "C:\\biig-case\\biig-case.aut";
String oddPath = "c:\\\\biig-case\\biig-case.aut";
instance.addRecentCase(name, path);
instance.removeRecentCase(name, oddPath);
assertEquals(0, instance.getTotalRecentCases());
}
@Test
public void testNormalizePathRemoveRecentCase2() {
System.out.println("normalizePathRemoveRecentCase2");
String name = "name";
String path = "C:\\biig-case\\biig-case.aut";
String oddPath = "c:\\\\biig-case\\biig-case.aut";
instance.addRecentCase(name, oddPath);
instance.removeRecentCase(name, path);
assertEquals(0, instance.getTotalRecentCases());
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="org.sleuthkit.autopsy.corecomponentinterfaces" default="netbeans" basedir=".">
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.corecomponentinterfaces.</description>
<import file="nbproject/build-impl.xml"/>
</project>

View File

@ -0,0 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.corecomponentinterfaces/0
OpenIDE-Module-Implementation-Version: 1
OpenIDE-Module-Layer: org/sleuthkit/autopsy/corecomponentinterfaces/layer.xml
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corecomponentinterfaces/Bundle.properties
OpenIDE-Module-Requires: org.openide.windows.WindowManager

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
-->
<project name="org.sleuthkit.autopsy.corecomponentinterfaces-impl" basedir="..">
<fail message="Please build using Ant 1.7.1 or higher.">
<condition>
<not>
<antversion atleast="1.7.1"/>
</not>
</condition>
</fail>
<property file="nbproject/private/suite-private.properties"/>
<property file="nbproject/suite.properties"/>
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
<property file="${suite.dir}/nbproject/platform.properties"/>
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="property"/>
<attribute name="value"/>
<sequential>
<property name="@{property}" value="@{value}"/>
</sequential>
</macrodef>
<property file="${user.properties.file}"/>
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
<condition>
<not>
<contains string="${cluster.path.evaluated}" substring="platform"/>
</not>
</condition>
</fail>
<import file="${harness.dir}/build.xml"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=70bb94aa
build.xml.script.CRC32=c5094f8f
build.xml.stylesheet.CRC32=a56c6a5b@1.42.2
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=70bb94aa
nbproject/build-impl.xml.script.CRC32=23300e1b
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.42.2

View File

@ -0,0 +1,3 @@
javac.source=1.6
javac.compilerargs=-Xlint -Xlint:-serial
spec.version.base=0.0

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>org.sleuthkit.autopsy.corecomponentinterfaces</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>org.netbeans.modules.settings</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.26.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.23.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.explorer</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.28.2</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.16.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.6.2</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.3.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.33.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0-1</release-version>
<specification-version>0.0</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages>
<package>org.sleuthkit.autopsy.corecomponentinterfaces</package>
</public-packages>
</data>
</configuration>
</project>

View File

@ -0,0 +1 @@
suite.dir=${basedir}/..

View File

@ -0,0 +1 @@
OpenIDE-Module-Name=CoreComponentInterfaces

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.corecomponentinterfaces;
import java.util.Collection;
import java.util.Iterator;
import org.openide.util.Lookup;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
* Responsible for opening and closing the core windows when a case is opened and closed.
*
* @author jantonius
*/
public class CoreComponentControl {
/**
* Opens all TopComponent windows that are needed ({@link DataExplorer}, {@link DataResult}, and
* {@link DataContent})
*/
public static void openCoreWindows() {
// TODO: there has to be a better way to do this.
// find the data explorer top components
Collection<? extends DataExplorer> dataExplorers = Lookup.getDefault().lookupAll(DataExplorer.class);
for (DataExplorer de : dataExplorers) {
TopComponent explorerWin = de.getTopComponent();
Mode m = WindowManager.getDefault().findMode("explorer");
m.dockInto(explorerWin); // redock into the explorer mode
explorerWin.open(); // open that top component
}
// find the data content top component
DataContent dc = Lookup.getDefault().lookup(DataContent.class);
TopComponent contentWin = dc.getTopComponent();
Mode m = WindowManager.getDefault().findMode("output");
m.dockInto(contentWin); // redock into the output mode
contentWin.open(); // open that top component
}
/**
* Closes all TopComponent windows that needed ({@link DataExplorer}, {@link DataResult}, and
* {@link DataContent})
*/
public static void closeCoreWindows() {
WindowManager wm = WindowManager.getDefault();
Iterator<Mode> iter = (Iterator<Mode>) wm.getModes().iterator();
while (iter.hasNext()) {
Mode mode = iter.next();
for (TopComponent tc : mode.getTopComponents()) {
tc.close();
}
}
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.corecomponentinterfaces;
import org.sleuthkit.autopsy.datamodel.ContentNode;
import java.beans.PropertyChangeListener;
import org.openide.windows.TopComponent;
/**
* The interface for the "bottom right component" window.
*
* @author jantonius
*/
public interface DataContent extends PropertyChangeListener {
/**
* Sets the "selected" node in this class
* @param selectedNode node to use
*/
public void setNode(ContentNode selectedNode);
/**
* Get the TopComponent that is used when displaying this DataContent
* @return TopComponent for this DataContent
*/
public TopComponent getTopComponent();
}

View File

@ -0,0 +1,63 @@
/*
* 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.corecomponentinterfaces;
import org.sleuthkit.autopsy.datamodel.ContentNode;
import java.awt.Component;
/**
* Responsible for a tab in the {@link DataContent} component. Displays the
* contents of the node passed to {@link setNode(ContentNode)}.
*/
public interface DataContentViewer {
/**
* Sets the node to display in the viewer. When called with null, must
* clear all references to previous nodes.
*/
public void setNode(ContentNode selectedNode);
/**
* Returns the title of this viewer.
*/
public String getTitle();
/**
* Get new DataContentViewer instance.
*/
public DataContentViewer getInstance();
/**
* Get Component to display this DataContentViewer
*/
public Component getComponent();
/**
* Resets the component in this viewer.
*/
public void resetComponent();
/**
* Checks whether the given node is supported by the viewer
* @param node Node to check for support
* @return True if supported, else false
*/
public boolean isSupported(ContentNode node);
}

View File

@ -0,0 +1,39 @@
/*
* 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.corecomponentinterfaces;
import java.beans.PropertyChangeListener;
import org.openide.windows.TopComponent;
/**
* The interface for the "top left component" window.
*
* @author jantonius
*/
public interface DataExplorer extends PropertyChangeListener {
/**
* Gets the TopComponent for rendering this DateExplorer
*
* @return the DataExplorer's TopComponent
*/
public TopComponent getTopComponent();
}

View File

@ -0,0 +1,55 @@
/*
* 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.corecomponentinterfaces;
import org.sleuthkit.autopsy.datamodel.ContentNode;
/**
* The interface for the "top right component" window.
*
* @author jantonius
*/
public interface DataResult {
/**
* Sets the "selected" node in this class.
*/
public void setNode(ContentNode selectedNode);
/**
* Gets the unique TopComponent ID of this class.
*
* @return preferredID the unique ID
*/
public String getPreferredID();
/**
* Sets the title of this TopComponent
*
* @param title the given title (String)
*/
public void setTitle(String title);
/**
* Checks if this is the main (uncloseable) instance of DataResult
*
* @return true if it is the main instance, otherwise false
*/
public boolean isMain();
}

View File

@ -0,0 +1,64 @@
/*
* 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.corecomponentinterfaces;
import org.sleuthkit.autopsy.datamodel.ContentNode;
import java.awt.Component;
/**
* Interface for the different viewers that show a set of nodes in the DataResult area.
* AbstractDataResultViewer has default implementations for the action handlers.
*
* @author jantonius
*/
public interface DataResultViewer {
/**
* Set the root node to display in this viewer. When called with null, must
* clear all references to previous nodes.
*/
public void setNode(ContentNode selectedNode);
/**
* Gets the title of this viewer
*/
public String getTitle();
/**
* Get a new instance of DataResultViewer
*/
public DataResultViewer getInstance();
/**
* Get Component to display this DataResultViewer
*/
public Component getComponent();
/**
* Resets the viewer.
*/
public void resetComponent();
/**
* Frees the objects that have been allocated by this viewer, in
* preparation for permanently disposing of it.
*/
public void clearComponent();
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
</filesystem>

View File

@ -0,0 +1,106 @@
<body>
<p>This package contains the interface classes that define the core components in Autopsy. These components are used in the difference zones of the GUI.</p>
<h2>Autopsy Zones</h2>
<p>There are three major zones in the Autopsy UI. The left hand side has the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer DataExplorer} zone. This area is where you can search for and explore data. It has all of the analysis smarts. An example of a DataExplorer is the directory tree that shows the hierarchy of directories (and hides the files from view).</p>
<p>The DataExplorer area identifies a subset of the data to show the user and passes the data to the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataResult DataResult}s area in the upper right. In the previous example, the contents of a specific folder would be passed to this area and displayed in a table or thumbnail form.</p>
<p>When a file or object is selected in the DataResult, it is passed to the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataContent DataContent} zone in the lower right. This is where file content can be viewed in hex form, strings, etc. </p>
<h2>Data Flow</h2>
<h3>Creating Nodes in DataExplorer</h3>
<p>Data flows between the areas inside of a NetBeans node. The DataExplorer modules create the NetBeans nodes. They query the SQLite database or do whatever they want to identify the set of files that are of interest. They create the NetBeans nodes based on Sleuthkit data model objects. See the org.sleuthkit.autopsy.datamodel package for more details on this. </p>
<h3>Getting Nodes to DataResult</h3>
<p>Each DataExplorer TopComponent is responsible for creating its own DataResult TopComponent to display its results. It can choose to re-use the same TopComponent for multiple searches (as DirectoryTree does) or it can choose to make a new one each time (as FileSearch does). The setNode() method on the DataResult object is used to set the root node to display. A dummy root node must be created as the parent if a parent does not already exist. </p>
<p>The DataExplorer is responsible for setting the double-click and right-click actions associated with the node. The default single click action is to pass data to DataContent. To override this, you must create a new DataResultViewer instance that overrides the propertyChange() method. The DataExplorer adds actions to wrapping the node in a FilterNode variant. The FilterNode then defines the actions for the node by overriding the getPreferredAction() and getActions() methods. As an example, org.sleuthkit.autopsy.directorytree.DataResultFilterNode and org.sleuthkit.autopsy.directorytree.DataResultFilterChildren wraps the nodes that are passed over by the DirectoryTree DataExplorer.</p>
DataResult can send data back to its DataExplorer by making a custom action that looks up it's instance (DataExplorer.getInstance()).
<h3>Getting Nodes to DataContent </h3>
<p> A default DataContent viewer is created when a case is opened. To display the contents of a node, it must be passed to a DataContent instance. The default single-click behavior of the DataResultViewers is to lookup the default DataContent TopComponent and pass the selected node to it. See {@link org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer#propertyChange(PropertyChangeEvent) AbstractDataResultViewer.propertyChange()} for details. </p>
<h2>Creating new Functionality</h2>
<h3>Creating a DataExplorer</h3>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li> Create a class that implements {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer DataExplorer}. We have been making the TopComponent class be the one that implements DataExplorer. Register this class as a DataExplorer service provider by specifying "@ServiceProvider(service=DataExplorer.class)" in the class or using layer.xml.
<li>Implement the methods required by the DataExplorer interface.
<li>Register the class to receive property change events from the org.sleuthkit.autopsy.Case module by using its addPropertyChangeListener() method.
<li>Access case data using the org.sleuthkit.autopsy.Case module.
<li>Create Nodes for the data objects using the techniques outlined in the previous section.
<li>Wrap the nodes in FilterNodes to define actions as outlined in the previous section.
<li>Send results to DataResults using the techniques outlined in the previous section.
</ol>
<h3>Creating a DataResultViewer</h3>
<p>DataResultTopComponent is the high-level window in the DataResult area. Each instance of this loads up all instances of DataResultViewers that have been registered with the system. Example viewers include the table and thumbnail views. If you want to make your own type of viewer, follow the steps below. Note that the table and thumbnail viewers come with Autopsy by default and can be used by all DataExplorers. </p>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li>Make a class that extends {@link org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer#AbstractDataResultViewer() AbstractDataResultViewer} and is registered as a service provider for the {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer DataResultViewer} class by specifying "@ServiceProvider(service = DataResultViewer.class)" or by using layer.xml. This class will extend JPanel. </li>
<li>See the previous sections on default actions.</li>
</ol>
<h3>Creating a DataContentViewer</h3>
<p>DataContentTopComponent is the high-level window in the DataContent area. Each instance of this loads up all instances of DataContentViewers that have been registered with the system. Example viewers include the strings and hexdump views. If you want to make your own type of viewer, follow the steps below. Note that the strings, hexdump, and image viewers come with Autopsy by default and can be used by all DataExplorers and DataResults. You only need to make a new DataContentViewer if these viewers do not satisfy your needs.</p>
<ol>
<li>Create a module from within NetBeans. It must be dependent on these modules:
<ul>
<li>Case
<li>CoreComponentInterfaces
<li>CoreComponents
<li>DataModel
<li>DialogsAPI (if pop-ups and such are going to be used)
<li>Explorer & Property Sheet API
<li>Lookup
<li>Nodes API
<li>Setting API
<li>UI Utilities API
<li>Utilities API
<li>Window System API
</ul>
<li>Make a class that implements {@link org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer DataContentViewer} and is registered as a service provider for DataContentViewer.class by specifying "@ServiceProvider(service = DataContentViewer.class)" or by using layer.xml. This class must extend JPanel. </li>
</ol>
</body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Some files were not shown because too many files have changed in this diff Show More