mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
4961 initial integration of RejView library into autopsy
This commit is contained in:
parent
cc92182522
commit
7bd569b665
@ -65,7 +65,6 @@
|
|||||||
|
|
||||||
<!--Copy other jars-->
|
<!--Copy other jars-->
|
||||||
<copy file="${thirdparty.dir}/rejistry/Rejistry-1.1-SNAPSHOT.jar" todir="${ext.dir}" />
|
<copy file="${thirdparty.dir}/rejistry/Rejistry-1.1-SNAPSHOT.jar" todir="${ext.dir}" />
|
||||||
<copy file="${thirdparty.dir}/rejView/RejView.jar" todir="${ext.dir}" />
|
|
||||||
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding.jar" todir="${ext.dir}" />
|
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding.jar" todir="${ext.dir}" />
|
||||||
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding-AllPlatforms.jar" todir="${ext.dir}" />
|
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding-AllPlatforms.jar" todir="${ext.dir}" />
|
||||||
<copy file="${thirdparty.dir}/stix/StixLib.jar" todir="${ext.dir}" />
|
<copy file="${thirdparty.dir}/stix/StixLib.jar" todir="${ext.dir}" />
|
||||||
|
@ -61,7 +61,6 @@ file.reference.pdfbox-2.0.13.jar=release\\modules\\ext\\pdfbox-2.0.13.jar
|
|||||||
file.reference.pdfbox-tools-2.0.13.jar=release\\modules\\ext\\pdfbox-tools-2.0.13.jar
|
file.reference.pdfbox-tools-2.0.13.jar=release\\modules\\ext\\pdfbox-tools-2.0.13.jar
|
||||||
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
|
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
|
||||||
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
|
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
|
||||||
file.reference.RejView.jar=release/modules/ext/RejView.jar
|
|
||||||
file.reference.rome-1.12.0.jar=release\\modules\\ext\\rome-1.12.0.jar
|
file.reference.rome-1.12.0.jar=release\\modules\\ext\\rome-1.12.0.jar
|
||||||
file.reference.sentiment-analysis-parser-0.1.jar=release\\modules\\ext\\sentiment-analysis-parser-0.1.jar
|
file.reference.sentiment-analysis-parser-0.1.jar=release\\modules\\ext\\sentiment-analysis-parser-0.1.jar
|
||||||
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
||||||
|
@ -685,10 +685,6 @@
|
|||||||
<runtime-relative-path>ext/Rejistry-1.1-SNAPSHOT.jar</runtime-relative-path>
|
<runtime-relative-path>ext/Rejistry-1.1-SNAPSHOT.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/Rejistry-1.1-SNAPSHOT.jar</binary-origin>
|
<binary-origin>release/modules/ext/Rejistry-1.1-SNAPSHOT.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/RejView.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/RejView.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
|
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
|
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.contentviewers;
|
package org.sleuthkit.autopsy.contentviewers;
|
||||||
|
|
||||||
import com.williballenthin.RejistryView.RejView;
|
|
||||||
import com.williballenthin.rejistry.RegistryHive;
|
import com.williballenthin.rejistry.RegistryHive;
|
||||||
import com.williballenthin.rejistry.RegistryHiveBuffer;
|
import com.williballenthin.rejistry.RegistryHiveBuffer;
|
||||||
import com.williballenthin.rejistry.RegistryParseException;
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
@ -33,6 +33,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import org.sleuthkit.autopsy.rejview.RejView;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
269
Core/src/org/sleuthkit/autopsy/rejview/HexView.java
Normal file
269
Core/src/org/sleuthkit/autopsy/rejview/HexView.java
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.BevelBorder;
|
||||||
|
import javax.swing.event.CaretEvent;
|
||||||
|
import javax.swing.event.CaretListener;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.DefaultHighlighter;
|
||||||
|
import javax.swing.text.JTextComponent;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HexView is a standard three-paned hex editor widget that displays binary data.
|
||||||
|
*
|
||||||
|
* Note, this does not do any intelligent paging of the data. You should estimate it to load three strings
|
||||||
|
* with length equal to the given ByteBuffer. So its probably not good to use this view with large files.
|
||||||
|
*/
|
||||||
|
public class HexView extends JPanel implements CaretListener {
|
||||||
|
private final static int DEFAULT_BYTES_PER_LINE = 0x10;
|
||||||
|
private final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
|
private final int _bytesPerLine;
|
||||||
|
private final ByteBuffer _buf;
|
||||||
|
private final JTextComponent _offsetView;
|
||||||
|
private final JTextComponent _hexView;
|
||||||
|
private final JTextComponent _asciiView;
|
||||||
|
private final JLabel _statusLabel;
|
||||||
|
private final Color _highlightColor;
|
||||||
|
private final DefaultHighlighter.DefaultHighlightPainter _highlighterPainter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the default 0x10 bytes per line.
|
||||||
|
*
|
||||||
|
* @param buf The binary data to display within this hex view.
|
||||||
|
*/
|
||||||
|
public HexView(ByteBuffer buf) {
|
||||||
|
this(buf, DEFAULT_BYTES_PER_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param buf The binary data to display within this hex view.
|
||||||
|
* @param bytesPerLine The number of bytes to display per line.
|
||||||
|
*/
|
||||||
|
public HexView(ByteBuffer buf, int bytesPerLine) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this._buf = buf;
|
||||||
|
this._bytesPerLine = bytesPerLine;
|
||||||
|
|
||||||
|
Font font = new Font("Monospaced", Font.PLAIN, 12);
|
||||||
|
|
||||||
|
this._offsetView = new JTextArea();
|
||||||
|
this._hexView = new JTextArea();
|
||||||
|
this._asciiView = new JTextArea();
|
||||||
|
JPanel _statusView = new JPanel();
|
||||||
|
|
||||||
|
// status bar
|
||||||
|
_statusView.setBorder(new BevelBorder(BevelBorder.LOWERED));
|
||||||
|
this.add(_statusView, BorderLayout.SOUTH);
|
||||||
|
_statusView.setPreferredSize(new Dimension(this.getWidth(), 18));
|
||||||
|
_statusView.setLayout(new BoxLayout(_statusView, BoxLayout.X_AXIS));
|
||||||
|
this._statusLabel = new JLabel("");
|
||||||
|
this._statusLabel.setHorizontalAlignment(SwingConstants.LEFT);
|
||||||
|
_statusView.add(this._statusLabel);
|
||||||
|
|
||||||
|
// right panes are split
|
||||||
|
JSplitPane _splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this._hexView, this._asciiView);
|
||||||
|
_splitPane.setResizeWeight(0.5);
|
||||||
|
_splitPane.setOneTouchExpandable(true);
|
||||||
|
_splitPane.setContinuousLayout(true);
|
||||||
|
|
||||||
|
// three panes sitting together
|
||||||
|
JPanel panes = new JPanel(new BorderLayout());
|
||||||
|
panes.add(this._offsetView, BorderLayout.WEST);
|
||||||
|
panes.add(_splitPane, BorderLayout.CENTER);
|
||||||
|
JScrollPane scroller = new JScrollPane(panes);
|
||||||
|
this.add(scroller, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
_offsetView.setFont(font);
|
||||||
|
_hexView.setFont(font);
|
||||||
|
_asciiView.setFont(font);
|
||||||
|
|
||||||
|
StringBuilder offsetSB = new StringBuilder();
|
||||||
|
StringBuilder hexSB = new StringBuilder();
|
||||||
|
StringBuilder asciiSB = new StringBuilder();
|
||||||
|
|
||||||
|
buf.position(0x0);
|
||||||
|
for (int i = 0; i < buf.limit(); i++) {
|
||||||
|
if (i % this._bytesPerLine == 0x0) {
|
||||||
|
offsetSB.append(String.format("0x%x \n", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte b = buf.get();
|
||||||
|
char[] hex = new char[3];
|
||||||
|
hex[0] = HEX_DIGITS[(b >>> 4) & 0x0F];
|
||||||
|
hex[1] = HEX_DIGITS[b & 0x0F];
|
||||||
|
hex[2] = ' ';
|
||||||
|
hexSB.append(hex);
|
||||||
|
|
||||||
|
if (b >= ' ' && b <= '~') {
|
||||||
|
asciiSB.append((char)b);
|
||||||
|
} else {
|
||||||
|
asciiSB.append('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % this._bytesPerLine == this._bytesPerLine - 1) {
|
||||||
|
hexSB.append("\n");
|
||||||
|
asciiSB.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._offsetView.setText(offsetSB.toString());
|
||||||
|
this._hexView.setText(hexSB.toString());
|
||||||
|
this._asciiView.setText(asciiSB.toString());
|
||||||
|
|
||||||
|
this._hexView.addCaretListener(this);
|
||||||
|
this._asciiView.addCaretListener(this);
|
||||||
|
|
||||||
|
this._asciiView.setSelectedTextColor(this._asciiView.getForeground());
|
||||||
|
this._hexView.setSelectedTextColor(this._asciiView.getForeground());
|
||||||
|
this._highlightColor = this._hexView.getSelectionColor();
|
||||||
|
this._highlighterPainter = new DefaultHighlighter.DefaultHighlightPainter(this._highlightColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clearHighlight removes any colors applied to the text views.
|
||||||
|
*/
|
||||||
|
private void clearHighlight() {
|
||||||
|
this._asciiView.getHighlighter().removeAllHighlights();
|
||||||
|
this._hexView.getHighlighter().removeAllHighlights();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setHighlight colors the given byte range.
|
||||||
|
* @param startByte The starting byte index of the selection.
|
||||||
|
* @param endByte The ending byte index of the selection.
|
||||||
|
*/
|
||||||
|
private void setHighlight(int startByte, int endByte) {
|
||||||
|
int startRows = (startByte - (startByte % this._bytesPerLine)) / this._bytesPerLine;
|
||||||
|
int endRows = (endByte - (endByte % this._bytesPerLine)) / this._bytesPerLine;
|
||||||
|
|
||||||
|
this.clearHighlight();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._asciiView.getHighlighter().addHighlight(startByte + startRows, endByte + endRows, this._highlighterPainter);
|
||||||
|
this._hexView.getHighlighter().addHighlight((startByte * 3) + startRows, (endByte * 3) + endRows, this._highlighterPainter);
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
System.out.println("bad location");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setSelection sets the given byte range as "selected", which from a GUI perspective means the
|
||||||
|
* bytes are highlighted, and the status bar updated.
|
||||||
|
* @param startByte The starting byte index of the selection.
|
||||||
|
* @param endByte The ending byte index of the selection.
|
||||||
|
*/
|
||||||
|
private void setSelection(int startByte, int endByte) {
|
||||||
|
this.setHighlight(startByte, endByte);
|
||||||
|
|
||||||
|
if (startByte != endByte) {
|
||||||
|
/**
|
||||||
|
* @param 1 Start
|
||||||
|
* @param 2 End
|
||||||
|
* @param 3 Len
|
||||||
|
*/
|
||||||
|
String statusTemplate = "Selection: %1$d to %2$d (len: %3$d) [0x%1$x to 0x%2$x (len: 0x%3$x)]";
|
||||||
|
this._statusLabel.setText(String.format(statusTemplate, startByte, endByte, endByte - startByte));
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* @param 1 Start
|
||||||
|
*/
|
||||||
|
String statusTemplate = "Position: %1$d [0x%1$x]";
|
||||||
|
this._statusLabel.setText(String.format(statusTemplate, startByte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// these flags are used to ensure we don't end up in a circular event loop where
|
||||||
|
// one component fires an event on the other, who volley's it back.
|
||||||
|
private int _hexLastSelectionStart = 0;
|
||||||
|
private int _hexLastSelectionEnd = 0;
|
||||||
|
private int _asciiLastSelectionStart = 0;
|
||||||
|
private int _asciiLastSelectionEnd = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void caretUpdate(CaretEvent e) {
|
||||||
|
if (e.getMark() == e.getDot()) {
|
||||||
|
this.clearHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.getSource() == this._asciiView) {
|
||||||
|
int startByte = e.getMark();
|
||||||
|
int endByte = e.getDot();
|
||||||
|
|
||||||
|
if (startByte > endByte) {
|
||||||
|
int t = endByte;
|
||||||
|
endByte = startByte;
|
||||||
|
startByte = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the number of line endings before the start,end points
|
||||||
|
int startRows = (startByte - (startByte % this._bytesPerLine)) / this._bytesPerLine;
|
||||||
|
int endRows = (endByte - (endByte % this._bytesPerLine)) / this._bytesPerLine;
|
||||||
|
|
||||||
|
// the byte index of the start,end points in the ASCII view
|
||||||
|
startByte = startByte - startRows;
|
||||||
|
endByte = endByte - endRows;
|
||||||
|
|
||||||
|
// avoid the loop
|
||||||
|
if (_asciiLastSelectionStart == startByte && _asciiLastSelectionEnd == endByte) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_asciiLastSelectionStart = startByte;
|
||||||
|
_asciiLastSelectionEnd = endByte;
|
||||||
|
|
||||||
|
this.setSelection(startByte, endByte);
|
||||||
|
} else if (e.getSource() == this._hexView) {
|
||||||
|
int startByte = e.getMark();
|
||||||
|
int endByte = e.getDot();
|
||||||
|
|
||||||
|
if (startByte > endByte) {
|
||||||
|
int t = endByte;
|
||||||
|
endByte = startByte;
|
||||||
|
startByte = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the number of line endings before the start,end points
|
||||||
|
int startRows = (startByte - (startByte % this._bytesPerLine)) / (3 * this._bytesPerLine);
|
||||||
|
int endRows = (endByte - (endByte % this._bytesPerLine)) / (3 * this._bytesPerLine);
|
||||||
|
|
||||||
|
// the byte index of the start,end points in the ASCII view
|
||||||
|
startByte = startByte - startRows;
|
||||||
|
startByte = startByte / 3;
|
||||||
|
endByte = endByte - endRows;
|
||||||
|
endByte = endByte / 3;
|
||||||
|
|
||||||
|
if (_hexLastSelectionStart == startByte && _hexLastSelectionEnd == endByte) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_hexLastSelectionStart = startByte;
|
||||||
|
_hexLastSelectionEnd = endByte;
|
||||||
|
|
||||||
|
this.setSelection(startByte, endByte);
|
||||||
|
} else {
|
||||||
|
System.out.println("from unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.HexDump;
|
||||||
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
|
import com.williballenthin.rejistry.ValueData;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a ValueData to a string similar to Regedit.exe on Windows.
|
||||||
|
* For an example, see the nice sample here:
|
||||||
|
* http://raja5.files.wordpress.com/2009/08/wincleanup_regedit.jpg
|
||||||
|
*/
|
||||||
|
public class RegeditExeValueFormatter {
|
||||||
|
public static String format(ValueData val) throws UnsupportedEncodingException, RegistryParseException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
switch(val.getValueType()) {
|
||||||
|
case REG_SZ:
|
||||||
|
case REG_EXPAND_SZ:{
|
||||||
|
|
||||||
|
String valString = val.getAsString();
|
||||||
|
if (valString.length() == 0) {
|
||||||
|
sb.append("(value not set)");
|
||||||
|
} else {
|
||||||
|
sb.append(valString);
|
||||||
|
}
|
||||||
|
if (sb.length() > 48) {
|
||||||
|
sb.setLength(45);
|
||||||
|
sb.append("...");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REG_MULTI_SZ: {
|
||||||
|
Iterator<String> it = val.getAsStringList().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
sb.append(it.next());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 48) {
|
||||||
|
sb.setLength(45);
|
||||||
|
sb.append("...");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REG_DWORD:
|
||||||
|
case REG_BIG_ENDIAN: {
|
||||||
|
sb.append(String.format("0x%08x (%d)", val.getAsNumber(), val.getAsNumber()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REG_QWORD: {
|
||||||
|
sb.append(String.format("0x%016x (%d)", val.getAsNumber(), val.getAsNumber())); // can you even do %016x?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
ByteBuffer valData = val.getAsRawData();
|
||||||
|
valData.position(0x0);
|
||||||
|
for (int i = 0; i < Math.min(16, valData.limit()); i++) {
|
||||||
|
byte b = valData.get();
|
||||||
|
sb.append(HexDump.toHexString(b));
|
||||||
|
if (i != 15) { // magic number, sorry.
|
||||||
|
sb.append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valData.limit() > 16) {
|
||||||
|
sb.append("...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
95
Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyNode.java
Normal file
95
Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyNode.java
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryKey;
|
||||||
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
|
import com.williballenthin.rejistry.RegistryValue;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RejTreeKeyNode implements RejTreeNode {
|
||||||
|
|
||||||
|
private final RegistryKey _key;
|
||||||
|
|
||||||
|
public RejTreeKeyNode(RegistryKey key) {
|
||||||
|
this._key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
try {
|
||||||
|
return this._key.getName();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
System.err.println("Failed to parse key name");
|
||||||
|
return "PARSE FAILED.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasChildren() {
|
||||||
|
try {
|
||||||
|
return this._key.getValueList().size() > 0 || this._key.getSubkeyList().size() > 0;
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
System.err.println("Failed to parse key children.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RejTreeNode> getChildren() {
|
||||||
|
LinkedList<RejTreeNode> children = new LinkedList<RejTreeNode>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Iterator<RegistryKey> keyit = this._key.getSubkeyList().iterator();
|
||||||
|
while (keyit.hasNext()) {
|
||||||
|
children.add(new RejTreeKeyNode(keyit.next()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<RegistryValue> valueit = this._key.getValueList().iterator();
|
||||||
|
while (valueit.hasNext()) {
|
||||||
|
children.add(new RejTreeValueNode(valueit.next()));
|
||||||
|
}
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
System.err.println("Failed to parse key children.");
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scope: package-protected
|
||||||
|
*/
|
||||||
|
RegistryKey getKey() {
|
||||||
|
return this._key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO(wb): this isn't exactly MVC...
|
||||||
|
*/
|
||||||
|
public RejTreeNodeView getView() {
|
||||||
|
return new RejTreeKeyView(this);
|
||||||
|
}
|
||||||
|
}
|
143
Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java
Normal file
143
Core/src/org/sleuthkit/autopsy/rejview/RejTreeKeyView.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
|
import com.williballenthin.rejistry.RegistryValue;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.table.TableColumn;
|
||||||
|
import javax.swing.table.TableColumnModel;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class RejTreeKeyView extends RejTreeNodeView {
|
||||||
|
private final RejTreeKeyNode _node;
|
||||||
|
|
||||||
|
public RejTreeKeyView(RejTreeKeyNode node) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this._node = node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param 1 Name
|
||||||
|
* @param 2 Number of subkeys
|
||||||
|
* @param 3 Number of values
|
||||||
|
*/
|
||||||
|
String metadataTemplate = "" +
|
||||||
|
"<html>" +
|
||||||
|
"<i>Name:</i> <b>%1$s</b><br/>" +
|
||||||
|
"<i>Number of subkeys:</i> %2$d<br/>" +
|
||||||
|
"<i>Number values:</i> %3$d<br/>" +
|
||||||
|
"</html>";
|
||||||
|
String keyName;
|
||||||
|
int numSubkeys;
|
||||||
|
int numValues;
|
||||||
|
|
||||||
|
try {
|
||||||
|
keyName = this._node.getKey().getName();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
keyName = "FAILED TO PARSE KEY NAME";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
numSubkeys = this._node.getKey().getSubkeyList().size();
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
numSubkeys = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
numValues = this._node.getKey().getValueList().size();
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
numValues = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JLabel metadataLabel = new JLabel(String.format(metadataTemplate, keyName, numSubkeys, numValues), JLabel.LEFT);
|
||||||
|
metadataLabel.setBorder(BorderFactory.createTitledBorder("Metadata"));
|
||||||
|
metadataLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
|
||||||
|
String[] columnNames = {"Name", "Type", "Value"};
|
||||||
|
Object[][] data = new Object[numValues][3];
|
||||||
|
|
||||||
|
try {
|
||||||
|
Iterator<RegistryValue> valit = this._node.getKey().getValueList().iterator();
|
||||||
|
int i = 0;
|
||||||
|
while (valit.hasNext()) {
|
||||||
|
RegistryValue val = valit.next();
|
||||||
|
if (val.getName().length() == 0) {
|
||||||
|
data[i][0] = "(Default)";
|
||||||
|
} else {
|
||||||
|
data[i][0] = val.getName();
|
||||||
|
}
|
||||||
|
data[i][1] = val.getValueType().toString();
|
||||||
|
data[i][2] = RegeditExeValueFormatter.format(val.getValue());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
// TODO(wb): need to add some warning here...
|
||||||
|
// not sure how to do it, though, since some data may have already been added
|
||||||
|
// but not necessarily all of it
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e) {
|
||||||
|
// TODO(wb): need to add some warning here...
|
||||||
|
}
|
||||||
|
|
||||||
|
JTable table = new JTable(data, columnNames);
|
||||||
|
table.setAutoCreateRowSorter(true);
|
||||||
|
table.setCellSelectionEnabled(false);
|
||||||
|
table.setRowSelectionAllowed(true);
|
||||||
|
table.setIntercellSpacing(new Dimension(10, 1));
|
||||||
|
|
||||||
|
// inspiration for packing the columns from:
|
||||||
|
// http://jroller.com/santhosh/entry/packing_jtable_columns
|
||||||
|
if (table.getColumnCount() > 0) {
|
||||||
|
int width[] = new int[table.getColumnCount()];
|
||||||
|
int total = 0;
|
||||||
|
for (int j = 0; j < width.length; j++) {
|
||||||
|
TableColumn column = table.getColumnModel().getColumn(j);
|
||||||
|
int w = (int)table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, column.getIdentifier(), false, false, -1, j).getPreferredSize().getWidth();
|
||||||
|
|
||||||
|
if (table.getRowCount() > 0) {
|
||||||
|
for (int i = 0; i < table.getRowCount(); i++) {
|
||||||
|
int pw = (int)table.getCellRenderer(i, j).getTableCellRendererComponent(table, table.getValueAt(i, j), false, false, i, j).getPreferredSize().getWidth();
|
||||||
|
w = Math.max(w, pw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
width[j] += w + table.getIntercellSpacing().width;
|
||||||
|
total += w + table.getIntercellSpacing().width;
|
||||||
|
}
|
||||||
|
width[width.length - 1] += table.getVisibleRect().width - total;
|
||||||
|
TableColumnModel columnModel = table.getColumnModel();
|
||||||
|
for (int j = 0; j < width.length; j++) {
|
||||||
|
TableColumn column = columnModel.getColumn(j);
|
||||||
|
table.getTableHeader().setResizingColumn(column);
|
||||||
|
column.setWidth(width[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JScrollPane valuesPane = new JScrollPane(table);
|
||||||
|
valuesPane.setBorder(BorderFactory.createTitledBorder("Values"));
|
||||||
|
|
||||||
|
this.add(metadataLabel, BorderLayout.NORTH);
|
||||||
|
this.add(valuesPane, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
}
|
35
Core/src/org/sleuthkit/autopsy/rejview/RejTreeNode.java
Normal file
35
Core/src/org/sleuthkit/autopsy/rejview/RejTreeNode.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RejTreeNode is the adaptor between the Registry structure model and the JTree model.
|
||||||
|
* It may describe both the contents of the node, and how it should be displayed.
|
||||||
|
*/
|
||||||
|
public interface RejTreeNode {
|
||||||
|
public abstract String toString();
|
||||||
|
public abstract boolean hasChildren();
|
||||||
|
public abstract List<RejTreeNode> getChildren();
|
||||||
|
public abstract RejTreeNodeView getView();
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
public class RejTreeNodeSelectionEvent {
|
||||||
|
private final RejTreeNode _node;
|
||||||
|
public RejTreeNodeSelectionEvent(RejTreeNode n) {
|
||||||
|
this._node = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RejTreeNode getNode() {
|
||||||
|
return this._node;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
public interface RejTreeNodeSelectionListener {
|
||||||
|
public abstract void nodeSelected(RejTreeNodeSelectionEvent e);
|
||||||
|
}
|
35
Core/src/org/sleuthkit/autopsy/rejview/RejTreeNodeView.java
Normal file
35
Core/src/org/sleuthkit/autopsy/rejview/RejTreeNodeView.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class RejTreeNodeView extends JPanel {
|
||||||
|
public RejTreeNodeView() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RejTreeNodeView(LayoutManager lm) {
|
||||||
|
super(lm);
|
||||||
|
}
|
||||||
|
}
|
75
Core/src/org/sleuthkit/autopsy/rejview/RejTreeValueNode.java
Normal file
75
Core/src/org/sleuthkit/autopsy/rejview/RejTreeValueNode.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryValue;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RejTreeValueNode implements RejTreeNode {
|
||||||
|
|
||||||
|
private final RegistryValue _value;
|
||||||
|
|
||||||
|
public RejTreeValueNode(RegistryValue value) {
|
||||||
|
this._value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
try {
|
||||||
|
String valueName = this._value.getName();
|
||||||
|
if (valueName == "") {
|
||||||
|
return "(Default)";
|
||||||
|
}
|
||||||
|
return valueName;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
System.err.println("Failed to parse _value name");
|
||||||
|
return "PARSE FAILED.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasChildren() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RejTreeNode> getChildren() {
|
||||||
|
return new LinkedList<RejTreeNode>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scope: package-protected
|
||||||
|
*/
|
||||||
|
RegistryValue getValue() {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO(wb): this isn't exactly MVC...
|
||||||
|
*/
|
||||||
|
public RejTreeNodeView getView() {
|
||||||
|
return new RejTreeValueView(this);
|
||||||
|
}
|
||||||
|
}
|
136
Core/src/org/sleuthkit/autopsy/rejview/RejTreeValueView.java
Normal file
136
Core/src/org/sleuthkit/autopsy/rejview/RejTreeValueView.java
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
|
import com.williballenthin.rejistry.ValueData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class RejTreeValueView extends RejTreeNodeView {
|
||||||
|
private final RejTreeValueNode _node;
|
||||||
|
|
||||||
|
public RejTreeValueView(RejTreeValueNode node) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this._node = node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param 1 Name
|
||||||
|
* @param 2 Type
|
||||||
|
*/
|
||||||
|
String metadataTemplate = "" +
|
||||||
|
"<html>" +
|
||||||
|
"<i>Name:</i> <b>%1$s</b><br/>" +
|
||||||
|
"<i>Type:</i> %2$s" +
|
||||||
|
"</html>";
|
||||||
|
String valueName;
|
||||||
|
String valueType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param 1 Value
|
||||||
|
*/
|
||||||
|
String valueTemplate = "" +
|
||||||
|
"<html>" +
|
||||||
|
"%1$s" +
|
||||||
|
"</html>";
|
||||||
|
try {
|
||||||
|
valueName = this._node.getValue().getName();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
valueName = "FAILED TO DECODE VALUE NAME";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
valueType = this._node.getValue().getValueType().toString();
|
||||||
|
} catch (RegistryParseException e ) {
|
||||||
|
valueType = "FAILED TO PARSE VALUE TYPE";
|
||||||
|
}
|
||||||
|
|
||||||
|
JLabel metadataLabel = new JLabel(String.format(metadataTemplate, valueName, valueType), JLabel.LEFT);
|
||||||
|
metadataLabel.setBorder(BorderFactory.createTitledBorder("Metadata"));
|
||||||
|
metadataLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
|
||||||
|
// this valueComponent must be set in the follow try/catch block.
|
||||||
|
JComponent valueComponent;
|
||||||
|
try {
|
||||||
|
ValueData data = this._node.getValue().getValue();
|
||||||
|
|
||||||
|
// the case statements are a bit repetitive, but i think make more sense than confusingly-nested if/elses
|
||||||
|
switch(data.getValueType()) {
|
||||||
|
case REG_SZ:
|
||||||
|
case REG_EXPAND_SZ: {
|
||||||
|
String valueValue = data.getAsString();
|
||||||
|
JLabel valueLabel = new JLabel(String.format(valueTemplate, valueValue), JLabel.LEFT);
|
||||||
|
valueLabel.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
valueComponent = valueLabel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REG_MULTI_SZ: {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String s : data.getAsStringList()) {
|
||||||
|
sb.append(s);
|
||||||
|
sb.append("<br />");
|
||||||
|
}
|
||||||
|
String valueValue = sb.toString();
|
||||||
|
JLabel valueLabel = new JLabel(String.format(valueTemplate, valueValue), JLabel.LEFT);
|
||||||
|
valueLabel.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
valueComponent = valueLabel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REG_DWORD:
|
||||||
|
case REG_QWORD:
|
||||||
|
case REG_BIG_ENDIAN: {
|
||||||
|
String valueValue = String.format("0x%x", data.getAsNumber());
|
||||||
|
JLabel valueLabel = new JLabel(String.format(valueTemplate, valueValue), JLabel.LEFT);
|
||||||
|
valueLabel.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
valueComponent = valueLabel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
HexView hexView = new HexView(data.getAsRawData());
|
||||||
|
hexView.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueComponent = hexView;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
JLabel valueLabel = new JLabel(String.format(valueTemplate, "FAILED TO PARSE VALUE VALUE"), JLabel.LEFT);
|
||||||
|
valueLabel.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
valueComponent = valueLabel;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
JLabel valueLabel = new JLabel(String.format(valueTemplate, "FAILED TO PARSE VALUE VALUE"), JLabel.LEFT);
|
||||||
|
valueLabel.setBorder(BorderFactory.createTitledBorder("Value"));
|
||||||
|
valueLabel.setVerticalAlignment(SwingConstants.TOP);
|
||||||
|
valueComponent = valueLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.add(metadataLabel, BorderLayout.NORTH);
|
||||||
|
this.add(new JScrollPane(valueComponent), BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
122
Core/src/org/sleuthkit/autopsy/rejview/RejTreeView.java
Normal file
122
Core/src/org/sleuthkit/autopsy/rejview/RejTreeView.java
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryHive;
|
||||||
|
import com.williballenthin.rejistry.RegistryParseException;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.TreeExpansionEvent;
|
||||||
|
import javax.swing.event.TreeExpansionListener;
|
||||||
|
import javax.swing.event.TreeSelectionEvent;
|
||||||
|
import javax.swing.event.TreeSelectionListener;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
|
public class RejTreeView extends JScrollPane implements TreeExpansionListener, TreeSelectionListener {
|
||||||
|
|
||||||
|
private final DefaultTreeModel _tree_model;
|
||||||
|
private JTree _tree;
|
||||||
|
private final RegistryHive _hive;
|
||||||
|
private final CopyOnWriteArrayList<RejTreeNodeSelectionListener> _nodeSelectionListeners;
|
||||||
|
|
||||||
|
public RejTreeView(RegistryHive hive) {
|
||||||
|
this._hive = hive;
|
||||||
|
DefaultMutableTreeNode rootNode;
|
||||||
|
this._nodeSelectionListeners = new CopyOnWriteArrayList<RejTreeNodeSelectionListener>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
rootNode = getTreeNode(new RejTreeKeyNode(this._hive.getRoot()));
|
||||||
|
} catch (RegistryParseException e) {
|
||||||
|
System.err.println("Failed to parse root key");
|
||||||
|
rootNode = new DefaultMutableTreeNode("PARSE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
this._tree_model = new DefaultTreeModel(rootNode);
|
||||||
|
this._tree_model.setAsksAllowsChildren(true);
|
||||||
|
|
||||||
|
this._tree = new JTree(this._tree_model);
|
||||||
|
this._tree.addTreeExpansionListener(this);
|
||||||
|
this._tree.addTreeSelectionListener(this);
|
||||||
|
|
||||||
|
// here's a bit of a hack to force the children to be loaded and shown
|
||||||
|
this._tree.collapsePath(new TreePath(rootNode.getPath()));
|
||||||
|
this._tree.expandPath(new TreePath(rootNode.getPath()));
|
||||||
|
|
||||||
|
setViewportView(this._tree);
|
||||||
|
setPreferredSize(new Dimension(250, 400));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTreeNode creates a TreeNode from a RejTreeNode, settings the appropriate fields.
|
||||||
|
*/
|
||||||
|
private DefaultMutableTreeNode getTreeNode(RejTreeNode node) {
|
||||||
|
DefaultMutableTreeNode ret;
|
||||||
|
ret = new DefaultMutableTreeNode(node);
|
||||||
|
ret.setAllowsChildren(node.hasChildren());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void treeExpanded(TreeExpansionEvent event) {
|
||||||
|
TreePath path = event.getPath();
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||||
|
|
||||||
|
if (node.getChildCount() == 0) {
|
||||||
|
RejTreeNode n = (RejTreeNode)node.getUserObject();
|
||||||
|
for (RejTreeNode rejTreeNode : n.getChildren()) {
|
||||||
|
node.add(getTreeNode(rejTreeNode));
|
||||||
|
}
|
||||||
|
this._tree_model.nodeStructureChanged(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void treeCollapsed(TreeExpansionEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void valueChanged(TreeSelectionEvent e) {
|
||||||
|
TreePath path = e.getPath();
|
||||||
|
System.out.println("Selected: " + path);
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||||
|
this.triggerRejTreeNodeSelection((RejTreeNode)node.getUserObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRejTreeNodeSelectionListener(RejTreeNodeSelectionListener l) {
|
||||||
|
this._nodeSelectionListeners.add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRejTreeNodeSelectionListener(RejTreeNodeSelectionListener l ) {
|
||||||
|
this._nodeSelectionListeners.remove(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerRejTreeNodeSelection(RejTreeNode n) {
|
||||||
|
RejTreeNodeSelectionEvent e = new RejTreeNodeSelectionEvent(n);
|
||||||
|
for (RejTreeNodeSelectionListener listener : this._nodeSelectionListeners) {
|
||||||
|
listener.nodeSelected(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
Core/src/org/sleuthkit/autopsy/rejview/RejView.java
Normal file
79
Core/src/org/sleuthkit/autopsy/rejview/RejView.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Copyright 2013 Willi Ballenthin
|
||||||
|
* Contact: willi.ballenthin <at> gmail <dot> com
|
||||||
|
*
|
||||||
|
* 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.rejview;
|
||||||
|
|
||||||
|
import com.williballenthin.rejistry.RegistryHive;
|
||||||
|
import com.williballenthin.rejistry.RegistryHiveBuffer;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class RejView extends JPanel implements RejTreeNodeSelectionListener {
|
||||||
|
|
||||||
|
private final RegistryHive _hive;
|
||||||
|
private final RejTreeView _tree_view;
|
||||||
|
private final JSplitPane _splitPane;
|
||||||
|
|
||||||
|
public RejView(RegistryHive hive) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this._hive = hive;
|
||||||
|
|
||||||
|
// have to do these cause they're final
|
||||||
|
this._tree_view = new RejTreeView(this._hive);
|
||||||
|
this._splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
|
||||||
|
this._tree_view, new JPanel());
|
||||||
|
|
||||||
|
this.setupUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RejView(ByteBuffer buf) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this._hive = new RegistryHiveBuffer(buf);
|
||||||
|
|
||||||
|
// have to do these cause they're final
|
||||||
|
this._tree_view = new RejTreeView(this._hive);
|
||||||
|
this._splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
|
||||||
|
this._tree_view, new JPanel());
|
||||||
|
|
||||||
|
this.setupUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupUI() {
|
||||||
|
this._splitPane.setResizeWeight(0);
|
||||||
|
this._splitPane.setOneTouchExpandable(true);
|
||||||
|
this._splitPane.setContinuousLayout(true);
|
||||||
|
|
||||||
|
this.add(this._splitPane, BorderLayout.CENTER);
|
||||||
|
this.setPreferredSize(new Dimension(800, 600));
|
||||||
|
|
||||||
|
this._tree_view.addRejTreeNodeSelectionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nodeSelected(RejTreeNodeSelectionEvent e) {
|
||||||
|
RejTreeNodeView v = e.getNode().getView();
|
||||||
|
int curDividerLocation = this._splitPane.getDividerLocation();
|
||||||
|
this._splitPane.setRightComponent(v);
|
||||||
|
this._splitPane.setDividerLocation(curDividerLocation);
|
||||||
|
}
|
||||||
|
}
|
BIN
thirdparty/rejView/RejView.jar
vendored
BIN
thirdparty/rejView/RejView.jar
vendored
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user