19 package org.sleuthkit.autopsy.corecomponents;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.util.logging.Level;
26 import org.openide.util.NbBundle;
28 import javax.swing.JMenuItem;
29 import javax.swing.JOptionPane;
30 import javax.swing.text.BadLocationException;
31 import javax.swing.text.Utilities;
32 import org.openide.nodes.Node;
33 import org.openide.util.lookup.ServiceProvider;
42 @SuppressWarnings(
"PMD.SingularField")
43 @ServiceProvider(service = DataContentViewer.class, position = 1)
46 private static final long pageLength = 16384;
47 private final byte[] data =
new byte[(int) pageLength];
48 private static int currentPage = 1;
59 customizeComponents();
60 this.resetComponent();
61 logger.log(Level.INFO,
"Created HexView instance: " +
this);
65 outputTextArea.setComponentPopupMenu(rightClickMenu);
66 ActionListener actList =
new ActionListener() {
68 public void actionPerformed(ActionEvent e) {
69 JMenuItem jmi = (JMenuItem) e.getSource();
70 if (jmi.equals(copyMenuItem)) {
71 outputTextArea.copy();
72 }
else if (jmi.equals(selectAllMenuItem)) {
73 outputTextArea.selectAll();
77 copyMenuItem.addActionListener(actList);
78 selectAllMenuItem.addActionListener(actList);
86 @SuppressWarnings(
"unchecked")
88 private
void initComponents() {
90 rightClickMenu =
new javax.swing.JPopupMenu();
91 copyMenuItem =
new javax.swing.JMenuItem();
92 selectAllMenuItem =
new javax.swing.JMenuItem();
93 jScrollPane3 =
new javax.swing.JScrollPane();
94 outputTextArea =
new javax.swing.JTextArea();
95 jScrollPane2 =
new javax.swing.JScrollPane();
96 hexViewerPanel =
new javax.swing.JPanel();
97 totalPageLabel =
new javax.swing.JLabel();
98 ofLabel =
new javax.swing.JLabel();
99 currentPageLabel =
new javax.swing.JLabel();
100 pageLabel =
new javax.swing.JLabel();
101 prevPageButton =
new javax.swing.JButton();
102 nextPageButton =
new javax.swing.JButton();
103 pageLabel2 =
new javax.swing.JLabel();
104 goToPageTextField =
new javax.swing.JTextField();
105 goToPageLabel =
new javax.swing.JLabel();
106 goToOffsetLabel =
new javax.swing.JLabel();
107 goToOffsetTextField =
new javax.swing.JTextField();
109 copyMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.copyMenuItem.text"));
110 rightClickMenu.add(copyMenuItem);
112 selectAllMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.selectAllMenuItem.text"));
113 rightClickMenu.add(selectAllMenuItem);
115 setPreferredSize(
new java.awt.Dimension(100, 58));
117 jScrollPane3.setPreferredSize(
new java.awt.Dimension(300, 33));
119 outputTextArea.setEditable(
false);
120 outputTextArea.setFont(
new java.awt.Font(
"Courier New", 0, 11));
121 outputTextArea.setTabSize(0);
122 outputTextArea.setInheritsPopupMenu(
true);
123 jScrollPane3.setViewportView(outputTextArea);
125 jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
126 jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
128 totalPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.totalPageLabel.text_1"));
130 ofLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.ofLabel.text_1"));
132 currentPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.currentPageLabel.text_1"));
133 currentPageLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
134 currentPageLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
136 pageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel.text_1"));
137 pageLabel.setMaximumSize(
new java.awt.Dimension(33, 14));
138 pageLabel.setMinimumSize(
new java.awt.Dimension(33, 14));
140 prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
141 prevPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.prevPageButton.text"));
142 prevPageButton.setBorderPainted(
false);
143 prevPageButton.setContentAreaFilled(
false);
144 prevPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
145 prevPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
146 prevPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
147 prevPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png")));
148 prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
149 public void actionPerformed(java.awt.event.ActionEvent evt) {
150 prevPageButtonActionPerformed(evt);
154 nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
155 nextPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.nextPageButton.text"));
156 nextPageButton.setBorderPainted(
false);
157 nextPageButton.setContentAreaFilled(
false);
158 nextPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
159 nextPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
160 nextPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
161 nextPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png")));
162 nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
163 public void actionPerformed(java.awt.event.ActionEvent evt) {
164 nextPageButtonActionPerformed(evt);
168 pageLabel2.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel2.text"));
169 pageLabel2.setMaximumSize(
new java.awt.Dimension(29, 14));
170 pageLabel2.setMinimumSize(
new java.awt.Dimension(29, 14));
172 goToPageTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageTextField.text"));
173 goToPageTextField.addActionListener(
new java.awt.event.ActionListener() {
174 public void actionPerformed(java.awt.event.ActionEvent evt) {
175 goToPageTextFieldActionPerformed(evt);
179 goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageLabel.text"));
181 goToOffsetLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetLabel.text"));
183 goToOffsetTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetTextField.text"));
184 goToOffsetTextField.addActionListener(
new java.awt.event.ActionListener() {
185 public void actionPerformed(java.awt.event.ActionEvent evt) {
186 goToOffsetTextFieldActionPerformed(evt);
190 javax.swing.GroupLayout hexViewerPanelLayout =
new javax.swing.GroupLayout(hexViewerPanel);
191 hexViewerPanel.setLayout(hexViewerPanelLayout);
192 hexViewerPanelLayout.setHorizontalGroup(
193 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
194 .addGroup(hexViewerPanelLayout.createSequentialGroup()
196 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
198 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
199 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
200 .addComponent(ofLabel)
201 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
202 .addComponent(totalPageLabel)
204 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
205 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
206 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
208 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
210 .addComponent(goToPageLabel)
211 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
212 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
214 .addComponent(goToOffsetLabel)
215 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
216 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
217 .addContainerGap(32, Short.MAX_VALUE))
219 hexViewerPanelLayout.setVerticalGroup(
220 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
221 .addGroup(hexViewerPanelLayout.createSequentialGroup()
222 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
223 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
224 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
225 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
226 .addComponent(ofLabel)
227 .addComponent(totalPageLabel))
228 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
229 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
230 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
231 .addComponent(goToPageLabel)
232 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
233 .addComponent(goToOffsetLabel)
234 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
238 jScrollPane2.setViewportView(hexViewerPanel);
240 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
241 this.setLayout(layout);
242 layout.setHorizontalGroup(
243 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
244 .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
245 .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
247 layout.setVerticalGroup(
248 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
249 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
250 .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
251 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
252 .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE))
257 setDataViewByPageNumber(currentPage - 1);
258 goToPageTextField.setText(Integer.toString(currentPage));
262 setDataViewByPageNumber(currentPage + 1);
263 goToPageTextField.setText(Integer.toString(currentPage));
267 String pageNumberStr = goToPageTextField.getText();
271 pageNumber = Integer.parseInt(pageNumberStr);
272 }
catch (NumberFormatException ex) {
273 pageNumber = totalPages + 1;
275 if (pageNumber > totalPages || pageNumber < 1) {
276 JOptionPane.showMessageDialog(
this,
277 NbBundle.getMessage(
this.getClass(),
278 "DataContentViewerHex.goToPageTextField.msgDlg",
280 NbBundle.getMessage(
this.getClass(),
281 "DataContentViewerHex.goToPageTextField.err"),
282 JOptionPane.WARNING_MESSAGE);
285 setDataViewByPageNumber(pageNumber);
299 String userSelectedLine;
302 userSelectedLine = outputTextArea.getText().subSequence(
303 Utilities.getRowStart(outputTextArea, outputTextArea.getCaretPosition()),
304 Utilities.getRowEnd(outputTextArea, outputTextArea.getCaretPosition()))
307 String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(
":"));
309 return Long.decode(hexForUserSelectedLine) + userInput;
310 }
catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
319 if (goToOffsetTextField.getText().startsWith(
"+") || goToOffsetTextField.getText().startsWith(
"-")) {
320 offset = getOffsetRelativeToCaretPosition(Long.decode(goToOffsetTextField.getText()));
322 offset = Long.decode(goToOffsetTextField.getText());
324 }
catch (NumberFormatException ex) {
326 JOptionPane.showMessageDialog(
this, NbBundle.getMessage(
this.getClass(),
"DataContentViewerHex.goToOffsetTextField.msgDlg", goToOffsetTextField.getText()));
331 setDataViewByOffset(offset);
333 outputTextArea.setText(NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
364 if (this.dataSource == null) {
371 long offset = (currentPage - 1) * pageLength;
373 goToOffsetTextField.setText(Long.toString(offset));
382 if (this.dataSource == null) {
385 currentPage = (int) (offset / pageLength) + 1;
387 goToPageTextField.setText(Integer.toString(currentPage));
392 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
394 String errorText = null;
397 if (dataSource.getSize() > 0) {
399 bytesRead = dataSource.read(data, offset, pageLength);
400 }
catch (TskException ex) {
401 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
402 offset + pageLength);
403 logger.log(Level.WARNING,
"Error while trying to show the hex content.", ex);
408 if (bytesRead <= 0) {
409 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
410 offset + pageLength);
414 if ((errorText == null) && (currentPage < totalPages)) {
415 nextPageButton.setEnabled(
true);
417 nextPageButton.setEnabled(
false);
420 if ((errorText == null) && (currentPage > 1)) {
421 prevPageButton.setEnabled(
true);
423 prevPageButton.setEnabled(
false);
426 currentPageLabel.setText(Integer.toString(currentPage));
427 setComponentsVisibility(
true);
430 if (errorText == null) {
431 int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
434 outputTextArea.setText(errorText);
437 outputTextArea.setCaretPosition(0);
438 this.setCursor(null);
443 if ((selectedNode == null) || (!isSupported(selectedNode))) {
448 Content content = DataContentViewerUtility.getDefaultContent(selectedNode);
449 if (content == null) {
454 dataSource = content;
456 if (dataSource.getSize() > 0) {
457 totalPages = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
459 totalPageLabel.setText(Integer.toString(totalPages));
461 this.setDataViewByPageNumber(1);
466 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.title");
471 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.toolTip");
483 this.dataSource = null;
484 currentPageLabel.setText(
"");
485 totalPageLabel.setText(
"");
486 outputTextArea.setText(
"");
487 setComponentsVisibility(
false);
496 currentPageLabel.setVisible(isVisible);
497 totalPageLabel.setVisible(isVisible);
498 ofLabel.setVisible(isVisible);
499 prevPageButton.setVisible(isVisible);
500 nextPageButton.setVisible(isVisible);
501 pageLabel.setVisible(isVisible);
502 pageLabel2.setVisible(isVisible);
503 goToPageTextField.setVisible(isVisible);
504 goToPageLabel.setVisible(isVisible);
505 goToOffsetTextField.setVisible(isVisible);
506 goToOffsetLabel.setVisible(isVisible);
514 Content content = node.getLookup().lookup(Content.class);
515 if (content != null && content.getSize() > 0) {
536 if (evt.isPopupTrigger()) {
537 rightClickMenu.setLocation(evt.getLocationOnScreen());
538 rightClickMenu.setVisible(
true);
539 copyMenuItem.setEnabled(outputTextArea.getSelectedText() != null);
541 rightClickMenu.setVisible(
false);
javax.swing.JScrollPane jScrollPane2
void setNode(Node selectedNode)
javax.swing.JLabel currentPageLabel
javax.swing.JPopupMenu rightClickMenu
void setComponentsVisibility(boolean isVisible)
javax.swing.JButton prevPageButton
int isPreferred(Node node)
javax.swing.JTextField goToOffsetTextField
javax.swing.JLabel goToPageLabel
void setDataView(long offset)
void maybeShowPopup(java.awt.event.MouseEvent evt)
javax.swing.JTextField goToPageTextField
void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt)
boolean isSupported(Node node)
javax.swing.JMenuItem copyMenuItem
long getOffsetRelativeToCaretPosition(Long userInput)
void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt)
void setDataViewByOffset(long offset)
static String byteArrayToHex(byte[] array, int length, long arrayOffset, Font font)
javax.swing.JPanel hexViewerPanel
void setDataViewByPageNumber(int page)
javax.swing.JTextArea outputTextArea
javax.swing.JButton nextPageButton
javax.swing.JMenuItem selectAllMenuItem
synchronized static Logger getLogger(String name)
javax.swing.JLabel goToOffsetLabel
javax.swing.JLabel ofLabel
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel totalPageLabel
javax.swing.JLabel pageLabel2
javax.swing.JScrollPane jScrollPane3
javax.swing.JLabel pageLabel
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)
DataContentViewer createInstance()
void customizeComponents()